# -*- coding: utf-8 -*-
"""Localhost-only MPEG-TS relay. Stream URLs never appear in local playback URLs."""
import json
import secrets
import threading
import time
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from urllib.request import Request, urlopen

HOST = '127.0.0.1'
PORT = 18877
_lock = threading.Lock()
_streams = {}

class RelayServer(ThreadingHTTPServer):
    daemon_threads = True
    allow_reuse_address = True

class Handler(BaseHTTPRequestHandler):
    protocol_version = 'HTTP/1.0'

    def log_message(self, fmt, *args):
        pass  # Avoid logging stream URLs, provider credentials or tokens.

    def do_POST(self):
        if self.path != '/register':
            self.send_error(404)
            return
        try:
            length = int(self.headers.get('Content-Length', '0'))
            if length < 1 or length > 16384:
                self.send_error(400)
                return
            payload = json.loads(self.rfile.read(length))
            url = payload.get('url', '')
            if not isinstance(url, str) or not url.startswith(('http://', 'https://')):
                self.send_error(400)
                return
            token = secrets.token_urlsafe(18)
            with _lock:
                now = time.monotonic()
                for k, (_, created) in list(_streams.items()):
                    if now - created > 3600:
                        del _streams[k]
                _streams[token] = (url, now)
            data = json.dumps({'path': '/live/' + token + '.ts'}).encode('utf-8')
            self.send_response(200)
            self.send_header('Content-Type', 'application/json')
            self.send_header('Content-Length', str(len(data)))
            self.end_headers()
            self.wfile.write(data)
        except (ValueError, TypeError, KeyError):
            self.send_error(400)

    def do_HEAD(self):
        self._stream(head_only=True)

    def do_GET(self):
        self._stream(head_only=False)

    def _stream(self, head_only):
        if not self.path.startswith('/live/') or not self.path.endswith('.ts'):
            self.send_error(404)
            return
        token = self.path[len('/live/'):-3]
        with _lock:
            entry = _streams.get(token)
        if entry is None:
            self.send_error(404)
            return
        if head_only:
            self.send_response(200)
            self.send_header('Content-Type', 'video/mp2t')
            self.end_headers()
            return
        try:
            request = Request(entry[0], headers={'User-Agent': 'Wget'})
            with urlopen(request, timeout=15) as upstream:
                self.send_response(200)
                self.send_header('Content-Type', 'video/mp2t')
                self.send_header('Cache-Control', 'no-cache')
                self.end_headers()
                while True:
                    chunk = upstream.read(65536)
                    if not chunk:
                        break
                    self.wfile.write(chunk)
        except (BrokenPipeError, ConnectionResetError):
            pass
        except Exception as exc:
            try:
                import xbmc
                xbmc.log('KodiFlix Live relay upstream error: {}'.format(type(exc).__name__), xbmc.LOGWARNING)
            except Exception:
                pass

def start():
    server = RelayServer((HOST, PORT), Handler)
    thread = threading.Thread(target=server.serve_forever, daemon=True)
    thread.start()
    return server
