# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# XBMC Launcher (xbmc / kodi)
# ------------------------------------------------------------

import sys
from core.item import Item
from core import filetools
from platformcode import config, logger, platformtools
from platformcode.logger import WebErrorException


def start():
    '''
    First function that is executed when entering the plugin.
    Within this function all calls should go to
    functions that we want to execute as soon as we open the plugin.
    '''
    logger.debug()

    if not config.dev_mode():
        try:
            with open(config.changelogFile, 'r') as fileC:
                changelog = fileC.read()
                if changelog.strip():
                    platformtools.dialog_ok('Kodi on Demand', 'Aggiornamenti applicati:\n' + changelog)
            filetools.remove(config.changelogFile)
        except:
            pass


def run(item=None):
    logger.debug()

    # Extract item from sys.argv
    if not item: item = makeItem()

    # Load or Repare Settings
    if not config.get_setting('show_once'): showOnce()

    # Acrions
    logger.debug(item.tostring())

    try:
        # Active tmdb
        if not config.get_setting('tmdb_active'):
            config.set_setting('tmdb_active', True)

        # If item has no action, stops here
        if item.action == '':
            logger.debug('Item without action')
            return

        # Channel Selector
        if item.channel == 'channelselector':
            itemlist = []
            import channelselector
            if item.action == 'getmainlist': # Action for main menu in channelselector
                itemlist = channelselector.getmainlist()
            elif item.action == 'getchanneltypes': # Action for channel types on channelselector: movies, series, etc.
                itemlist = channelselector.getchanneltypes()
            elif item.action == 'filterchannels': # Action for channel listing on channelselector
                itemlist = channelselector.filterchannels(item.channel_type)
            platformtools.render_items(itemlist, item)


        # Special action for playing a video from the library
        elif item.action == 'play_from_library':
            return playFromLibrary(item)

        # Special play action
        elif item.action == 'play': play(item)

        # Special findvideos Action
        elif item.action == 'findvideos': findvideos(item)

        # Special action for searching, first asks for the words then call the "search" function
        elif item.action == 'search': search(item)

        ######## Following shares must be improved ########

        # Special itemInfo Action
        elif item.action == "itemInfo":
            platformtools.dialog_textviewer('Item info', item.parent)

        # Special action for open item.url in browser
        elif item.action == "open_browser":
            import webbrowser
            if not webbrowser.open(item.url):
                import xbmc
                if xbmc.getCondVisibility('system.platform.linux') and xbmc.getCondVisibility('system.platform.android'):  # android
                    xbmc.executebuiltin('StartAndroidActivity("", "android.intent.action.VIEW", "", "%s")' % item.url)
                else:
                    platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(70740) % "\n".join([item.url[j:j+57] for j in range(0, len(item.url), 57)]))

        # Special gotopage Action
        elif item.action == "gotopage":
            page = platformtools.dialog_numeric(0, config.get_localized_string(70513))
            if page:
                import xbmc
                item.action = item.real_action
                if item.page:
                    item.page = int(page)
                else:
                    import re
                    item.url = re.sub('([=/])[0-9]+(/?)$', '\g<1>' + page + '\g<2>', item.url)
                xbmc.executebuiltin("Container.Update(%s?%s)" % (sys.argv[0], item.tourl()))

        # Special action for adding a movie to the library
        elif item.action == "add_pelicula_to_library":
            from core import videolibrarytools
            videolibrarytools.add_movie(item)

        # Special action for adding a serie to the library
        elif item.action == "add_serie_to_library":
            channel = importChannel(item)
            from core import videolibrarytools
            videolibrarytools.add_tvshow(item, channel)

        # Special action for adding a undefined to the library
        elif item.action == "add_to_library":
            channel = importChannel(item)
            from core import videolibrarytools
            videolibrarytools.add_to_videolibrary(item, channel)

        # Special action for downloading all episodes from a serie
        elif item.action == "download_all_episodes":
            from specials import downloads
            item.action = item.extra
            del item.extra
            downloads.save_download(item)

        # keymaptools special actions
        elif item.action == "keymap":
            from platformcode import keymaptools
            if item.open:
                return keymaptools.open_shortcut_menu()
            else:
                return keymaptools.set_key()
        elif item.action == "delete_key":
            from platformcode import keymaptools
            return keymaptools.delete_key()

        # delete tmdb cache
        elif item.action == "script":
            from core import tmdb
            tmdb.clean_cache()
            platformtools.dialog_notification(config.get_localized_string(20000), config.get_localized_string(60011), time=2000, sound=False)

        ################################################

        # For all other actions
        else: actions(item)



    except WebErrorException as e:
        import traceback
        from core import scrapertools

        logger.error(traceback.format_exc())

        platformtools.dialog_ok(
            config.get_localized_string(59985) % e.channel,
            config.get_localized_string(60013) % e.url)

    except Exception as e:
        import traceback
        from core import scrapertools

        logger.error(traceback.format_exc())

        patron = r'File "{}([^.]+)\.py"'.format(filetools.join(config.get_runtime_path(), 'channels', '').replace('\\', '\\\\'))
        Channel = scrapertools.find_single_match(traceback.format_exc(), patron)

        if Channel or e.__class__ == logger.ChannelScraperException:
            if item.url:
                if platformtools.dialog_yesno(config.get_localized_string(60087) % Channel, config.get_localized_string(60014), nolabel='ok', yeslabel=config.get_localized_string(70739)):
                    run(Item(action='open_browser', url=item.url))
            else:
                platformtools.dialog_ok(config.get_localized_string(60087) % Channel, config.get_localized_string(60014))
        else:
            if platformtools.dialog_yesno(config.get_localized_string(60038), config.get_localized_string(60015)):
                platformtools.itemlist_update(Item(channel='setting', action='report_menu'), True)
    finally:
        # db need to be closed when not used, it will cause freezes
        from core import db
        db.close()
        import threading
        logger.debug(threading.enumerate())


def new_search(item, channel=None):
    itemlist=[]
    if 'search' in dir(channel):
        itemlist = channel.search(item, item.text)
    else:
        from core import support
        itemlist = support.search(channel, item, item.text)

    writelist = item.channel
    for it in itemlist:
        writelist += ',' + it.tourl()
    # filetools.write(temp_search_file, writelist)
    return itemlist


def limitItemlist(itemlist):
    logger.debug()
    try:
        value = config.get_setting('max_links', 'videolibrary')
        if value == 0:
            new_list = itemlist
        else:
            new_list = itemlist[:value]
        return new_list
    except:
        return itemlist


def makeItem():
    logger.debug()
    if sys.argv[2]:
        sp = sys.argv[2].split('&')
        url = sp[0]
        item = Item().fromurl(url)
        if len(sp) > 1:
            for e in sp[1:]:
                key, val = e.split('=')
                if val.lower() == 'false': val = False
                elif val.lower() == 'true': val = True
                item.__setattr__(key, val)
    # If no item, this is mainlist
    else:
        item = Item(channel='channelselector', action='getmainlist', viewmode='movie')

    return item


def showOnce():
    if not config.get_all_settings_addon():
        logger.error('corrupted settings.xml!!')
        settings_xml = filetools.join(config.get_data_path(), 'settings.xml')
        settings_bak = filetools.join(config.get_data_path(), 'settings.bak')
        if filetools.exists(settings_bak):
            filetools.copy(settings_bak, settings_xml, True)
            logger.info('restored settings.xml from backup')
        else:
            filetools.write(settings_xml, '<settings version="2">\n</settings>')  # resetted settings
    else:
        from platformcode import xbmc_videolibrary
        xbmc_videolibrary.ask_set_content(silent=False)
        config.set_setting('show_once', True)


def play(item):
    channel = importChannel(item)

    # define info for trakt
    try:
        from core import trakt_tools
        trakt_tools.set_trakt_info(item)
    except:
        pass
    logger.debug('item.action=', item.action.upper())

    # First checks if channel has a "play" function
    if hasattr(channel, 'play'):
        logger.debug('Executing channel "play" method')
        itemlist = channel.play(item)
        # Play should return a list of playable URLS
        if len(itemlist) > 0 and isinstance(itemlist[0], Item):
            item = itemlist[0]
            platformtools.play_video(item)

        # Allow several qualities from Play in El Channel
        elif len(itemlist) > 0 and isinstance(itemlist[0], list):
            item.video_urls = itemlist
            platformtools.play_video(item)

        # If not, shows user an error message
        else:
            platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(60339))

    # If player don't have a "play" function, not uses the standard play from platformtools
    else:
        logger.debug('Executing core "play" method')
        platformtools.play_video(item)


def findvideos(item, itemlist=[]):
    if not itemlist:
        logger.debug('Executing channel', item.channel, 'method', item.action)
        channel = importChannel(item)
        from core import servertools

        p_dialog = platformtools.dialog_progress_bg(config.get_localized_string(20000), config.get_localized_string(60683))
        p_dialog.update(0)

        try:
            # First checks if channel has a "findvideos" function
            if hasattr(channel, 'findvideos'):
                itemlist = getattr(channel, item.action)(item)

            # If not, uses the generic findvideos function
            else:
                logger.debug('No channel "findvideos" method, executing core method')
                itemlist = servertools.find_video_items(item)

            itemlist = limitItemlist(itemlist)
        except Exception as ex:
            template = "An exception of type %s occured. Arguments:\n%r"
            message = template % (type(ex).__name__, ex.args)
            logger.error(" %s" % message)

        p_dialog.update(100)
        p_dialog.close()

    serverlist = [s for s in itemlist if s.server]
    if itemlist and not serverlist:
        platformtools.render_items(itemlist, item)
    if not serverlist:
        platformtools.dialog_notification(config.get_localized_string(20000), config.get_localized_string(60347))
    elif len(serverlist) == 1:
        # If there is only one server play it immediately
        play(itemlist[0].clone(no_return=True))
    else:
        platformtools.serverWindow(item, itemlist)


def search(item):
    channel = importChannel(item)
    from core import channeltools

    if config.get_setting('last_search'):
        last_search = channeltools.get_channel_setting('Last_searched', 'search', '')
    else:
        last_search = ''

    search_text = platformtools.dialog_input(last_search)

    if search_text is not None:
        channeltools.set_channel_setting('Last_searched', search_text, 'search')
        itemlist = new_search(item.clone(text=search_text), channel)
    else:
        return

    platformtools.render_items(itemlist, item)


def addToLibrary(item):
    channel = importChannel(item)
    from core import videolibrarytools
    videolibrarytools.add_to_videolibrary(item, channel)


def importChannel(item):
    channel = platformtools.channelImport(item.channel)
    if not channel:
        logger.debug('Channel', item.channel, 'not exist!')
        return

    logger.debug('Running channel', channel.__name__,  '|', channel.__file__)
    return channel


def actions(item):
    logger.debug('Executing channel', item.channel, 'method', item.action)
    channel = importChannel(item)
    itemlist = getattr(channel, item.action)(item)
    if type(itemlist) == list:
        if config.get_setting('trakt_sync'):
            from core import trakt_tools
            token_auth = config.get_setting('token_trakt', 'trakt')
            if not token_auth:
                trakt_tools.auth_trakt()
            else:
                import xbmc
                if not xbmc.getCondVisibility('System.HasAddon(script.trakt)') and config.get_setting('install_trakt'):
                    trakt_tools.ask_install_script()
            itemlist = trakt_tools.trakt_check(itemlist)
        else:
            config.set_setting('install_trakt', True)

        if len([s for s in itemlist if s.server]) > 0:
            findvideos(item, itemlist)
        else:
            platformtools.render_items(itemlist, item)


def playFromLibrary(item):
    if not item.next_ep: platformtools.fakeVideo()
    item.action = item.next_action if item.next_action else 'findvideos'
    logger.debug('Executing channel', item.channel, 'method', item.action)
    return run(item)
