# Copyright (C) 2023 Caqui - All Rights Reserved
# You may use, distribute and modify this code under the
# terms of the MIT license.
# Visit: https://github.com/douglasdcm/caqui

import json
import subprocess
import time
import urllib.request
from typing import List

import requests

from caqui.constants import TIMEOUT
from caqui.exceptions import ServerError

WS_URL = "http://127.0.0.1"
PORT = 9222


class LocalServerCDP:
    def __init__(self, port=PORT, headless=True):
        self._port = port
        self._process = None
        self._headless = headless
        self._flags = [
            f"--remote-debugging-port={self._port}",
            f"--user-data-dir=/tmp/cdp-profile-{self._port}",
            "--no-first-run",
            "--no-default-browser-check",
            "--no-zygote",
            "--no-sandbox",
            "about:blank",
            f"--remote-allow-origins={WS_URL}:{self._port}",
        ]

    @property
    def port(self):
        return self._port

    @property
    def ws_url(self):
        return self.get_ws_url()

    def override_browser_flags(self, flags: List):
        """Inform a list of flags to be passed to the browser. For example [--no-first-run]"""
        self._flags = flags

    def start_chrome(self):
        self._start_browser("google-chrome")

    def start_opera(self):
        self._start_browser("opera")

    def start_edge(self):
        return self._start_browser("microsoft-edge")

    def _start_browser(self, browser):
        self._flags.insert(0, browser)
        if self._headless:
            self._flags.append("--headless")
        self._process = subprocess.Popen(
            self._flags,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            start_new_session=True,
        )
        if self._process is None:
            raise ServerError("Not able to start the server.")
        self._wait_server()

    def _wait_server(self) -> None:
        MAX_RETIES: int = 10
        for i in range(MAX_RETIES):
            try:
                requests.get(f"{WS_URL}:{self._port}", timeout=TIMEOUT)
                break
            except requests.exceptions.ConnectionError:
                time.sleep(0.5)
                if i == (MAX_RETIES - 1) and self._process:
                    self._process.kill()
                    self._process.wait()
                    raise Exception("Driver not started")

    def dispose(self, delay=0):
        if delay:
            time.sleep(delay)
        if self._process:
            self._process.kill()
            self._process.wait()
            self._process = None

    def get_ws_url(self):
        return get_ws_url(self._port)


def get_ws_url(port=PORT):
    with urllib.request.urlopen(f"{WS_URL}:{port}/json") as r:
        targets = json.loads(r.read())
        return targets[0]["webSocketDebuggerUrl"]
