import os
import xbmc
import base64
import threading

from xbmc import Monitor
from six.moves import urllib_request

from elementum.addon import ADDON, ADDON_ID
from elementum.daemon import shutdown
from elementum.logger import log
from elementum.config import init, ELEMENTUMD_HOST, ONLY_CLIENT
from kodi_six.utils import PY2


class ElementumMonitor(Monitor):
    # List of properties that we check to understand if change of settings should be ignored
    monitored = ['trakt_token', 'trakt_refresh_token', 'trakt_token_expiry', 'opensubtitles_token', 'opensubtitles_token_expiry']
    current_properties = {}

    opener = urllib_request.build_opener()
    opener.addheaders = [('User-Agent', ADDON_ID)]

    login = ADDON.getSetting("remote_login")
    password = ADDON.getSetting("remote_password")
    if login or password:
        log.debug("Setting auth to %s:%s" % (login, password))
        base64string = base64.b64encode('{}:{}'.format(login, password).encode())
        opener.addheaders = [
            ('User-Agent', ADDON_ID),
            ('Authorization', "Basic %s" % base64string.decode('utf-8'))
        ]

    urllib_request.install_opener(opener)
    # Make requests to the ElementumD service bypass System proxy settings
    os.environ['no_proxy'] = "localhost,127.0.0.1,%s" % ADDON.getSetting("remote_host")

    def read_properties(self):
        result = {}
        for prop in self.monitored:
            result[prop] = ADDON.getSetting(prop)

        return result

    def check_properties(self, new):
        # Comparing current with new properties
        for k, v in new.items():
            if k not in self.current_properties:
                continue
            if self.current_properties[k] != v:
                return True

        # Store 'new' as the new current state
        self.current_properties = new
        return False

    def __init__(self):
        self._closing = threading.Event()
        self._reboot = False
        Monitor.__init__(self)
        self.current_properties = self.read_properties()

    def __str__(self):
        return 'ElementumMonitor'

    @property
    def closing(self):
        return self._closing

    def restart(self):
        try:
            log.info("Triggering Elementum restart")
            init()
            urllib_request.urlopen("%s/restart" % ELEMENTUMD_HOST, timeout=1)
        except:
            pass

    def reboot(self, val=None):
        if val is not None:
            self._reboot = val

        return self._reboot

    def close(self):
        self._closing.set()

    def onAbortRequested(self):
        # Only when closing Kodi
        if self.abortRequested():
            xbmc.executebuiltin("Dialog.Close(all, true)")
            log.info("onAbortRequested")
            if not ONLY_CLIENT:
                shutdown()
            try:
                self._closing.set()
                self._closing.clear()
            except SystemExit as e:
                log.info("Exit %d" % (e.code))
                if e.code != 0:
                    os._exit(0)
                pass

    def onSettingsChanged(self):
        try:
            # We check if changed settings belong to those that we should ignore (like token refresh or expiry time)
            if self.check_properties(self.read_properties()):
                log.info("Ignoring Elementum settings change")
                return

            log.info("Triggering Elementum reload")
            init()
            urllib_request.urlopen("%s/reload" % ELEMENTUMD_HOST, timeout=1)
            urllib_request.urlopen("%s/cmd/clear_page_cache" % ELEMENTUMD_HOST, timeout=1)
        except:
            pass

    def onNotification(self, sender, method, data):
        if method and "elementum_restart" in method:
            self.restart()
            self.reboot(True)

            return

        try:
            if PY2:
                data_base64 = base64.b64encode(data)
            else:
                data_base64 = base64.b64encode(data.encode("utf-8")).decode("utf-8")

            urllib_request.urlopen("%s/notification?sender=%s&method=%s&data=%s" % (
                ELEMENTUMD_HOST,
                sender,
                method,
                data_base64))
        except:
            pass
