# -*- coding: utf-8 -*-
"""Minimal Kodi module stubs so the real addon search code runs outside Kodi.

install(settings_overrides) must run before any `wcs` import. The Addon stub
reads the real addon settings.xml (values are never printed) and applies the
overrides on top, so a harness run can flip providers or autoplay settings.
"""

import os
import sys
import types
import xml.etree.ElementTree as ET

ADDON_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
KODI_HOME = os.path.expanduser('~/Library/Application Support/Kodi')
SETTINGS_PATH = os.path.join(KODI_HOME, 'userdata/addon_data/plugin.video.milionar/settings.xml')

LOG = []            # (level, message) from xbmc.log, inspected by the harness
_OVERRIDES = {}
EXTRA_ORIGINAL_TITLES = {}  # title -> original title for cases outside the Kodi library
DB_PATH = os.path.join(KODI_HOME, 'userdata/Database/MyVideos131.db')


def _json_rpc(request):
    """VideoLibrary.GetMovies/GetTVShows with a title filter, answered from the Kodi DB."""
    import json
    import sqlite3
    req = json.loads(request)
    method = req.get('method')
    value = ((req.get('params') or {}).get('filter') or {}).get('value', '')
    if method not in ('VideoLibrary.GetMovies', 'VideoLibrary.GetTVShows'):
        return json.dumps({'id': req.get('id'), 'result': {}})
    key = 'movies' if method.endswith('Movies') else 'tvshows'
    items = []
    if value in EXTRA_ORIGINAL_TITLES:
        items.append({'title': value, 'originaltitle': EXTRA_ORIGINAL_TITLES[value], 'year': 0, 'uniqueid': {}})
    elif os.path.exists(DB_PATH):
        db = sqlite3.connect(DB_PATH)
        if key == 'movies':
            rows = db.execute('select c00, c16, substr(premiered, 1, 4), idMovie from movie where c00 = ?', (value,))
            kind = 'movie'
        else:
            rows = db.execute('select c00, c09, substr(c05, 1, 4), idShow from tvshow where c00 = ?', (value,))
            kind = 'tvshow'
        for title, original, year, media_id in rows.fetchall():
            ids = dict(db.execute('select type, value from uniqueid where media_type = ? and media_id = ?',
                                  (kind, media_id)).fetchall())
            items.append({'title': title, 'originaltitle': original or '', 'uniqueid': ids,
                          'year': int(year) if (year or '').isdigit() else 0})
    return json.dumps({'id': req.get('id'), 'result': {key: items}})


def _read_settings():
    values = {}
    if os.path.exists(SETTINGS_PATH):
        for node in ET.parse(SETTINGS_PATH).getroot().iter('setting'):
            if node.get('id'):
                values[node.get('id')] = node.text or ''
    values.update(_OVERRIDES)
    return values


class Addon:
    def __init__(self, addon_id=None):
        self._settings = _read_settings()

    def getSetting(self, key):
        return self._settings.get(key, '')

    def getSettingBool(self, key):
        return str(self._settings.get(key, 'false')).lower() == 'true'

    def getSettingInt(self, key):
        try:
            return int(self._settings.get(key, '0') or 0)
        except ValueError:
            return 0

    def setSetting(self, key, value):
        self._settings[key] = value  # in-memory only, never written back

    def getLocalizedString(self, string_id):
        return 'str{}'.format(string_id)

    def getAddonInfo(self, key):
        return {'path': ADDON_DIR, 'id': 'plugin.video.milionar', 'name': 'Milionář'}.get(key, '')

    def openSettings(self):
        pass


class ListItem:
    def __init__(self, label='', label2='', path='', offscreen=False):
        self.label = label
        self.props = {}
        self.art = {}

    def setProperty(self, key, value):
        self.props[key.lower()] = value

    def getProperty(self, key):
        return self.props.get(key.lower(), '')

    def setArt(self, art):
        self.art.update(art)

    def getLabel(self):
        return self.label

    def __getattr__(self, name):
        return lambda *a, **k: None


class ListControl:
    """Stand-in for any control; list methods collect items (control 50 = results)."""

    def __init__(self, control_id):
        self.control_id = control_id
        self.items = []
        self.selected = 0

    def reset(self):
        self.items = []

    def addItem(self, item):
        self.items.append(item)

    def addItems(self, items):
        self.items.extend(items)

    def size(self):
        return len(self.items)

    def selectItem(self, index):
        self.selected = index

    def getSelectedItem(self):
        return self.items[self.selected] if self.items else None

    def __getattr__(self, name):
        return lambda *a, **k: None


class WindowXMLDialog:
    def __init__(self, *args, **kwargs):
        self._props = {}
        self._controls = {}

    def getControl(self, control_id):
        return self._controls.setdefault(control_id, ListControl(control_id))

    def setProperty(self, key, value):
        self._props[key] = value

    def getProperty(self, key):
        return self._props.get(key, '')

    def close(self):
        pass

    def __getattr__(self, name):
        if name.startswith('_'):
            raise AttributeError(name)  # getattr(self, '_x', default) must see the default, as in Kodi
        return lambda *a, **k: None


class Dialog:
    def notification(self, *a, **k):
        LOG.append((2, 'NOTIFICATION {}'.format(a)))

    def ok(self, *a, **k):
        LOG.append((2, 'DIALOG.OK {}'.format(a)))
        return True

    def yesno(self, *a, **k):
        return False

    def select(self, *a, **k):
        return -1

    def __getattr__(self, name):
        return lambda *a, **k: None


def _module(name, **attrs):
    mod = types.ModuleType(name)
    mod.__dict__.update(attrs)
    mod.__getattr__ = lambda attr: (lambda *a, **k: None)
    sys.modules[name] = mod
    return mod


def _translate_path(path):
    path = path or ''
    if path.startswith('special://home/'):
        return os.path.join(KODI_HOME, path[len('special://home/'):])
    if path.startswith('special://profile/'):
        return os.path.join(KODI_HOME, 'userdata', path[len('special://profile/'):])
    return path


def install(settings_overrides=None):
    _OVERRIDES.clear()
    _OVERRIDES.update(settings_overrides or {})
    if 'xbmc' in sys.modules and getattr(sys.modules['xbmc'], '_harness_stub', False):
        return
    _module('xbmc', _harness_stub=True, LOGDEBUG=0, LOGINFO=1, LOGWARNING=2, LOGERROR=3, LOGFATAL=4,
            log=lambda msg, level=1: LOG.append((level, msg)),
            sleep=lambda ms: None, executebuiltin=lambda *a, **k: None,
            executeJSONRPC=_json_rpc, getCondVisibility=lambda c: False,
            getInfoLabel=lambda l: '', Monitor=type('Monitor', (), {'abortRequested': lambda s: False,
                                                                    'waitForAbort': lambda s, t=0: False}),
            Player=type('Player', (), {'__init__': lambda s, *a, **k: None}))
    _module('xbmcgui', WindowXMLDialog=WindowXMLDialog, WindowXML=WindowXMLDialog, WindowDialog=WindowXMLDialog,
            Window=WindowXMLDialog, ListItem=ListItem, Dialog=Dialog,
            DialogProgress=type('DialogProgress', (), {'__getattr__': lambda s, n: (lambda *a, **k: None)}),
            NOTIFICATION_INFO='info', NOTIFICATION_WARNING='warning', NOTIFICATION_ERROR='error',
            ACTION_NAV_BACK=92, ACTION_PREVIOUS_MENU=10, ACTION_CONTEXT_MENU=117)
    _module('xbmcaddon', Addon=Addon)
    _module('xbmcplugin', SORT_METHOD_NONE=0)
    _module('xbmcvfs', translatePath=_translate_path, exists=os.path.exists,
            mkdirs=lambda p: os.makedirs(p, exist_ok=True) or True)
    # requests & co. come from Kodi's bundled script.module.* addons
    for module in ('requests', 'urllib3', 'certifi', 'chardet', 'idna', 'unidecode'):
        lib = os.path.join(KODI_HOME, 'addons', 'script.module.' + module, 'lib')
        if os.path.isdir(lib) and lib not in sys.path:
            sys.path.append(lib)
    if ADDON_DIR not in sys.path:
        sys.path.insert(0, ADDON_DIR)
