#!/usr/bin/env python3

import argparse
import os
import shutil
import re
import sys
import signal
import subprocess

from http.server import SimpleHTTPRequestHandler

import webbrowser
import socketserver

from subprocess import PIPE, Popen
from typing import List, Tuple

from urllib.parse import unquote

www_dir_path = None
httpd = None
default_port = 8080


class WebServerHandler(SimpleHTTPRequestHandler):

    def __init__(self, *args, **kwargs):
        super().__init__(
            *args, directory=os.path.realpath(www_dir_path, **kwargs)
        )

    def log_message(self, format, *args):
        pass

    def do_GET(self):
        super().do_GET()

    def do_POST(self):
        try:

            self.send_response(200)
            # self.send_header('Location', self.path)
            self.end_headers()

            content_len = int(self.headers.get('content-length', 0))
            post_body = unquote(self.rfile.read(content_len)).split("&")

            # with open("post.txt","a") as f:
            #     f.write(str(post_body))
            #     f.write("\n")

            commit_hash = post_body[0].split("=")[1]
            kicad_pro_path = post_body[1].split("=")[1]

            cmd = "kicad_rev {}".format(kicad_pro_path)
            print("Cmd:", cmd)
            process = subprocess.Popen(cmd.split(" "), stdout=subprocess.PIPE, stderr=subprocess.PIPE)

            # self._set_response()
            # self.wfile.write("POST request for {}".format(self.path).encode('utf-8'))

        except:
            pass

def signal_handler(sig, frame):
    httpd.server_close()
    sys.exit(0)


def parse_cli_args():
    parser = argparse.ArgumentParser(description="Kicad PCB visual diffs.")
    parser.add_argument(
        "-d", "--display", type=str, help="Set DISPLAY value, default :1.0", default=":1.0",
    )
    parser.add_argument(
        "-n", "--nested", action='store_true', help="Fix paths when it was a nested project"
    )
    parser.add_argument(
        "-p", "--port", type=int, help="Force the weverver on an specific port"
    )
    parser.add_argument(
        "-r", "--port_range", type=int, default=10, help="Port range to try"
    )
    parser.add_argument(
        "-S", "--server-only", action='store_true', help="Port range to try"
    )
    parser.add_argument(
        "-w",
        "--webserver-disable",
        action="store_true",
        help="Does not execute webserver (just generate images)",
    )
    parser.add_argument(
        "-v", "--verbose", action="count", default=0, help="Increase verbosity (-vvv)"
    )
    parser.add_argument(
        "-i", "--ip", type=str, help="Override default IP address", default="127.0.0.1",
    )
    parser.add_argument(
        "www_dir", metavar="WWW_DIR", help="A folder with web/index.html inside"
    )

    args = parser.parse_args()

    if args.verbose >= 3:
        print("")
        print("Command Line Arguments")
        print(args)

    return args


def launch_webserver(ip, request_handler, port, kicad_project, server_only):

    global httpd
    httpd = socketserver.TCPServer(("", port), request_handler)

    with httpd:
        if args.nested:
            url = "{ip}:{port}/{nested_project}/web/index.html".format(
                ip=ip,
                port=str(port),
                nested_project=kicad_project
            )
        else:
            url = "http://{ip}:{port}/web/index.html".format(
                ip=ip,
                port=str(port)
            )

        print("")
        print("Starting webserver at {}".format(url))
        print("(Hit Ctrl+C to exit)")
        if not server_only:
            webbrowser.open(url)
        httpd.serve_forever()


def run_cmd(path: str, cmd: List[str]) -> Tuple[str, str]:

    p = Popen(
        cmd,
        stdin=PIPE,
        stdout=PIPE,
        stderr=PIPE,
        close_fds=True,
        encoding="utf-8",
        cwd=path,
    )

    stdout, stderr = p.communicate()
    p.wait()

    return stdout.strip("\n "), stderr


if __name__ == "__main__":

    signal.signal(signal.SIGINT, signal_handler)
    args = parse_cli_args()

    if args.www_dir:

        www_dir_path = os.path.abspath(args.www_dir)
        kicad_project = ".."

        # Assume it is running outside of the webserver the folder
        index_html = os.path.realpath(os.path.join(www_dir_path, "web", "index.html"))
        if not os.path.exists(index_html):
            print("Could not find index.html")
            exit(1)

        if args.verbose:
            print("")
            print("www_dir_path:", www_dir_path)
            print("kicad_project:", kicad_project)
            print("index_html:", index_html)
            print("")

    else:
        print("www directory is missing")
        exit(1)

    if not args.webserver_disable:

        socketserver.TCPServer.allow_reuse_address = True
        request_handler = WebServerHandler

    if args.port:
        try:
            launch_webserver(args.ip, request_handler, args.port, kicad_project, args.server_only)
        except Exception:
            print("Specified port {port} is in use".format(port=port))
            pass
    else:
        for i in range(args.port_range):
            try:
                port = default_port + i
                launch_webserver(args.ip, request_handler, port, kicad_project, args.server_only)
            except Exception:
                # print("Specified port {port} is in use".format(port=port))
                pass
        print("Specified ports are in use.")
