#!/usr/bin/python
# -*- coding: utf-8 -*-

'''
    script.skin.helper.service
    Helper service and scripts for Kodi skins
    skinshortcuts.py
    Methods to connect skinhelper to skinshortcuts for smartshortcuts, widgets and backgrounds
'''

from utils import kodi_json, log_msg, urlencode, ADDON_ID, getCondVisibility
from metadatautils import MetadataUtils
import xbmc
import xbmcvfs
import xbmcplugin
import xbmcgui
import xbmcaddon
import sys

# extendedinfo has some login-required widgets, these must not be probed without login details
EXTINFO_CREDS = False
if getCondVisibility("System.Hasaddon(script.extendedinfo)"):
    exinfoaddon = xbmcaddon.Addon(id="script.extendedinfo")
    if exinfoaddon.getSetting("tmdb_username") and exinfoaddon.getSetting("tmdb_password"):
        EXTINFO_CREDS = True
    del exinfoaddon


def add_directoryitem(entry, is_folder=True, widget=None, widget2=None):
    '''helper to create a listitem for our smartshortcut node'''
    label = "$INFO[Window(Home).Property(%s.title)]" % entry
    path = "$INFO[Window(Home).Property(%s.path)]" % entry
    content = "$INFO[Window(Home).Property(%s.content)]" % entry
    image = "$INFO[Window(Home).Property(%s.image)]" % entry
    mediatype = "$INFO[Window(Home).Property(%s.type)]" % entry

    if is_folder:
        path = sys.argv[0] + "?action=SMARTSHORTCUTS&path=" + entry
        listitem = xbmcgui.ListItem(label, path=path)
        listitem.setIconImage("DefaultFolder.png")
    else:
        listitem = xbmcgui.ListItem(label, path=path)
        props = {}
        props["list"] = content
        if not xbmc.getInfoLabel(mediatype):
            mediatype = "media"
        props["type"] = mediatype
        props["background"] = "$INFO[Window(Home).Property(%s.image)]" % entry
        props["backgroundName"] = "$INFO[Window(Home).Property(%s.title)]" % entry
        listitem.setInfo(type="Video", infoLabels={"Title": "smartshortcut"})
        listitem.setThumbnailImage(image)
        listitem.setIconImage("special://home/addons/script.skin.helper.service/fanart.jpg")

        if widget:
            widget_type = "$INFO[Window(Home).Property(%s.type)]" % widget
            if not xbmc.getInfoLabel(mediatype):
                widget_type = mediatype
            if widget_type in ["albums", "artists", "songs"]:
                widget_target = "music"
            else:
                widget_target = "video"
            props["widget"] = "addon"
            props["widgetName"] = "$INFO[Window(Home).Property(%s.title)]" % widget
            props["widgetType"] = widget_type
            props["widgetTarget"] = widget_target
            props["widgetPath"] = "$INFO[Window(Home).Property(%s.content)]" % widget
            if "plugin:" in xbmc.getInfoLabel("$INFO[Window(Home).Property(%s.content)]" % widget):
                props["widgetPath"] = props["widgetPath"] + \
                    "&reload=$INFO[Window(Home).Property(widgetreload)]$INFO[Window(Home).Property(widgetreload2)]"

        if widget2:
            widget_type = "$INFO[Window(Home).Property(%s.type)]" % widget2
            if not xbmc.getInfoLabel(mediatype):
                widget_type = mediatype
            if widget_type == "albums" or widget_type == "artists" or widget_type == "songs":
                widget_target = "music"
            else:
                widget_target = "video"
            props["widget.1"] = "addon"
            props["widgetName.1"] = "$INFO[Window(Home).Property(%s.title)]" % widget2
            props["widgetType.1"] = widget_type
            props["widgetTarget.1"] = widget_target
            props["widgetPath.1"] = "$INFO[Window(Home).Property(%s.content)]" % widget2
            if "plugin:" in xbmc.getInfoLabel("$INFO[Window(Home).Property(%s.content)]" % widget2):
                props["widgetPath.1"] = props["widgetPath.1"] + \
                    "&reload=$INFO[Window(Home).Property(widgetreload)]$INFO[Window(Home).Property(widgetreload2)]"

        listitem.setInfo(type="Video", infoLabels={"mpaa": repr(props)})

    listitem.setArt({"fanart": image})
    xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=path, listitem=listitem, isFolder=is_folder)


def smartshortcuts_sublevel(entry):
    '''get subnodes for smartshortcut node'''
    if "emby" in entry:
        content_strings = [
            "",
            ".recent",
            ".inprogress",
            ".unwatched",
            ".recentepisodes",
            ".inprogressepisodes",
            ".nextepisodes",
            ".recommended"]
    elif "plex" in entry:
        content_strings = ["", ".ondeck", ".recent", ".unwatched"]
    elif "netflix.generic.suggestions" in entry:
        content_strings = ["", ".0", ".1", ".2", ".3", ".4", ".5", ".6", ".7", ".8", ".9", ".10"]
    elif "netflix" in entry:
        content_strings = [
            "",
            ".mylist",
            ".recent",
            ".inprogress",
            ".suggestions",
            ".genres",
            ".recommended",
            ".trending"]

    for content_string in content_strings:
        key = entry + content_string
        widget = None
        widget2 = None
        if content_string == "":
            # this is the main item so define our widgets
            mediatype = xbmc.getInfoLabel("$INFO[Window(Home).Property(%s.type)]" % entry)
            if "plex" in entry:
                widget = entry + ".ondeck"
                widget2 = entry + ".recent"
            elif mediatype == "movies" or mediatype == "movie" or mediatype == "artist" or "netflix" in entry:
                widget = entry + ".recent"
                widget2 = entry + ".inprogress"
            elif mediatype == "tvshows" and "emby" in entry:
                widget = entry + ".nextepisodes"
                widget2 = entry + ".recent"
            elif (mediatype == "homevideos" or mediatype == "photos") and "emby" in entry:
                widget = entry + ".recent"
                widget2 = entry + ".recommended"
            else:
                widget = entry
        if xbmc.getInfoLabel("$INFO[Window(Home).Property(%s.path)]" % key):
            add_directoryitem(key, False, widget, widget2)


def get_smartshortcuts(sublevel=None):
    '''called from skinshortcuts to retrieve listing of all smart shortcuts'''
    xbmcplugin.setContent(int(sys.argv[1]), 'files')
    if sublevel:
        smartshortcuts_sublevel(sublevel)
    else:

        all_smartshortcuts = xbmc.getInfoLabel("Window(Home).Property(all_smartshortcuts)")
        win = xbmcgui.Window(10000)
        all_smartshortcuts = win.getProperty("all_smartshortcuts")

        if all_smartshortcuts:
            for node in eval(all_smartshortcuts):
                if "emby" in node or "plex" in node or "netflix" in node:
                    # create main folder entry
                    add_directoryitem(node, True)
                else:
                    # create final listitem entry (playlist, favorites)
                    add_directoryitem(node, False, node)
    xbmcplugin.endOfDirectory(int(sys.argv[1]))


def smartshortcuts_widgets():
    '''get the widget nods for smartshortcuts'''
    widgets = []
    all_smartshortcuts = xbmc.getInfoLabel("Window(Home).Property(all_smartshortcuts)")
    if all_smartshortcuts:
        for node in eval(all_smartshortcuts):
            label = xbmc.getInfoLabel("$INFO[Window(Home).Property(%s.title)]" % node)
            if "emby" in node or "plex" in node or "netflix" in node:
                # create main folder entry
                path = sys.argv[0] + "?action=SMARTSHORTCUTS&path=%s" % node
                widgets.append([label, path, "folder", True])
            else:
                content = xbmc.getInfoLabel("$INFO[Window(Home).Property(%s.content)]" % node)
                media_type = xbmc.getInfoLabel("$INFO[Window(Home).Property(%s.type)]" % node)
                widgets.append([label, content, media_type])
    return widgets


def item_filter_mapping():
    '''map label to each filtertype'''
    mappings = []
    mappings.append(("scriptwidgets", xbmc.getInfoLabel("System.AddonTitle(script.skin.helper.widgets)")))
    mappings.append(("librarydataprovider", xbmc.getInfoLabel("System.AddonTitle(service.library.data.provider)")))
    mappings.append(("extendedinfo", xbmc.getInfoLabel("System.AddonTitle(script.extendedinfo)")))
    mappings.append(("smartshortcuts", "Smart Shortcuts"))
    mappings.append(("skinplaylists", "Playlists"))
    mappings.append(("favourites", "Favourites"))
    mappings.append(("static", "Static widgets"))
    return mappings


def get_item_filter_label(filterkey):
    '''gets the label for the fiven filterkey'''
    label = ""
    for item in item_filter_mapping():
        if item[0] == filterkey:
            label = item[1]
    return label


def get_widgets(item_filter="", sublevel=""):
    '''get all widgets provider by several plugins and listings'''
    xbmcplugin.setContent(int(sys.argv[1]), 'files')
    if item_filter:
        # skinner has provided a comma seperated list of widgetitems to include in the listing
        item_filters = item_filter.split(",")
    else:
        # no list provided by the skinner so just show all available widgets
        item_filters = [mapping[0] for mapping in item_filter_mapping()]

    # build the widget listiing...
    for item_filter in item_filters:
        if item_filter == "smartshortcuts":
            widgets = smartshortcuts_widgets()
        elif item_filter == "skinplaylists":
            widgets = playlists_widgets()
        elif item_filter == "favourites":
            widgets = favourites_widgets()
        elif item_filter == "static":
            widgets = static_widgets()
        elif sublevel:
            widgets = plugin_widgetlisting(item_filters[0], sublevel)
        elif item_filter == "scriptwidgets":
            widgets = plugin_widgetlisting("script.skin.helper.widgets")
        elif item_filter == "librarydataprovider":
            widgets = plugin_widgetlisting("service.library.data.provider")
        elif item_filter == "extendedinfo":
            widgets = plugin_widgetlisting("script.extendedinfo")
        else:
            # unknown filter
            continue

        if not sublevel and len(item_filters) > 1 and item_filter != "static":
            # only show main listing for this category...
            if widgets:
                label = get_item_filter_label(item_filter)
                listitem = xbmcgui.ListItem(label, iconImage="DefaultFolder.png")
                url = "plugin://script.skin.helper.service?action=widgets&path=%s" % item_filter
                xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=url, listitem=listitem, isFolder=True)
        else:
            # show widgets for the selected filter...
            for widget in widgets:
                media_type = widget[2]
                if media_type == "folder":
                    is_folder = True
                elif len(widget) > 3:
                    is_folder = widget[3]
                else:
                    is_folder = False
                if media_type == "movies":
                    image = "DefaultMovies.png"
                    media_library = "Videos"
                    target = "video"
                elif media_type == "pvr":
                    media_library = "TvChannels"
                    image = "DefaultTVShows.png"
                    target = "pvr"
                elif media_type == "tvshows":
                    image = "DefaultTVShows.png"
                    media_library = "Videos"
                    target = "video"
                elif media_type == "episodes":
                    image = "DefaultTVShows.png"
                    media_library = "Videos"
                    target = "video"
                elif media_type == "albums":
                    image = "DefaultMusicAlbums.png"
                    media_library = "Music"
                    target = "music"
                elif media_type == "songs":
                    image = "DefaultMusicSongs.png"
                    media_library = "Music"
                    target = "music"
                elif media_type == "artists":
                    image = "DefaultMusicArtists.png"
                    media_library = "Music"
                    target = "music"
                elif media_type == "musicvideos":
                    image = "DefaultMusicVideos.png"
                else:
                    image = "Defaultaddon.png"
                    media_library = "Videos"
                    target = "video"

                if is_folder:
                    listitem = xbmcgui.ListItem(widget[0])
                    listitem.setIconImage("DefaultFolder.png")
                    xbmcplugin.addDirectoryItem(
                        handle=int(sys.argv[1]),
                        url=widget[1],
                        listitem=listitem, isFolder=True)
                else:
                    widgetpath = "ActivateWindow(%s,%s,return)" % (media_library, widget[1].split("&")[0])
                    listitem = xbmcgui.ListItem(widget[0], path=widgetpath)
                    props = {}
                    props["list"] = widget[1]
                    props["type"] = widget[2]
                    props["background"] = image
                    props["backgroundName"] = ""
                    props["widgetPath"] = widget[1]
                    props["widgetTarget"] = target
                    props["widgetName"] = widget[0]
                    props["widget"] = item_filter
                    listitem.setInfo(type="Video", infoLabels={"Title": "smartshortcut"})
                    listitem.setThumbnailImage(image)
                    listitem.setArt({"fanart": image})
                    # we use the mpaa property to pass all properties to skinshortcuts
                    listitem.setInfo(type="Video", infoLabels={"mpaa": repr(props)})
                    xbmcplugin.addDirectoryItem(
                        handle=int(
                            sys.argv[1]),
                        url=widgetpath,
                        listitem=listitem,
                        isFolder=False)

    xbmcplugin.endOfDirectory(int(sys.argv[1]))


def get_skinhelper_backgrounds():
    '''retrieve listing of all backgrounds as provided by skinhelper backgrounds addon'''
    result = []
    backgrounds = xbmc.getInfoLabel("Window(Home).Property(SkinHelper.AllBackgrounds)")
    if backgrounds:
        backgrounds = eval(backgrounds)
        win = xbmcgui.Window(10000)
        for key, value in backgrounds:
            label = value
            image = "$INFO[Window(Home).Property(%s)]" % key
            if win.getProperty(key):
                result.append((label, image))
            # also check if wall images exists for this item
            wall_props = [".Wall", ".Poster.Wall", ".Wall.BW", ".Poster.Wall.BW"]
            for wall_prop in wall_props:
                image = "$INFO[Window(Home).Property(%s%s)]" % (key, wall_prop)
                if win.getProperty("%s%s" % (key, wall_prop)):
                    if ".Poster" in wall_prop:
                        newlabel = "%s: %s" % (xbmc.getInfoLabel("$ADDON[script.skin.helper.backgrounds 32030]"), label)
                    else:
                        newlabel = "%s: %s" % (xbmc.getInfoLabel("$ADDON[script.skin.helper.backgrounds 32029]"), label)
                    if ".BW" in wall_prop:
                        newlabel = "%s (%s)" % (newlabel, xbmc.getInfoLabel(
                            "$ADDON[script.skin.helper.backgrounds 32031]"))
                    result.append((newlabel, image))
                else:
                    break
        del win
    return result


def get_backgrounds():
    '''called from skinshortcuts to retrieve listing of all backgrounds'''
    xbmcplugin.setContent(int(sys.argv[1]), 'files')
    for label, image in get_skinhelper_backgrounds():
        listitem = xbmcgui.ListItem(label, path=image)
        listitem.setArt({"fanart": image})
        listitem.setThumbnailImage(image)
        xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=image, listitem=listitem, isFolder=False)
    xbmcplugin.endOfDirectory(int(sys.argv[1]))


def playlists_widgets():
    '''skin provided playlists'''
    widgets = []
    import xml.etree.ElementTree as xmltree
    for playlist_path in ["special://skin/playlists/",
                          "special://skin/extras/widgetplaylists/", "special://skin/extras/playlists/"]:
        if xbmcvfs.exists(playlist_path):
            log_msg("skinshortcuts widgets processing: %s" % playlist_path)
            media_array = kodi_json('Files.GetDirectory', {"directory": playlist_path, "media": "files"})
            for item in media_array:
                if item["file"].endswith(".xsp"):
                    playlist = item["file"]
                    contents = xbmcvfs.File(item["file"], 'r')
                    contents_data = contents.read().decode('utf-8')
                    contents.close()
                    xmldata = xmltree.fromstring(contents_data.encode('utf-8'))
                    media_type = ""
                    label = item["label"]
                    for line in xmldata.getiterator():
                        if line.tag == "smartplaylist":
                            media_type = line.attrib['type']
                        if line.tag == "name":
                            label = line.text
                    try:
                        languageid = int(label)
                        label = xbmc.getLocalizedString(languageid)
                    except Exception:
                        pass
                    if not media_type:
                        mutils = MetadataUtils()
                        media_type = mutils.detect_plugin_content(playlist)
                        del mutils
                    widgets.append([label, playlist, media_type])
    return widgets


def plugin_widgetlisting(pluginpath, sublevel=""):
    '''get all nodes in a plugin listing'''
    widgets = []
    if sublevel:
        media_array = kodi_json('Files.GetDirectory', {"directory": pluginpath, "media": "files"})
    else:
        if not getCondVisibility("System.HasAddon(%s)" % pluginpath):
            return []
        media_array = kodi_json('Files.GetDirectory', {"directory": "plugin://%s" % pluginpath, "media": "files"})
    for item in media_array:
        log_msg("skinshortcuts widgets processing: %s" % (item["file"]))
        content = item["file"]
        label = item["label"]
        # extendedinfo has some login-required widgets, skip those
        if ("script.extendedinfo" in pluginpath and not EXTINFO_CREDS and (
                "info=starred" in content or "info=rated" in content or "info=account" in content)):
            continue
        if item.get("filetype", "") == "file":
            continue
        mutils = MetadataUtils()
        media_type = mutils.detect_plugin_content(item["file"])
        del mutils
        if media_type == "empty":
            continue
        if media_type == "folder":
            content = "plugin://script.skin.helper.service?action=widgets&path=%s&sublevel=%s" % (
                urlencode(item["file"]), label)
        # add reload param for widgets
        if "reload=" not in content:
            if "movies" in content:
                reloadstr = "&reload=$INFO[Window(Home).Property(widgetreload-movies)]"
            elif "episodes" in content:
                reloadstr = "&reload=$INFO[Window(Home).Property(widgetreload-episodes)]"
            elif "tvshows" in content:
                reloadstr = "&reload=$INFO[Window(Home).Property(widgetreload-tvshows)]"
            elif "musicvideos" in content:
                reloadstr = "&reload=$INFO[Window(Home).Property(widgetreload-musicvideos)]"
            elif "albums" in content or "songs" in content or "artists" in content:
                reloadstr = "&reload=$INFO[Window(Home).Property(widgetreload-music)]"
            else:
                reloadstr = "&reload=$INFO[Window(Home).Property(widgetreload)]"\
                    "$INFO[Window(Home).Property(widgetreload2)]"
            content = content + reloadstr
        content = content.replace("&limit=100", "&limit=25")
        widgets.append([label, content, media_type])
        if pluginpath == "script.extendedinfo" and not sublevel:
            # some additional entrypoints for extendedinfo...
            widgets += extendedinfo_youtube_widgets()
    return widgets


def favourites_widgets():
    '''widgets from favourites'''
    favourites = kodi_json('Favourites.GetFavourites',
                           {"type": None, "properties": ["path", "thumbnail", "window", "windowparameter"]})
    widgets = []
    if favourites:
        for fav in favourites:
            if "windowparameter" in fav:
                content = fav["windowparameter"]
                # check if this is a valid path with content
                if ("script://" not in content.lower() and "mode=9" not in content.lower() and
                        "search" not in content.lower() and "play" not in content.lower()):
                    label = fav["title"]
                    log_msg("skinshortcuts widgets processing favourite: %s" % label)
                    mutils = MetadataUtils()
                    mediatype = mutils.detect_plugin_content(content)
                    del mutils
                    if mediatype and mediatype != "empty":
                        widgets.append([label, content, mediatype])
    return widgets


def static_widgets():
    '''static widget nodes which are hardcoded in a skin'''
    widgets = []
    addon = xbmcaddon.Addon(ADDON_ID)
    widgets.append([xbmc.getLocalizedString(8), "$INCLUDE[WeatherWidget]", "static"])
    widgets.append([xbmc.getLocalizedString(130), "$INCLUDE[SystemInfoWidget]", "static"])
    widgets.append([addon.getLocalizedString(32025), "$INCLUDE[skinshortcuts-submenu]", "static"])
    if getCondVisibility("System.Hasaddon(script.games.rom.collection.browser)"):
        widgets.append([addon.getLocalizedString(32026), "$INCLUDE[RCBWidget]", "static"])
    del addon
    return widgets


def extendedinfo_youtube_widgets():
    '''the youtube nodes from extendedinfo addon'''
    # some additional entrypoints for extendedinfo...
    widgets = []
    entrypoints = [
        "plugin://script.extendedinfo?info=youtubeusersearch&&id=Eurogamer",
        "plugin://script.extendedinfo?info=youtubeusersearch&&id=Engadget",
        "plugin://script.extendedinfo?info=youtubeusersearch&&id=MobileTechReview"]
    for entry in entrypoints:
        content = entry
        label = entry.split("id=")[1]
        widgets.append([label, content, "episodes"])
    return widgets


def set_skinshortcuts_property(property_name="", value="", label=""):
    '''set custom property in skinshortcuts menu editor'''
    if value or label:
        wait_for_skinshortcuts_window()
        xbmc.sleep(250)
        xbmc.executebuiltin("SetProperty(customProperty,%s)" % property_name.encode("utf-8"))
        xbmc.executebuiltin("SetProperty(customValue,%s)" % value.encode("utf-8"))
        xbmc.executebuiltin("SendClick(404)")
        xbmc.sleep(250)
        xbmc.executebuiltin("SetProperty(customProperty,%s.name)" % property_name.encode("utf-8"))
        xbmc.executebuiltin("SetProperty(customValue,%s)" % label.encode("utf-8"))
        xbmc.executebuiltin("SendClick(404)")
        xbmc.sleep(250)
        xbmc.executebuiltin("SetProperty(customProperty,%sName)" % property_name.encode("utf-8"))
        xbmc.executebuiltin("SetProperty(customValue,%s)" % label.encode("utf-8"))
        xbmc.executebuiltin("SendClick(404)")


def wait_for_skinshortcuts_window():
    '''wait untill skinshortcuts is active window (because of any animations that may have been applied)'''
    for i in range(40):
        if not (getCondVisibility(
                "Window.IsActive(DialogSelect.xml) | "
                "Window.IsActive(script-skin_helper_service-ColorPicker.xml) | "
                "Window.IsActive(DialogKeyboard.xml)")):
            break
        else:
            xbmc.sleep(100)