# -*- coding: utf-8 -*-
"""Context menu actions that change the store (docs/plan/milionar-library/080 §2, 040 §5), main.py fast path.

State transactions publish row changes; Kodi mirroring and missing metadata run in the service worker.
"""
import time

import xbmc
import xbmcaddon
import xbmcgui

from wcs.library2 import jobs, meta, rows, store, tmdb

ADDON_ID = 'plugin.video.milionar'
S_ADDED, S_REMOVED = 32418, 32419          # "Added to {}" / "Removed from {}"
S_EDIT_WIDGETS = 32373                      # "Upravit widgety" (Home widgets only)
S_NO_NEXT = 32398                           # "Žádný další díl k přehrání"


def _text(string_id):
    return xbmcaddon.Addon(ADDON_ID).getLocalizedString(string_id)


def _done():
    if (xbmc.getCondVisibility('Window.IsActive(videos)')
            and xbmc.getInfoLabel('Container.FolderPath').startswith('plugin://{}/'.format(ADDON_ID))):
        xbmc.executebuiltin('Container.Refresh')


def _episodes(kind, tmdb_id, season):
    """Complete cached aired targets, or None when metadata needs background work."""
    return jobs.cached_targets(kind, tmdb_id, season)


def mark(kind, tmdb_id, season=None, episode=None, watched=True):
    """Mark a movie, an episode, a season or a whole series (aired regular episodes) watched / unwatched."""
    when = int(time.time())
    if kind == 'movie':
        targets, media = [(None, None)], 'movie'
    elif kind == 'episode':
        targets, media = [(season, episode)], 'tv'
    else:
        targets, media = _episodes(kind, tmdb_id, season), 'tv'
    if targets is None or jobs.has_pending(media, tmdb_id):
        jobs.enqueue(media, tmdb_id, kind, season, episode, watched)
        xbmcgui.Dialog().notification('Milionář', _text(32653), xbmcgui.NOTIFICATION_INFO, 5000)
        return 0
    return store.mark_many(media, tmdb_id, targets, watched, when)


def hide_continue(media, tmdb_id):
    store.set_hidden_from_continue(media, tmdb_id, True)


def set_list(media, tmdb_id, add):
    """Add to / remove from My movies / My series; an added title gets a snapshot (name, year, overview, poster)."""
    legacy = None
    if add:
        key = meta.key_movie(tmdb_id) if media == 'movie' else meta.key_tv(tmdb_id)
        data = meta.get(key)[0] or (tmdb.movie(tmdb_id) if media == 'movie' else tmdb.show(tmdb_id)) or {}
        from wcs.library2 import shared
        legacy = shared.list_snapshot(media, tmdb_id, data)
    store.set_in_list(media, tmdb_id, bool(add), legacy)
    xbmcgui.Dialog().notification('Milionář', _text(S_ADDED if add else S_REMOVED).format(
        _text(32351 if media == 'movie' else 32352)), xbmcgui.NOTIFICATION_INFO, 2500)


def next_target(data, tmdb_id):
    """(season, episode) the series continues with: resume / next episode, the first one for a series not started, S01E01 when
    the cache knows nothing yet; None when the next episode has not aired or the series is complete."""
    data.preload_series([tmdb_id])
    _show, order, state = data.series_state(tmdb_id)
    if state['kind'] in ('resume', 'next'):
        return state['episode']['s'], state['episode']['e']
    if state['kind'] is None:
        if not order:
            return 1, 1
        if order[0]['aired']:
            return order[0]['s'], order[0]['e']
    return None


def play_next(tmdb_id, src='known', start='resume'):
    """Click on a series: play its next episode (`src`: known = same stream as last time else the dialog | dialog)."""
    target = next_target(rows.Data(), tmdb_id)
    if not target:
        xbmcgui.Dialog().notification('Milionář', _text(S_NO_NEXT), xbmcgui.NOTIFICATION_INFO, 4000)
        return
    from wcs.library2 import play
    play.play_episode(tmdb_id, target[0], target[1], src, start)


def toggle_list(media, tmdb_id):
    """Add the title to My movies / My series, or remove it when it is there (the notification says which)."""
    listed = bool((rows.Data().titles(media).get(tmdb_id) or {}).get('in_list'))
    set_list(media, tmdb_id, not listed)


def toggle_watched(kind, tmdb_id, season=None, episode=None):
    """Mark the movie / episode / series watched, or unwatched when it already is."""
    from wcs.library2 import menu
    watched = jobs.pending_watched(kind, tmdb_id, season, episode)
    if watched is None:
        watched = menu.Menu().is_watched(kind, tmdb_id, season, episode)
    mark(kind, tmdb_id, season, episode, not watched)


def open_menu(params):
    """The skin closes Kodi's menu; our custom popup applies the originating widget's configuration."""
    from wcs.skin import context
    return context.open_menu(params)


def run(params):
    action = params.get('action', '')
    kind = params.get('type', '')
    if action == 'ctx_open':
        return open_menu(params)
    tmdb_id = int(params['tmdb'])

    def number(key):
        return int(params[key]) if params.get(key) not in (None, '') else None
    if action == 'ctx_mark':
        mark(kind, tmdb_id, number('s'), number('e'), params.get('watched') == '1')
    elif action == 'ctx_hide_continue':
        hide_continue(kind, tmdb_id)
    elif action == 'ctx_list':
        set_list(kind, tmdb_id, params.get('add') == '1')
    elif action == 'ctx_list_toggle':
        toggle_list(kind, tmdb_id)
    elif action == 'ctx_mark_toggle':
        toggle_watched(kind, tmdb_id, number('s'), number('e'))
    elif action == 'ctx_next':
        return play_next(tmdb_id, params.get('src', 'known'), params.get('from', 'resume'))
    _done()
