from tmdbhelper.lib.addon.plugin import ADDON, get_localized, executebuiltin
from tmdbhelper.lib.items.container import ContainerDirectory
from tmdbhelper.lib.items.directories.base.basedir_nodes import BaseDirNode
from jurialmunkey.ftools import cached_property
from collections import namedtuple


BaseDirItem = namedtuple("BaseDirItem", "item type")


class BaseDirList:
    def __init__(
        self,
        main=False,
        trakt=False,
        tmdb=False,
        mdblist=False,
        tvdb=False,
        random=False,
        trakt_genre=False,
        tmdb_v4=False,
        calendar=False,
        details=False,
    ):
        self.main = main
        self.tmdb = tmdb
        self.trakt = trakt
        self.mdblist = mdblist
        self.tvdb = tvdb
        self.random = random
        self.trakt_genre = trakt_genre
        self.tmdb_v4 = tmdb_v4
        self.calendar = calendar
        self.details = details

    def build_basedir(self, item_type=None, group=None, info=None):
        basedir = self.get_basedir_grouped(item_type, info) if info and not group else None
        basedir = basedir or self.get_basedir_ungrouped(item_type, group)
        return basedir

    @staticmethod
    def set_grouped_item(i, info):
        iobj = i['item']
        item = iobj.item.get_item(iobj.type, mixed_dir=False)
        if i['count'] > 1:  # Only subgroup items when more than one in group
            item['params'] = {'info': info, 'group': f'{iobj.item.group}'}
            item['label'] = get_localized(iobj.item.group)
        return item

    def get_basedir_grouped(self, item_type=None, info=None):
        groups = {}
        for i in self.get_basedir(item_type):
            item_group = groups.setdefault(i.item.group, {'item': i, 'count': 0})
            item_group['count'] += 1
        return [
            self.set_grouped_item(i, info)
            for i in groups.values()
        ]

    def get_basedir_ungrouped(self, item_type=None, group=None):
        return [
            i.item.get_item(i.type, mixed_dir=bool(not item_type))
            for i in self.get_basedir(item_type)
            if not group or int(group) == i.item.group  # Convert paramstring value to int for comparison
        ]

    def get_basedir(self, item_type=None):
        basedir = [
            BaseDirItem(basedir_item, basedir_item_type)
            for basedir_item in self.basedir
            if basedir_item.enabled
            for basedir_item_type in basedir_item.types
            if not item_type or basedir_item_type == item_type
        ]
        return basedir

    @property
    def basedir(self):
        basedir = []
        basedir += self.basedir_main
        basedir += self.basedir_random
        basedir += self.basedir_tmdb
        basedir += self.basedir_trakt
        basedir += self.basedir_mdblist
        basedir += self.basedir_tvdb
        basedir += self.basedir_trakt_genre
        basedir += self.basedir_tmdb_v4
        basedir += self.basedir_calendar
        basedir += self.basedir_details
        return basedir

    @property
    def basedir_main(self):
        from tmdbhelper.lib.items.directories.base.basedir_main import get_all_main_class_instances
        return [] if not self.main else get_all_main_class_instances()

    @property
    def basedir_random(self):
        from tmdbhelper.lib.items.directories.base.basedir_random import get_all_random_class_instances
        return [] if not self.random else get_all_random_class_instances()

    @property
    def basedir_tmdb(self):
        from tmdbhelper.lib.items.directories.base.basedir_tmdb import get_all_tmdb_class_instances
        return [] if not self.tmdb else get_all_tmdb_class_instances()

    @property
    def basedir_trakt(self):
        from tmdbhelper.lib.items.directories.base.basedir_trakt import get_all_trakt_class_instances
        return [] if not self.trakt else get_all_trakt_class_instances()

    @property
    def basedir_mdblist(self):
        from tmdbhelper.lib.items.directories.base.basedir_mdblist import get_all_mdblist_class_instances
        return [] if not self.mdblist else get_all_mdblist_class_instances()

    @property
    def basedir_tvdb(self):
        from tmdbhelper.lib.items.directories.base.basedir_tvdb import get_all_tvdb_class_instances
        return [] if not self.tvdb else get_all_tvdb_class_instances()

    @property
    def basedir_trakt_genre(self):
        from tmdbhelper.lib.items.directories.base.basedir_trakt_genre import get_all_trakt_genre_class_instances
        return [] if not self.trakt_genre else get_all_trakt_genre_class_instances(self.trakt_genre)

    @property
    def basedir_tmdb_v4(self):
        from tmdbhelper.lib.items.directories.base.basedir_tmdb_v4 import get_all_tmdb_v4_class_instances
        return [] if not self.tmdb_v4 else get_all_tmdb_v4_class_instances()

    @property
    def basedir_calendar(self):
        from tmdbhelper.lib.items.directories.base.basedir_calendar import get_all_calendar_class_instances
        return [] if not self.calendar else get_all_calendar_class_instances(**self.calendar)

    @property
    def basedir_details(self):
        from tmdbhelper.lib.items.directories.base.basedir_details import get_all_details_class_instances
        return [] if not self.details else get_all_details_class_instances(**self.details)


class ListBaseDir(ContainerDirectory):

    @staticmethod
    def get_trakt_calendar_item(endpoint=None, user=None, info='trakt_calendar', **kwargs):
        return {k: v for k, v in (
            ('info', info),
            ('endpoint', endpoint),
            ('user', user),
        ) if v}

    @staticmethod
    def get_library_calendar_item():
        return {'info': 'library_nextaired'}

    @cached_property
    def plugin_category(self):
        routes = {
            'dir_movie': lambda: get_localized(342),
            'dir_tv': lambda: get_localized(20343),
            'dir_person': lambda: get_localized(32172),
            'dir_tmdb': 'TheMovieDb',
            'dir_tmdb_v4': lambda: f'TheMovieDb {get_localized(32079)}',
            'dir_trakt': 'Trakt',
            'dir_mdblist': 'MDbList',
            'dir_tvdb': 'TVDb',
            'dir_random': lambda: get_localized(590),
            'dir_custom_node': 'Nodes',
        }
        try:
            func = routes[self.params['info']]
        except KeyError:
            return
        try:
            text = func()
        except TypeError:
            text = func
        try:
            return f'{text} {get_localized(int(self.params["group"]))}'
        except KeyError:
            return text

    def get_items(self, info=None, group=None, **kwargs):
        routes = {
            'dir_movie': lambda: BaseDirList(tmdb=True, trakt=True).build_basedir('movie', group=group),
            'dir_tv': lambda: BaseDirList(tmdb=True, trakt=True).build_basedir('tv', group=group),
            'dir_person': lambda: BaseDirList(tmdb=True, trakt=True).build_basedir('person', group=group),
            'dir_tmdb': lambda: BaseDirList(tmdb=True).build_basedir(group=group, info='dir_tmdb'),
            'dir_trakt': lambda: BaseDirList(trakt=True).build_basedir(group=group, info='dir_trakt'),
            'dir_mdblist': lambda: BaseDirList(mdblist=True).build_basedir(group=group),
            'dir_tvdb': lambda: BaseDirList(tvdb=True).build_basedir(group=group),
            'dir_random': lambda: BaseDirList(random=True).build_basedir(),
            'dir_calendar_dvd': lambda: BaseDirList(calendar=ListBaseDir.get_trakt_calendar_item(info='trakt_dvdcalendar', **kwargs)).build_basedir('movie'),
            'dir_calendar_movie': lambda: BaseDirList(calendar=ListBaseDir.get_trakt_calendar_item(info='trakt_moviecalendar', **kwargs)).build_basedir('movie'),
            'dir_calendar_trakt': lambda: BaseDirList(calendar=ListBaseDir.get_trakt_calendar_item(**kwargs)).build_basedir('tv'),
            'dir_calendar_library': lambda: BaseDirList(calendar=ListBaseDir.get_library_calendar_item()).build_basedir('tv'),
            'dir_custom_node': lambda: BaseDirNode(**kwargs).build_basedir(),
            'dir_trakt_genre': lambda: BaseDirList(trakt_genre=kwargs.get('genre')).build_basedir(kwargs.get('tmdb_type')),
            'dir_trakt_authenticate': lambda: executebuiltin('RunScript(plugin.video.themoviedb.helper,authenticate_trakt)'),
            'dir_tmdb_v4': lambda: BaseDirList(tmdb_v4=True).build_basedir(),
            'dir_settings': lambda: ADDON.openSettings(),
        }
        try:
            return routes[info]()
        except KeyError:
            return BaseDirList(main=True).build_basedir()


class ListRelatedBaseDir(ContainerDirectory):
    def get_items(self, tmdb_type, tmdb_id, season=None, episode=None, include_play=False, **kwargs):
        return BaseDirList(
            details={
                'tmdb_type': tmdb_type, 'tmdb_id': tmdb_id, 'season': season, 'episode': episode,
                'detailed_item': {}, 'include_play': include_play,
            }
        ).build_basedir(tmdb_type)
