# -*- coding: utf-8 -*-
"""Click action of Home widgets (docs/plan/milionar-library/150-widget-clicks.md).

Every widget row has a kind (movie, series, episode, ...), a fixed set of click options and a default; the slot's skin
string `mil.<sec>.<n>.click` picks one. This module only knows ids and builds the paths of the items, so it stays light
for the `main.py` fast path (no network, no Kodi library, no router import). The actions behind the paths are the
proven addon actions (`mplay_req`, `show_wcs_details`, ...) and the fast-path actions of `ctx.py` / `channel_play.py`.
"""
from urllib.parse import parse_qsl, quote, quote_plus, urlsplit

import xbmcaddon

from wcs.skin.hero_contract import SECTIONS as HERO_SECTIONS

ADDON_ID = 'plugin.video.milionar'
BASE = 'plugin://{}/'.format(ADDON_ID)

# ---- option sets per kind of item (the first ones are the most useful; labels: addon strings)
COMMON = ('similar', 'game', 'list', 'channel', 'watched')
OPTIONS = {
    'vinyl_collection': ('open', 'detail', 'play_all', 'shuffle'),
    'vinyl_song': ('play', 'detail', 'play_from', 'queue'),
    'vinyl_genre': ('open', 'detail', 'play_all', 'shuffle'),
    'vinyl_radio': ('open', 'detail', 'play_all'),
    'movie': ('play', 'play_start', 'stream', 'detail') + COMMON,
    'series': ('folder', 'detail', 'next', 'next_stream') + COMMON,
    'episode': ('play', 'play_start', 'stream', 'detail', 'folder', 'season') + COMMON,
    'mixed': ('play', 'play_start', 'stream', 'detail') + COMMON,
    'game': ('game', 'play', 'stream', 'detail', 'similar'),
    'demo': ('game',),
    'mytv_next': ('play', 'detail', 'folder', 'season', 'similar', 'game', 'channel_open'),
    'tv_channel': ('live', 'live_shuffle', 'first', 'random', 'open'),
    'cinema_channel': ('live', 'random', 'open'),
}
# kind -> {option: label string id}; the labels of a kind may differ (a channel of MyCinema plays films)
LABELS = {
    'play_all': 32522, 'shuffle': 32523, 'play_from': 32524, 'queue': 32525,
    'play': 32377, 'play_start': 32378, 'stream': 32379, 'detail': 32380, 'folder': 32381, 'season': 32382,
    'next': 32383, 'next_stream': 32384, 'similar': 32385, 'game': 32386, 'list': 32387, 'channel': 32388,
    'watched': 32389, 'channel_open': 32390, 'live': 32391, 'live_shuffle': 32392, 'first': 32393, 'random': 32394,
    'open': 32396, 'hero': 32684,
}
KIND_LABELS = {'cinema_channel': {'random': 32395, 'open': 32397},
               'vinyl_collection': {'open': 32521}, 'vinyl_genre': {'open': 32521},
               'vinyl_radio': {'open': 32521}, 'vinyl_song': {'play': 32526}}
S_CLICK, S_CHOOSE = 32375, 32376

ROW_KIND = {
    'vinyl_curator': 'vinyl_collection', 'vinyl_discover': 'vinyl_collection',
    'vinyl_top_tracks': 'vinyl_song',
    'vinyl_songs': 'vinyl_song', 'vinyl_albums': 'vinyl_collection', 'vinyl_artists': 'vinyl_collection',
    'vinyl_playlists': 'vinyl_collection', 'vinyl_genres': 'vinyl_genre', 'vinyl_radios': 'vinyl_radio',
    'vinyl_favorite_songs': 'vinyl_song', 'vinyl_favorite_playlists': 'vinyl_collection',
    'vinyl_favorite_albums': 'vinyl_collection', 'vinyl_favorite_artists': 'vinyl_collection',
    'cont_movies': 'movie', 'my_movies_progress': 'movie', 'my_movies_added': 'movie', 'my_movies_unwatched': 'movie',
    'my_movies_watched': 'movie', 'my_movies_all': 'movie',
    'cont_series': 'episode', 'my_series_next': 'episode', 'my_series_new': 'episode', 'my_series_upcoming': 'episode',
    'my_series_added': 'series', 'my_series_unwatched': 'series', 'my_series_all': 'series',
    'recent_played': 'mixed',
    'widget_tmdb_popular_movies': 'movie', 'widget_tmdb_popular_series': 'series', 'widget_mycinema_recommended': 'movie',
    'widget_ai_recent': 'mixed', 'widget_game_topics': 'game', 'widget_mytv_next': 'mytv_next',
    'widget_demo_movies': 'demo', 'widget_demo_series': 'demo',
    'widget_mytv_channels': 'tv_channel', 'widget_mycinema_channels': 'cinema_channel',
    'fy_continue': 'mixed', 'fy_for_you': 'mixed', 'fy_top10': 'mixed', 'fy_because_1': 'mixed',
    'fy_because_2': 'mixed', 'fy_because_3': 'mixed', 'fy_tonight': 'mixed', 'fy_new': 'mixed', 'fy_gems': 'mixed',
}                                                       # rows without a kind (genres, Kraska, ČSFD) are folders only
DEFAULT = {
    'vinyl_curator': 'open', 'vinyl_discover': 'open', 'vinyl_songs': 'play',
    'vinyl_top_tracks': 'play',
    'vinyl_albums': 'open', 'vinyl_artists': 'open', 'vinyl_playlists': 'open', 'vinyl_genres': 'open',
    'vinyl_radios': 'open', 'vinyl_favorite_songs': 'play', 'vinyl_favorite_playlists': 'open',
    'vinyl_favorite_albums': 'open', 'vinyl_favorite_artists': 'open',
    'cont_movies': 'play', 'my_movies_progress': 'play', 'my_movies_added': 'detail', 'my_movies_unwatched': 'detail',
    'my_movies_watched': 'detail', 'my_movies_all': 'detail',
    'cont_series': 'play', 'my_series_next': 'play', 'my_series_new': 'play', 'my_series_upcoming': 'play',
    'my_series_added': 'folder', 'my_series_unwatched': 'folder', 'my_series_all': 'folder',
    'recent_played': 'play',
    'widget_tmdb_popular_movies': 'detail', 'widget_tmdb_popular_series': 'detail', 'widget_mycinema_recommended': 'detail',
    'widget_ai_recent': 'play', 'widget_game_topics': 'game', 'widget_mytv_next': 'play',
    'widget_demo_movies': 'game', 'widget_demo_series': 'game',
    'widget_mytv_channels': 'live', 'widget_mycinema_channels': 'live',
    'fy_continue': 'play', 'fy_for_you': 'detail', 'fy_top10': 'detail', 'fy_because_1': 'detail',
    'fy_because_2': 'detail', 'fy_because_3': 'detail', 'fy_tonight': 'detail', 'fy_new': 'detail', 'fy_gems': 'detail',
}
UNAIRED_NOTE = ('play', 'play_start', 'stream', 'next', 'next_stream')     # an unaired episode only shows its date

# the two lists of the skin (Moje filmy / Moje seriály) have their own, shorter sets (listings.py)
LIST_KINDS = {'movies': 'movie', 'series': 'series'}
LIST_DEFAULT = {'movies': 'detail', 'series': 'folder'}
LIST_OPTIONS = {'movies': ('play', 'play_start', 'stream', 'detail'), 'series': ('folder', 'detail', 'next', 'next_stream')}


def kind_of(row):
    return ROW_KIND.get(row, '')


def options(row, section=None):
    """Click options of a widget row (empty: a folder-only row)."""
    values = OPTIONS.get(ROW_KIND.get(row, ''), ())
    if values and (section is None or section in HERO_SECTIONS):
        return values + ('hero',)
    return values


def default(row):
    return DEFAULT.get(row, '')


def resolve(row, value):
    """The click of a widget: its stored value when it is valid for the row, otherwise the row's default."""
    return value if value in options(row) else default(row)


def label(row, option):
    kind = ROW_KIND.get(row, '')
    string_id = KIND_LABELS.get(kind, {}).get(option) or LABELS.get(option)
    return xbmcaddon.Addon(ADDON_ID).getLocalizedString(string_id) if string_id else option


def label_of(option):
    """Label of an option without a row (the skin settings of the lists)."""
    return xbmcaddon.Addon(ADDON_ID).getLocalizedString(LABELS[option])


def list_click(kind):
    """Click of the skin's lists (`movies` | `series`): the skin setting, valid or the default (never the addon setting)."""
    import xbmc
    value = xbmc.getInfoLabel('Skin.String(mil.list.{}.click)'.format(kind))
    return value if value in LIST_OPTIONS[kind] else LIST_DEFAULT[kind]


# --------------------------------------------------------------------------- paths of the title options

def _run(query):
    """Playable plugin URL that resolves to nothing and starts RunPlugin(<query>) (the `skin_run` pattern)."""
    return '{}?action=skin_run&run={}'.format(BASE, quote(query, safe=''))


def seasons_path(tmdb_id):
    return '{}?action=mlist&kind=seasons&tmdb={}'.format(BASE, tmdb_id)


def season_path(tmdb_id, season):
    return '{}?action=mlist&kind=episodes&tmdb={}&s={}'.format(BASE, tmdb_id, season)


def _unaired(text):
    return '{}?action=mupcoming&text={}'.format(BASE, quote_plus(text or ''))


def title_path(media, tmdb_id, click, season=None, episode=None, meta=None, unaired_text=None):
    """(path, is_folder) of the click `click` on a title.

    media: `movie`, `tv` (a series) or `episode`; `meta`: title, original, plot, poster, fanart, year of the title;
    `unaired_text`: set for an episode that has not aired yet (a play like option only shows it).
    """
    meta = meta or {}
    tmdb_id = int(tmdb_id)
    title = meta.get('title') or ''
    if unaired_text is not None and click in UNAIRED_NOTE:
        return _unaired(unaired_text), False
    if media == 'movie':
        query_id = 'type=movie&tmdb={}'.format(tmdb_id)
        details = 'action=show_wcs_details&media_type=movie&tmdb_id={}'.format(tmdb_id)
    elif media == 'episode':
        query_id = 'type=episode&tmdb={}&s={}&e={}'.format(tmdb_id, season, episode)
        details = 'action=show_wcs_details&media_type=tv&tmdb_id={}'.format(tmdb_id)
    else:
        query_id = None
        details = 'action=show_wcs_details&media_type=tv&tmdb_id={}'.format(tmdb_id)
    kind = 'movie' if media == 'movie' else 'tv'
    if click in ('play', 'play_start', 'stream', 'next', 'next_stream'):
        src = 'dialog' if click in ('stream', 'next_stream') else 'known'
        start = 'start' if click == 'play_start' else 'resume'
        if media == 'tv':                                   # a series: its next episode, worked out when clicked
            return _run('action=ctx_next&tmdb={}&src={}&from={}'.format(tmdb_id, src, start)), False
        return _run('action=mplay_req&{}&src={}&from={}'.format(query_id, src, start)), False
    if click == 'detail':
        return _run(details), False
    if click == 'folder':
        return seasons_path(tmdb_id), True
    if click == 'season' and media == 'episode':
        return season_path(tmdb_id, season), True
    if click == 'similar':
        original = meta.get('original') or title
        return _run('action=display_similar_{}_dialog&tmdb_id={}&original_title={}'.format(
            'movies' if media == 'movie' else 'series', tmdb_id, quote_plus(original))), False
    if click == 'game':
        from wcs.games import millionaire
        subject = millionaire.Subject(title=title, tmdb_id=str(tmdb_id), media_type=kind,
                                      plot=meta.get('plot') or '', year=meta.get('year') or '',
                                      poster=meta.get('poster') or '', backdrop=meta.get('fanart') or '',
                                      season_number=season if media == 'episode' else None,
                                      episode_number=episode if media == 'episode' else None,
                                      episode_title=meta.get('episode_title') or '')
        return _run(millionaire.query(subject)), False
    if click == 'list':
        return _run('action=ctx_list_toggle&type={}&tmdb={}'.format(kind, tmdb_id)), False
    if click == 'channel':
        return _run('action=ctx_channel&type={}&tmdb={}'.format(kind, tmdb_id)), False
    if click == 'watched':
        extra = '&s={}&e={}'.format(season, episode) if media == 'episode' else ''
        return _run('action=ctx_mark_toggle&type={}&tmdb={}{}'.format('episode' if media == 'episode' else kind, tmdb_id, extra)), False
    return _run(details), False                             # an unknown value never breaks a widget: the detail


def exec_for(path, folder=False):
    """The builtin the skin's container `onclick` runs for an item (`ListItem.Property(milionar.exec)`).

    Kodi's own click on a widget item (CDirectoryProvider::OnClick) first runs its video "select action" for every item
    with a video tag: an item with a resume point gets Kodi's resume prompt before our action. The skin therefore runs
    the click itself (Includes_Home.xml `onclick_action`); this is what it runs: a folder opens in the Videos window, an
    action starts through RunPlugin (the `run` of a `skin_run` URL directly, without the extra hop)."""
    if folder:
        return 'ActivateWindow(Videos,{},return)'.format(path)
    params = dict(parse_qsl(urlsplit(path).query))
    if params.get('action') == 'skin_run' and params.get('run'):
        return 'RunPlugin({}?{})'.format(BASE.rstrip('/'), params['run'])
    return 'RunPlugin({})'.format(path)


def entry_path(entry, click):
    """(path, is_folder) for an entry of the cached / history widgets (`media_type`, `tmdb_id`, title, plot, poster ...)."""
    media = 'movie' if entry.get('media_type') == 'movie' else 'tv'
    tmdb_id = entry.get('tmdb_id') or entry.get('id')
    meta = {'title': entry.get('title') or entry.get('name') or '', 'plot': entry.get('plot') or '',
            'poster': entry.get('poster') or ''}
    return title_path(media, tmdb_id, click, meta=meta)
