# -*- coding: utf-8 -*-
"""What a Millionaire game is about: a film, a series (or one of its episodes), a channel / cinema mix, or a person.

Every place that offers the game describes its subject with a `Subject`; `wcs.games.millionaire.open_game` turns it
into the game window. `from_params` reads the plugin action `milionar_game` (and completes plot, genre and backdrop
from TMDb when the caller had none), `query` writes it, `from_person` describes an actor / director / creator.
"""
from typing import NamedTuple, Optional
from urllib.parse import urlencode

import xbmc

ACTION = 'milionar_game'
TMDB_IMAGE = 'https://image.tmdb.org/t/p/{}{}'
PERSON_TYPES = ('actor', 'director', 'writer', 'creator')


class Subject(NamedTuple):
    title: str
    media_type: str = 'movie'          # movie | series | channel | actor | director | writer | creator
    plot: str = ''
    genre: str = ''
    year: str = ''
    poster: str = ''                   # the picture of the card
    backdrop: str = ''                 # the backdrop of the card ('' = the poster)
    episode_title: str = ''
    season_number: Optional[int] = None
    episode_number: Optional[int] = None
    person: Optional[dict] = None      # name, biography, known_for ... of a person game
    tmdb_id: str = ''


def _int(value):
    try:
        return int(value) if value not in (None, '') else None
    except (TypeError, ValueError):
        return None


def query(subject):
    """The plugin query of the action `milionar_game` for a subject (what `from_params` reads back)."""
    params = {'action': ACTION, 'title': subject.title, 'media_type': subject.media_type, 'tmdb_id': subject.tmdb_id,
              'plot': subject.plot, 'poster': subject.poster, 'fanart': subject.backdrop,
              'year': subject.year, 'genre': subject.genre}
    if subject.episode_title:
        params['episode_title'] = subject.episode_title
    if subject.season_number is not None:
        params['season_number'] = subject.season_number
    if subject.episode_number is not None:
        params['episode_number'] = subject.episode_number
    return urlencode({key: value for key, value in params.items() if value not in (None, '')})


def plugin_url(subject):
    return 'plugin://plugin.video.milionar/?' + query(subject)


def from_person(data, media_type, title=None, plot=None, person=None):
    """A person game: the profile photo is the card and its backdrop, the biography (500 characters) the plot."""
    profile_path = (data or {}).get('profile_path')
    picture = TMDB_IMAGE.format('w780', profile_path) if profile_path else ''
    return Subject(title=title if title is not None else (data or {}).get('name', ''), media_type=media_type,
                   plot=(plot if plot is not None else (data or {}).get('biography', ''))[:500],
                   poster=picture, backdrop=picture, person=person if person is not None else data)


def from_params(params):
    """The subject of a `milionar_game` plugin call; plot, genre and backdrop come from TMDb when they are missing."""
    title = params.get('title', '')
    fanart = params.get('fanart', '')
    poster = params.get('poster', '')
    tmdb_id = params.get('tmdb_id', '')
    media_type = params.get('media_type', 'movie')
    plot = params.get('plot', '')
    genre = params.get('genre', '')
    backdrop = fanart or poster
    person = None
    year = params.get('year', '')
    if (not plot or not fanart) and tmdb_id:
        try:
            details = _tmdb_details(tmdb_id, media_type)
        except Exception as exc:
            xbmc.log('[plugin.video.milionar] Error getting {} details for the game: {}'.format(media_type, exc),
                     xbmc.LOGERROR)
            details = None
        if details:
            plot = plot or details['plot']
            title = title or details['title']
            genre = genre or details['genre']
            backdrop = details['backdrop'] or backdrop
            person = details['person']
            year = year or details.get('year', '')
    return Subject(title=title, media_type=media_type, plot=plot, genre=genre, poster=poster or fanart,
                   backdrop=backdrop, episode_title=params.get('episode_title', ''),
                   season_number=_int(params.get('season_number')), episode_number=_int(params.get('episode_number')),
                   person=person, tmdb_id=tmdb_id, year=year)


def _tmdb_details(tmdb_id, media_type):
    """{'title', 'plot', 'genre', 'backdrop', 'person'} of a TMDb id (person, series or film)."""
    from wcs.metadata import TMDbClient as tmdb
    if media_type in PERSON_TYPES:                   # (creators used to be looked up as a film of the same id)
        data = tmdb.get_person_details(tmdb_id, media_type)
        if not data:
            return None
        profile = data.get('profile_path', '')
        return {'title': data.get('name', ''), 'plot': data.get('biography', ''), 'genre': '',
                'backdrop': TMDB_IMAGE.format('w780', profile) if profile else '',
                'person': {key: data.get(key, default) for key, default in (
                    ('name', ''), ('biography', ''), ('known_for_department', ''), ('profile_path', ''),
                    ('known_for', []))}}
    if media_type in ('series', 'tv'):
        import requests
        import xbmcaddon
        response = requests.get('https://api.themoviedb.org/3/tv/{}'.format(tmdb_id), timeout=10, params={
            'api_key': tmdb.get_tmdb_api_key(xbmcaddon.Addon()), 'language': 'cs-CZ'})
        response.raise_for_status()
        data = response.json()
    else:
        data = tmdb.get_movie_detailed_info(tmdb_id)
    if not data:
        return None
    backdrop_path = data.get('backdrop_path', '')
    return {'title': '', 'plot': data.get('overview', ''),
            'genre': ', '.join(g.get('name', '') for g in (data.get('genres') or [])[:3]),
            'backdrop': TMDB_IMAGE.format('w780', backdrop_path) if backdrop_path else '', 'person': None,
            'year': (data.get('release_date') or data.get('first_air_date') or '')[:4]}
