# -*- coding: utf-8 -*-
from __future__ import unicode_literals, division, absolute_import, print_function

import logging
from builtins import *  # noqa pylint: disable=unused-import, redefined-builtin

from flexget import plugin
from flexget.event import event
from flexget.manager import Session

from . import api_trakt as plugin_api_trakt
from . import db

# TODO: not very nice ..
lookup_series = plugin_api_trakt.ApiTrakt.lookup_series
lookup_movie = plugin_api_trakt.ApiTrakt.lookup_movie


log = logging.getLogger('trakt_lookup')


def is_show(entry):
    return entry.get('series_name') or entry.get('tvdb_id', eval_lazy=False)


def is_episode(entry):
    return entry.get('series_season') and entry.get('series_episode')


def is_season(entry):
    return entry.get('series_season') and not is_episode(entry)


def is_movie(entry):
    return bool(entry.get('movie_name'))


class TraktLazyLookup(object):
    def __init__(self, field_map, lookup_function):
        self.field_map = field_map
        self.lookup_function = lookup_function

    def __call__(self, entry):
        with Session() as session:
            try:
                result = self.lookup_function(entry, session)
            except LookupError as e:
                log.debug(e)
            else:
                entry.update_using_map(self.field_map, result)

        return entry


class TraktUserDataLookup(object):
    def __init__(self, field_name, data_type, media_type, lookup_function):
        self.field_name = field_name
        self.lookup_function = lookup_function
        self.data_type = data_type
        self.media_type = media_type

    def __call__(self, entry):
        try:
            result = self.lookup_function(
                data_type=self.data_type, media_type=self.media_type, entry=entry
            )
        except LookupError as e:
            log.debug(e)
        else:
            entry[self.field_name] = result

        return entry


class PluginTraktLookup(object):
    """Retrieves trakt information for entries. Uses series_name,
    series_season, series_episode from series plugin.

    Example:

    trakt_lookup: yes

    Primarily used for passing trakt information to other plugins.
    Among these is the IMDB url for the series.

    This information is provided (via entry):
    series info:
    trakt_series_name
    trakt_series_runtime
    trakt_series_first_aired_epoch
    trakt_series_first_aired_iso
    trakt_series_air_time
    trakt_series_content_ratingi
    trakt_series_genres
    trakt_series_imdb_url
    trakt_series_trakt_url
    imdb_id
    tvdb_id
    trakt_series_actors
    trakt_series_country
    trakt_series_year
    trakt_series_tvrage_id
    trakt_series_status
    trakt_series_overview

    trakt_ep_name
    trakt_ep_season
    trakt_ep_number
    trakt_ep_overview
    trakt_ep_first_aired_epoch
    trakt_ep_first_aired_iso
    trakt_ep_id
    trakt_ep_tvdb_id


    """

    # Series info
    series_map = {
        'trakt_series_name': 'title',
        'trakt_series_year': 'year',
        'imdb_id': 'imdb_id',
        'tvdb_id': 'tvdb_id',
        'tmdb_id': 'tmdb_id',
        'trakt_show_id': 'id',
        'trakt_show_slug': 'slug',
        'tvrage_id': 'tvrage_id',
        'trakt_trailer': 'trailer',
        'trakt_homepage': 'homepage',
        'trakt_series_runtime': 'runtime',
        'trakt_series_first_aired': 'first_aired',
        'trakt_series_air_time': 'air_time',
        'trakt_series_air_day': 'air_day',
        'trakt_series_content_rating': 'certification',
        'trakt_genres': lambda i: [db_genre.name for db_genre in i.genres],
        'trakt_series_network': 'network',
        'imdb_url': lambda series: series.imdb_id
        and 'http://www.imdb.com/title/%s' % series.imdb_id,
        'trakt_series_url': lambda series: series.slug
        and 'https://trakt.tv/shows/%s' % series.slug,
        'trakt_series_country': 'country',
        'trakt_series_status': 'status',
        'trakt_series_overview': 'overview',
        'trakt_series_rating': 'rating',
        'trakt_series_votes': 'votes',
        'trakt_series_language': 'language',
        'trakt_series_aired_episodes': 'aired_episodes',
        'trakt_series_episodes': lambda show: [episodes.title for episodes in show.episodes],
        'trakt_languages': 'translation_languages',
    }

    series_actor_map = {'trakt_actors': lambda show: db.list_actors(show.actors)}
    show_translate_map = {
        'trakt_translations': lambda show: db.get_translations_dict(show.translations, 'show')
    }

    # Episode info
    episode_map = {
        'trakt_ep_name': 'title',
        'trakt_ep_imdb_id': 'imdb_id',
        'trakt_ep_tvdb_id': 'tvdb_id',
        'trakt_ep_tmdb_id': 'tmdb_id',
        'trakt_ep_tvrage': 'tvrage_id',
        'trakt_episode_id': 'id',
        'trakt_ep_first_aired': 'first_aired',
        'trakt_ep_overview': 'overview',