#!/usr/bin/env python3

import argparse
import http.server
import socketserver
import logging
import pprint

#__name__ = "python-web-server"
__version__ = (1, 1, 1)

# setting up logging for this script
_level = logging.INFO
_format = "%(asctime)-15s [%(levelname)-8s] %(lineno)d : %(funcName)s : %(message)s"
logging.basicConfig(format=_format, level=_level)
log = logging.getLogger()


class SimpleHandler(http.server.BaseHTTPRequestHandler):

    def do_HEAD(self):
        log.info(f"server version: {self.server_version}")
        log.info(f"client address: {self.client_address}")
        log.info(f"path: {self.path}")
        log.info(f"headers: {self.headers}")
        log.info(f"request version: {self.request_version}")

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()

        headers = "\n".join([f"{k}: {v}" for k, v in self.headers.items()])

        if self.path != '/':
            uri = f"{self.path[1:]} "
        else:
            uri = ""

        message = f"""Hello, {uri}World!
                      App version: {__version__}
                      Server version: {self.server_version}
                      Client address: {self.client_address}
                      Path: {self.path}
                      Headers:
                      {pprint.pformat(self.headers)}
                      Request version: {self.request_version}
                   """

        self.wfile.write(bytes(message, encoding='utf-8'))
        return

    def do_GET(self):
        log.info(f"server version: {self.server_version}")
        log.info(f"client address: {self.client_address}")
        log.info(f"path: {self.path}")
        log.info(f"headers: {self.headers}")
        log.info(f"request version: {self.request_version}")

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()

        headers = "<br/>".join([f"{k}: {v}" for k, v in self.headers.items()])

        if self.path != '/':
            uri = f"{self.path[1:]} "
        else:
            uri = ""

        message = f"""<html><body>
                      <h1>Hello, {uri}World!</h1>
                      <p>App version: <b>{__version__}</b></p>
                      <p>Server version: <b>{self.server_version}</b></p>
                      <p>Client address: <b>{self.client_address}</b></p>
                      <p>Path: <b>{self.path}</b></p>
                      <p>Headers:</p> <p><code>{pprint.pformat(self.headers)}</code></p>
                      <p>Request version: <b>{self.request_version}</b></p>
                      </body></html>"""

        self.wfile.write(bytes(message, encoding='utf-8'))
        return

class SockHandler(socketserver.BaseRequestHandler):

    def handle(self):
        self.data = self.request.recv(1024).strip()
        log.info(f"client address: {self.client_address}")
        log.info(f"received data:\n{self.data}")
        self.request.sendall(b"Hello, World!\n")


def _version(ver=__version__):
    """
    Stringify version value
    """
    return f"{ver[0]}.{ver[1]}.{ver[2]}"


def parse_args():
    """
    Parse args
    """
    argp = argparse.ArgumentParser()
    argp.add_argument('-i', '--ip-address', default="", help="IP Address to bind the server")
    argp.add_argument('-p', '--port', type=int, default=8080, help="Port on which to listen for traffic")
    argp.add_argument('-v', '--version', action='version', version=f"%(prog)s {_version()}", help="Print version")
    argp.add_argument('-d', '--debug', help="Run in debug mode")
    return argp.parse_args()


if __name__ == "__main__":
    args = parse_args()

    if args.debug:
        log.setLevel(logging.DEBUG)

    try:
        #simple_handler = SimpleHandler()  # http.server.SimpleHTTPRequestHandler  

        with http.server.HTTPServer((args.ip_address, args.port), SimpleHandler) as httpd:
            log.info(f"Server started on {args.ip_address}:{args.port}")
            httpd.serve_forever()

        #with socketserver.TCPServer((args.ip_address, args.port), SockHandler) as tcpd:
        #    log.info(f"Server started on {args.ip_address}:{args.port}")
        #    tcpd.serve_forever()

    except KeyboardInterrupt as control_c:
        log.info("Server stopped")