import sys, json, urllib.parse, psutil
from http.server import HTTPServer, BaseHTTPRequestHandler
from torrent_downloader import TorrentDownloader
from profile_image_processor import ProfileImageProcessor

torrent_port = sys.argv[1]
http_port = sys.argv[2]
rpc_password = sys.argv[3]
start_download_payload = sys.argv[4]

torrent_downloader = None

if start_download_payload:
    initial_download = json.loads(urllib.parse.unquote(start_download_payload))
    torrent_downloader = TorrentDownloader(torrent_port)
    torrent_downloader.start_download(initial_download['game_id'], initial_download['magnet'], initial_download['save_path'])

class Handler(BaseHTTPRequestHandler):
    rpc_password_header = 'x-hydra-rpc-password'

    skip_log_routes = [
        "process-list",
        "status"
    ]

    def log_error(self, format, *args):
        sys.stderr.write("%s - - [%s] %s\n" %
                         (self.address_string(),
                          self.log_date_time_string(),
                          format%args))

    def log_message(self, format, *args):
        for route in self.skip_log_routes:
            if route in args[0]: return

        super().log_message(format, *args)
        
    def do_GET(self):
        if self.path == "/status":
            if self.headers.get(self.rpc_password_header) != rpc_password:
                self.send_response(401)
                self.end_headers()
                return

            self.send_response(200)
            self.send_header("Content-type", "application/json")
            self.end_headers()

            status = torrent_downloader.get_download_status()

            self.wfile.write(json.dumps(status).encode('utf-8'))

        elif self.path == "/healthcheck":
            self.send_response(200)
            self.end_headers()
        
        elif self.path == "/process-list":
            if self.headers.get(self.rpc_password_header) != rpc_password:
                self.send_response(401)
                self.end_headers()
                return
            
            process_list = [proc.info for proc in psutil.process_iter(['exe', 'pid', 'name'])]

            self.send_response(200)
            self.send_header("Content-type", "application/json")
            self.end_headers()

            self.wfile.write(json.dumps(process_list).encode('utf-8'))
    
    def do_POST(self):
        global torrent_downloader

        if self.headers.get(self.rpc_password_header) != rpc_password:
            self.send_response(401)
            self.end_headers()
            return

        content_length = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_length)
        data = json.loads(post_data.decode('utf-8'))

        if self.path == "/profile-image":
            parsed_image_path = data['image_path']
            
            try:
                parsed_image_path, mime_type = ProfileImageProcessor.process_image(parsed_image_path)
                self.send_response(200)
                self.send_header("Content-type", "application/json")
                self.end_headers()
                
                self.wfile.write(json.dumps({'imagePath': parsed_image_path, 'mimeType': mime_type}).encode('utf-8'))
            except:
                self.send_response(400)
                self.end_headers()

        elif self.path == "/action":
            if torrent_downloader is None:
                torrent_downloader = TorrentDownloader(torrent_port)

            if data['action'] == 'start':
                torrent_downloader.start_download(data['game_id'], data['magnet'], data['save_path'])
            elif data['action'] == 'pause':
                torrent_downloader.pause_download(data['game_id'])
            elif data['action'] == 'cancel':
                torrent_downloader.cancel_download(data['game_id'])
            elif data['action'] == 'kill-torrent':
                torrent_downloader.abort_session()
                torrent_downloader = None

            self.send_response(200)
            self.end_headers()

        else:
            self.send_response(404)
            self.end_headers()


if __name__ == "__main__":
    httpd = HTTPServer(("", int(http_port)), Handler)
    httpd.serve_forever()
