from .browser import Browser
from .search_utils import find_firefox

import os
import subprocess

import requests
import json
from websocket import create_connection
import base64


class FirefoxCDP(Browser):
    def __init__(self, executable=None, flags=None, print_command=False):
        self.executable = executable
        if not flags:
            self.flags = [
                # '--default-background-color=0',
                # '--hide-scrollbars',
            ]
        else:
            self.flags = [flags] if isinstance(flags, str) else flags

        self.print_command = print_command

        self.ws = None  # Websocket connection
        self.proc = None  # Headless browser Popen object

        self.__id = 0

    @property
    def executable(self):
        return self._executable

    @executable.setter
    def executable(self, value):
        self._executable = find_firefox(value)

    @property
    def _id(self):
        self.__id += 1
        return self.__id

    def cdp_send(self, method, **params):
        """
        """
        return self.ws.send(
            json.dumps({
                'id': self._id,
                'method': method,
                'params': params,
            })
        )

    def screenshot(
        self,
        input,
        output_path,
        output_file='screenshot.png',
        size=(1920, 1080),
    ):
        """
        """
        # Useful documentation about the Chrome DevTools Protocol:
        # https://chromedevtools.github.io/devtools-protocol/

        # enabling the page allow to receive the Page.loadEventFired event
        self.cdp_send('Page.enable')
        print(self.ws.recv())
        
        self.cdp_send('Page.navigate', url=input)
        print('Navigated to:', input)

        # wait for page to load entirely
        while True:
            print('Waiting for page to load...')
            message = json.loads(self.ws.recv())
            print(message)
            if message.get('method') == 'Page.loadEventFired':
                break
        
        print('Page loaded.')

        self.cdp_send('Page.disable')
        self.cdp_send(
            'Emulation.setDeviceMetricsOverride',
            width=size[0],
            height=size[1],
            deviceScaleFactor=0,  # 0 disables the override
            mobile=False,
        )
        self.cdp_send('Page.captureScreenshot')

        # get screenshot data when ready,
        # while potentially skipping unneeded messages
        while True:
            message = json.loads(self.ws.recv())
            if 'result' in message and 'data' in message['result']:
                # retrive base64 encoded image data
                img_data = message['result']['data']
                break

        # decode and write image data to file
        with open(os.path.join(output_path, output_file), 'wb') as f:
            f.write(base64.b64decode(img_data))

    def __enter__(self):
        """
        """
        print('Entering context. (ChromeHeadlessServer)')

        temp_dir = os.environ['TMP'] if os.name == 'nt' else '/tmp'
        temp_dir = os.path.join(temp_dir, 'firefox-html2image-profile')

        # create a user.js file that overrides Firefox's default config
        # http://kb.mozillazine.org/User.js_file
        os.makedirs(temp_dir, exist_ok=True)
        with open(os.path.join(temp_dir, 'user.js'), 'w') as f:
            f.write(
                '// File generated by html2image\n'
                'user_pref("devtools.chrome.enabled", true);\n'
                'user_pref("devtools.debugger.prompt-connection", false);\n'
                'user_pref("devtools.debugger.remote-enabled", true);\n'
                '\n'
                '// https://bugzilla.mozilla.org/show_bug.cgi?id=1746154#c4 \n'
                'user_pref("fission.bfcacheInParent", false);\n'
                'user_pref("fission.webContentIsolationStrategy", 0);\n'
            )

        command = [
            f'{self.executable}',
            # '--headless',
            *self.flags,
            '--profile', temp_dir,
            '--new-instance',
            '--remote-debugging-port=9223',
            # 'about:home',
            # browser.newtabpage.activity-stream.asrouter.providers.onboarding
        ]

        if self.print_command or True:
            print(' '.join(command))

        self.proc = subprocess.Popen(command)

        r = requests.get('http://localhost:9223/json/list')

        self.ws = create_connection(
            r.json()[0]['webSocketDebuggerUrl'],

            # Firefox 97.0 requires an empty origin header
            suppress_origin=True,
        )
        # except ConnectionRefusedError as e:
        #     # devtools.chrome.enabled true
        #     # devtools.debugger.prompt-connection false
        #     # devtools.debugger.remote-enabled true
        #     print('Could not connect to Firefox cdp instance.')

    def __exit__(self, *exc):
        """
        """
        print(f'Exiting context. (ChromeHeadlessServer), {exc}')

        self.cdp_send('Browser.close')
        self.ws.close()
        self.proc.terminate()  # ensure that the process is terminated
