#!/usr/bin/env python3

import base64
import http.server
import json
import os
import random
import socketserver
import ssl
import threading

HTTP_PORT   = int(os.environ.get('HTTP_PORT', 8080))
HTTPS_PORT  = int(os.environ.get('HTTPS_PORT', 8181))
MGMT_PORT   = int(os.environ.get('MGMT_PORT', 8282))
CREDENTIALS = base64.b64encode(os.environ.get('CREDENTIALS', '').encode('UTF'))
CERTIFICATE = os.environ.get('CERTIFICATE_PATH', '/etc/ssl/certs/dummy.crt').encode('UTF')

class HTTPHandler(http.server.BaseHTTPRequestHandler):

    def do_GET(self):
        if self.path == '/fail':
            self.send_response(self._generateRandomCode())
        elif ( len(CREDENTIALS) > 0 ):
            if self._checkAuth():
                self.send_response(200)
            else:
                self.send_response(401)
                self.send_header('WWW-Authenticate', 'Test')
        else:
            self.send_response(200)

        self.send_header('Content-type','application/json')
        self.end_headers()

        self._register()
        return

    def do_POST(self):
        body = ''

        if self.path == '/fail':
            self.send_response(self._generateRandomCode())
        elif ( len(CREDENTIALS) > 0 and not self._checkAuth() ):
            self.send_response(401)
            self.send_header('WWW-Authenticate', 'Test')
        else:
            try:
                if 'content-length' in self.headers:
                    length = int(self.headers['content-length'])
                    body = str(self.rfile.read(length), "utf-8") if length > 0 else ''
                json.loads(body)
                self.send_response(200)
            except:
                self.send_response(400)

        self.send_header('Content-type','application/json')
        self.end_headers()

        self._register(body)
        return

    def _register(self, body=''):
        with lock:
            if self.path not in DummyHandler._stats:
                DummyHandler._stats[self.path] = 0
            DummyHandler._stats[self.path] += 1
            DummyHandler._history.append({
                'path': self.path,
                'verb':self.command ,
                'body': body,
                'headers': [{h: self.headers[h]} for h in self.headers ]
            })

    def _generateRandomCode(self):
        return random.choice(list(range(402, 418))+list(range(500, 505)))

    def _checkAuth(self):
        try:
            credentials = self.headers['Authorization']
            expected = 'Basic ' + CREDENTIALS.decode('UTF')
            print("Matching {} with {}".format(credentials, expected))
            return credentials == expected
        except:
            print("No Authorization header present")
            return False

class DummyHandler(http.server.BaseHTTPRequestHandler):

    _stats = {}
    _history = []

    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type','application/json')
        self.end_headers()

        if self.path == '/stats':
            self.wfile.write(json.dumps(self._getStats()).encode('UTF-8'))
        elif self.path == '/history':
            self.wfile.write(json.dumps(self._getHistory()).encode('UTF-8'))
        elif self.path == '/clear':
            self._clear()

        return

    def _clear(self):
        with lock:
            DummyHandler._stats = {}
            DummyHandler._history = []

    def _getStats(self):
        with lock:
            return DummyHandler._stats

    def _getHistory(self):
        with lock:
            return DummyHandler._history

class ThreadedHTTPServer(socketserver.ThreadingMixIn, http.server.HTTPServer):
    """Handle requests in a separate thread."""

def serve_forever(server):
    server.serve_forever()

if __name__ == "__main__":
    global lock
    lock = threading.Lock()

    # Create HTTP Endpoint
    http_server = ThreadedHTTPServer(("", HTTP_PORT), HTTPHandler)
    print("Serving HTTP server on port: {}".format(HTTP_PORT))
    http_thread = threading.Thread(target=serve_forever, args=[http_server])
    http_thread.setDaemon(True)
    http_thread.start()

    # Create HTTPS Endpoint
    https_server = ThreadedHTTPServer(("", HTTPS_PORT), HTTPHandler)
    context = ssl.create_default_context(purpose=ssl.Purpose.CLIENT_AUTH)
    context.load_cert_chain(certfile=CERTIFICATE)
    https_server.socket = context.wrap_socket (https_server.socket, server_side=True)
    print("Serving HTTPS server on port: {}".format(HTTPS_PORT))
    https_thread = threading.Thread(target=serve_forever, args=[https_server])
    https_thread.setDaemon(True)
    https_thread.start()

    # Create Management Endpoint
    mgmt_server = ThreadedHTTPServer(("", MGMT_PORT), DummyHandler)
    print("Serving DUMMY server on port: {}".format(MGMT_PORT))
    serve_forever(mgmt_server)