# -*- coding: utf-8 -*-
"""`action=mplay`: resolve the canonical play URL to a stream (docs/plan/milionar-library/040 §2).

Runs inside Kodi's plugin resolve call: pick the source (dialog / automatic / same as last time), resolve the
provider stream, write the now-playing contract for the service tracker, then setResolvedUrl.
"""
import json
import os
import time
from urllib.parse import quote_plus

import xbmc
import xbmcaddon
import xbmcgui
import xbmcplugin

from wcs.library2 import play, store, tmdb, urls

NP_PROPERTY = play.NP_PROPERTY


def _log(msg, level=xbmc.LOGINFO):
    xbmc.log('[Milionář Library] {}'.format(msg), level)


def _fail(handle):
    xbmcplugin.setResolvedUrl(handle, False, xbmcgui.ListItem())


def _stream_for(selected, addon):
    """Provider stream URL for a picked file {'ident', 'provider'}; None when it cannot be resolved."""
    provider = selected.get('provider', 'webshare')
    ident = selected['ident']
    try:
        if provider == 'kraska':
            from wcs.streamcinema import SCClient
            from wcs.kraska import KraskaClient
            real = SCClient.get_ident(ident, addon)
            return KraskaClient.resolve(real, addon) if real else None
        from wcs.webshare import WebshareClient
        token = WebshareClient.revalidate(addon, lambda *a, **k: None)
        return WebshareClient.getlink(ident, token, dtype='video_stream', addon=addon) if token else None
    except Exception as exc:
        _log('stream resolve failed ({}): {}: {}'.format(provider, type(exc).__name__, exc), xbmc.LOGWARNING)
        return None


def _pick_movie(info, data, addon, src):
    from wcs import utils
    return utils.search_and_select_movie_file(
        data['title'], data['year'], data['plot'], data['poster'], data['fanart'], data['rating'], data['genre'],
        data['director'], data['runtime'], addon, tmdb_id=info['tmdb'], autoplay=(src == 'auto'))


def _pick_episode(info, data, addon, src):
    from wcs import utils
    return utils.search_and_select_episode_file(
        data['series_name'], info['s'], info['e'], data['episode_title'], data['plot'], data['poster'], data['fanart'],
        data['rating'], data['genre'], addon, data['year'], data['runtime'], autoplay_request=(src == 'auto'),
        tmdb_id=info['tmdb'])


def _last_pick(info, addon):
    """Same file as the last play of this item, or None when nothing is stored."""
    kind = 'movie' if info['type'] == 'movie' else 'tv'
    state = store.get_state(kind, info['tmdb'], info.get('s'), info.get('e'))
    if state and state.get('last_ident'):
        return {'ident': state['last_ident'], 'name': state.get('last_file_name') or '',
                'provider': state.get('last_provider') or 'webshare'}
    return None


def _listitem(info, data, stream, selected):
    if info['type'] == 'movie':
        title, plot = data['title'], data['plot']
    else:
        title = '{} S{:02d}E{:02d}'.format(data['series_name'], info['s'], info['e'])
        plot = data['plot']
    item = xbmcgui.ListItem(label=title, path=stream)
    art = {}
    if data.get('poster'):
        art.update({'thumb': data['poster'], 'icon': data['poster'], 'poster': data['poster']})
    if data.get('fanart'):
        art['fanart'] = data['fanart']
    if art:
        item.setArt(art)
    tag = item.getVideoInfoTag()
    tag.setTitle(title)
    tag.setPlot(plot or '')
    if info['type'] == 'movie':
        tag.setMediaType('movie')
        if str(data.get('year') or '').isdigit():
            tag.setYear(int(data['year']))
    else:
        tag.setMediaType('episode')
        tag.setTvShowTitle(data['series_name'])
        tag.setSeason(info['s'])
        tag.setEpisode(info['e'])
    item.setProperty('mimetype', 'application/octet-stream')
    item.setProperty('IsPlayable', 'true')
    return item


def _write_contract(info, data, stream, selected, canonical, start_at, origin=None, follow=True):
    runtime_min = data.get('runtime') or ''
    return play.contract(info, stream, selected, canonical, title=data.get('title') or data.get('episode_title', ''),
                         show_title=data.get('series_name', ''),
                         runtime_s=int(runtime_min) * 60 if str(runtime_min).isdigit() else 0, start_at=start_at,
                         origin=origin or 'mplay', follow=follow)


def _after_resolve(info, data, addon):
    """What the old play paths did after starting: recently played entry and the info dialog with the game."""
    from wcs import user_data
    from wcs.playback.dialog_scheduler import schedule_info_dialog
    from wcs.playback.metadata import MediaMetadata
    try:
        if info['type'] == 'movie':
            user_data.add_recently_played_item(addon, {
                'title': data['title'], 'year': data['year'], 'poster': data['poster'], 'rating': data['rating'],
                'media_type': 'movie', 'tmdb_id': info['tmdb'], 'plot': data['plot'], 'genre': data['genre']})
            schedule_info_dialog(MediaMetadata.from_tmdb_movie({
                'title': data['title'], 'year': data['year'], 'plot': data['plot'], 'poster': data['poster'],
                'fanart': data['fanart'], 'rating': data['rating'], 'genre': data['genre'],
                'director': data['director'], 'runtime': data['runtime']}), source='addon_movie')
        else:
            from wcs.utils import _on_episode_playback_start
            _on_episode_playback_start(
                addon, data['series_name'], info['s'], info['e'], data['episode_title'], data['plot'], data['poster'],
                data['fanart'], data['rating'], data['genre'], data['year'], data['runtime'], str(info['tmdb']),
                '', episode_thumb=data.get('episode_thumb', ''))
    except Exception as exc:
        _log('post-resolve step failed: {}: {}'.format(type(exc).__name__, exc), xbmc.LOGWARNING)


def run(handle, params):
    started = time.time()
    try:
        info = urls.parse('plugin://{}/?{}'.format(urls.ADDON_ID, '&'.join('{}={}'.format(k, v) for k, v in params.items())))
    except Exception:
        info = None
    if not info:
        _log('not a canonical url: {}'.format(params), xbmc.LOGWARNING)
        return _fail(handle)
    canonical = urls.canonical(info)
    request = play.consume(canonical)
    addon = xbmcaddon.Addon(urls.ADDON_ID)

    data = tmdb.movie_info(info['tmdb']) if info['type'] == 'movie' else tmdb.episode_info(info['tmdb'], info['s'], info['e'])
    if not data:
        xbmcgui.Dialog().notification('Milionář', addon.getLocalizedString(32260), xbmcgui.NOTIFICATION_ERROR, 4000)
        return _fail(handle)

    selected, stream = None, None
    if not stream:
        from wcs import user_data
        if not user_data.check_providers_and_prompt(addon):
            return _fail(handle)
        if request.get('pick') and request['pick'].get('ident'):
            selected = dict(request['pick'])
            selected.setdefault('provider', 'webshare')
            selected.setdefault('name', '')
            stream = _stream_for(selected, addon)
            if not stream:
                selected = None
        if not stream and request['src'] in ('last', 'known'):           # known: same file as last time, else the dialog
            selected = _last_pick(info, addon)
            stream = _stream_for(selected, addon) if selected else None
            if not stream:
                selected = None
        if not stream:
            selected = (_pick_movie if info['type'] == 'movie' else _pick_episode)(
                info, data, addon, 'auto' if request['src'] in ('auto', 'last') else 'dialog')
            if not selected or 'ident' not in selected:
                _log('no source picked for {}'.format(canonical))
                if request['src'] in ('auto', 'last') and info['type'] == 'episode':
                    xbmcgui.Dialog().notification('Milionář', addon.getLocalizedString(32282), xbmcgui.NOTIFICATION_INFO, 5000)
                return _fail(handle)
            stream = _stream_for(selected, addon)
        if not stream:
            xbmcgui.Dialog().notification('Milionář', addon.getLocalizedString(30158), xbmcgui.NOTIFICATION_ERROR, 4000)
            return _fail(handle)

    kind = 'movie' if info['type'] == 'movie' else 'tv'
    state = store.get_state(kind, info['tmdb'], info.get('s'), info.get('e'))
    start_at = float(state['resume_pos']) if (state and request['from'] == 'resume') else 0.0
    _write_contract(info, data, stream, selected, canonical, start_at, request.get('origin'), request.get('follow', True))
    item = _listitem(info, data, stream, selected)
    xbmcplugin.setResolvedUrl(handle, True, item)
    _log('resolved {} via {} in {:.1f}s (start_at {:.0f}s)'.format(canonical, selected.get('provider'),
                                                                    time.time() - started, start_at))
    _after_resolve(info, data, addon)
