# -*- coding: utf-8 -*-
"""Temporary timing lines in kodi.log for docs/plan/skin-optimization; remove with that plan's last step.

`log()` writes one line with the prefix PREFIX at LOGINFO, so it is there without Kodi's debug logging.

The probe thread watches Home and does not care how the rows get their cards (plugin call, static items, items bound
by the service): it only counts, per section, the rows whose list has at least one card.

  focus <sec>                      another menu item got the focus
  cards <sec> <k>/<n>              the number of that section's rows with cards changed (n = its configured rows)

Normally only the section on screen is watched. With the file `perf_watch` in the addon's profile directory (written
by scripts/skin_harness/measure.py) every section that is not switched off is watched, also in the background.
"""
import os
import threading
import time

import xbmc
import xbmcvfs
from wcs.skin import family
from wcs.skin.hero_contract import WIDGET_SLOTS

PREFIX = '[DEBUG][Milionář Perf] '
# Home menu id -> (section, first list id, skin setting that switches its menu item off): every section of Home.xml
MENUS = {'mil_foryou': ('foryou', 32000, 'HomeMenuNoMilForYouButton'),
         'mil_continue': ('cont', 24000, 'HomeMenuNoMilContinueButton'),
         'mil_mymovies': ('my_movies', 29000, 'HomeMenuNoMilMyMoviesButton'),
         'mil_myseries': ('my_series', 30000, 'HomeMenuNoMilMySeriesButton'),
         'mil_mytv': ('mytv', 22000, 'HomeMenuNoMilMyTVButton'),
         'mil_vinyl': ('vinyl', 31000, 'HomeMenuNoMilVinylButton'),
         'mil_mycinema': ('mycinema', 23000, 'HomeMenuNoMilMyCinemaButton'),
         'mil_game': ('game', 25000, 'HomeMenuNoMilGameButton'),
         'mil_ai': ('ai', 26000, 'HomeMenuNoMilAIButton'),
         'mil_kraska': ('kraska', 27000, 'HomeMenuNoMilKraskaButton'),
         'mil_tmdb': ('tmdb', 28000, 'HomeMenuNoMilTMDbButton')}
POLL = 0.05
CONFIG_EVERY = 3.0                        # seconds between reads of the slot configuration and the switches
WATCH_FLAG = 'special://profile/addon_data/plugin.video.milionar/perf_watch'


def log(message):
    xbmc.log(PREFIX + message, xbmc.LOGINFO)


def _slots(section, base):
    """List ids of the section's configured rows."""
    result = []
    for number in range(1, WIDGET_SLOTS + 1):
        row = xbmc.getInfoLabel('Skin.String(mil.{}.{}.type)'.format(section, number))
        if row and row != 'off':
            result.append(base + number * 100)
    return result


def _configuration():
    """{section: list ids} of the sections whose menu item is not switched off."""
    return {section: _slots(section, base) for section, base, flag in MENUS.values()
            if not xbmc.getCondVisibility('Skin.HasSetting({})'.format(flag))}


def _with_cards(ids):
    count = 0
    for list_id in ids:
        value = xbmc.getInfoLabel('Container({}).NumItems'.format(list_id))
        if value.isdigit() and int(value) > 0:
            count += 1
    return count


def _probe(monitor):
    watch_all = os.path.exists(xbmcvfs.translatePath(WATCH_FLAG))
    log('probe started ({})'.format('all sections' if watch_all else 'the section on screen'))
    by_menu = {menu: values[0] for menu, values in MENUS.items()}
    sections, read_at = {}, 0.0
    focused, counts, active = None, {}, False
    while not monitor.waitForAbort(POLL if active else 0.25):
        active = family.active() and xbmc.getCondVisibility('Window.IsActive(home)')
        if not active:
            focused = None
            continue
        now = time.monotonic()
        if now - read_at >= CONFIG_EVERY:
            sections, read_at = _configuration(), now
        section = by_menu.get(xbmc.getInfoLabel('Container(9000).ListItem.Property(id)'))
        if section != focused:
            focused = section
            if section:
                log('focus {}'.format(section))
        for name in (sections if watch_all else [focused] if focused in sections else []):
            ids = sections[name]
            value = (_with_cards(ids), len(ids))
            if counts.get(name) != value:
                counts[name] = value
                log('cards {} {}/{}'.format(name, value[0], value[1]))


def _guarded(monitor):
    try:
        _probe(monitor)
    except Exception as exc:
        xbmc.log(PREFIX + 'probe stopped: {}: {}'.format(type(exc).__name__, exc), xbmc.LOGWARNING)


def start(monitor):
    threading.Thread(target=_guarded, args=(monitor,), name='milionar-perf', daemon=True).start()
