# Gnu General Public License - see LICENSE.TXT
from __future__ import division, absolute_import, print_function, unicode_literals

from six.moves.urllib.parse import quote, unquote, parse_qsl
import sys
import os
import time
import cProfile
import pstats
from six import StringIO

import xbmcplugin
import xbmcgui
import xbmcaddon
import xbmc

from .jellyfin import api
from .utils import translate_string, get_version, load_user_details, get_art_url, get_default_filters, translate_path, kodi_version
from .kodi_utils import HomeWindow
from .datamanager import clear_cached_server_data
from .server_detect import check_server, check_connection_speed
from .lazylogger import LazyLogger
from .menu_functions import display_main_menu, display_menu, show_movie_alpha_list, show_tvshow_alpha_list, show_genre_list, show_search, show_movie_pages, show_artist_alpha_list
from .server_sessions import show_server_sessions
from .action_menu import ActionMenu
from .dialogs import BitrateDialog
from .widgets import get_widget_content, get_widget_content_cast, check_for_new_content
from .cache_images import CacheArtwork
from .dir_functions import get_content, process_directory
from .tracking import timer
from .skin_cloner import clone_default_skin
from .play_utils import play_file

__addon__ = xbmcaddon.Addon()
__addondir__ = translate_path(__addon__.getAddonInfo('profile'))
__cwd__ = __addon__.getAddonInfo('path')
PLUGINPATH = translate_path(os.path.join(__cwd__))

log = LazyLogger(__name__)

user_details = load_user_details()


@timer
def main_entry_point():
    log.debug("===== JellyCon START =====")

    settings = xbmcaddon.Addon()
    profile_count = int(settings.getSetting('profile_count'))
    pr = None
    if profile_count > 0:
        profile_count = profile_count - 1
        settings.setSetting('profile_count', str(profile_count))
        pr = cProfile.Profile()
        pr.enable()

    log.debug("Running Python: {0}".format(sys.version_info))
    log.debug("Running JellyCon: {0}".format(get_version()))
    log.debug("Kodi BuildVersion: {0}".format(xbmc.getInfoLabel("System.BuildVersion")))
    log.debug("Kodi Version: {0}".format(kodi_version()))
    log.debug("Script argument data: {0}".format(sys.argv))

    params = get_params()
    log.debug("Script params: {0}".format(params))

    request_path = params.get("request_path", None)
    param_url = params.get('url', None)

    mode = params.get("mode", None)

    if len(params) == 1 and request_path and request_path.find("/library/movies") > -1:
        check_server()
        new_params = {}
        new_params["item_type"] = "Movie"
        new_params["media_type"] = "movies"
        show_content(new_params)
    elif mode == "CHANGE_USER":
        check_server(change_user=True, notify=False)
    elif mode == "CACHE_ARTWORK":
        CacheArtwork().cache_artwork_interactive()
    elif mode == "DETECT_SERVER":
        check_server(force=True, notify=True)
    elif mode == "DETECT_SERVER_USER":
        check_server(force=True, change_user=True, notify=False)
    elif mode == "DETECT_CONNECTION_SPEED":
        check_connection_speed()
    elif mode == "playTrailer":
        item_id = params["id"]
        play_item_trailer(item_id)
    elif mode == "MOVIE_ALPHA":
        show_movie_alpha_list(params)
    elif mode == "TVSHOW_ALPHA":
        show_tvshow_alpha_list(params)
    elif mode == "ARTIST_ALPHA":
        show_artist_alpha_list(params)
    elif mode == "GENRES":
        show_genre_list(params)
    elif mode == "MOVIE_PAGES":
        show_movie_pages(params)
    elif mode == "TOGGLE_WATCHED":
        toggle_watched(params)
    elif mode == "SHOW_MENU":
        show_menu(params)
    elif mode == "CLONE_SKIN":
        clone_default_skin()
    elif mode == "SHOW_SETTINGS":
        __addon__.openSettings()
        window = xbmcgui.getCurrentWindowId()
        if window == 10000:
            log.debug("Currently in home - refreshing to allow new settings to be taken")
            xbmc.executebuiltin("ActivateWindow(Home)")
    elif mode == "CLEAR_CACHE":
        clear_cached_server_data()
    elif mode == "WIDGET_CONTENT":
        get_widget_content(int(sys.argv[1]), params)
    elif mode == "WIDGET_CONTENT_CAST":
        get_widget_content_cast(int(sys.argv[1]), params)
    elif mode == "SHOW_CONTENT":
        check_server()
        show_content(params)
    elif mode == "SEARCH":
        xbmcplugin.setContent(int(sys.argv[1]), 'files')
        show_search()
    elif mode == "NEW_SEARCH":
        search_results(params)
    elif mode == "NEW_SEARCH_PERSON":
        search_results_person(params)
    elif mode == "SHOW_SERVER_SESSIONS":
        show_server_sessions()
    elif mode == "SHOW_ADDON_MENU":
        display_menu(params)
    elif mode == "GET_CONTENT_BY_TV_SHOW":
        parent_id = __get_parent_id_from(params)
        if parent_id is not None:
            enriched_url = param_url + "&ParentId=" + parent_id
            get_content(enriched_url, params)
        else:
            log.info("Unable to find TV show parent ID.")
    else:
        log.debug("JellyCon -> Mode: {0}".format(mode))
        log.debug("JellyCon -> URL: {0}".format(param_url))

        if mode == "GET_CONTENT":
            get_content(param_url, params)
        elif mode == "PLAY":
            play_action(params)
        else:
            check_server()
            display_main_menu()

    if pr:
        pr.disable()

        file_time_stamp = time.strftime("%Y%m%d-%H%M%S")
        tab_file_name = __addondir__ + "profile(" + file_time_stamp + ").txt"
        s = StringIO()
        ps = pstats.Stats(pr, stream=s)
        ps = ps.sort_stats('cumulative')
        ps.print_stats()
        ps.strip_dirs()
        ps = ps.sort_stats('tottime')
        ps.print_stats()
        with open(tab_file_name, 'w') as f:
            f.write(s.getvalue())

    log.debug("===== JellyCon FINISHED =====")


def __enrich_url(param_url, params):
    enriched_url = param_url
    parent_id = __get_parent_id_from(params)
    if parent_id is not None:
        enriched_url = param_url + "&ParentId=" + parent_id
    return enriched_url


def __get_parent_id_from(params):
    result = None
    show_provider_ids = params.get("show_ids")
    if show_provider_ids is not None:
        log.debug("TV show providers IDs: {}".format(show_provider_ids))
        get_show_url = "/Users/{}/Items?fields=MediaStreams&Recursive=true" \
                       "&IncludeItemTypes=series&IncludeMedia=true&ImageTypeLimit=1&Limit=16" \
                       "&AnyProviderIdEquals={}".format(api.user_id, show_provider_ids)
        content = api.get(get_show_url)
        show = content.get("Items")
        if len(show) == 1:
            result = content.get("Items")[0].get("Id")
        else:
            log.debug("TV show not found for ids: {}".format(show_provider_ids))
    else:
        log.error("TV show parameter not found in request.")
    return result


def toggle_watched(params):
    log.debug("toggle_watched: {0}".format(params))
    item_id = params.get("item_id", None)
    if item_id is None:
        return
    url = "/Users/{}/Items/{}?format=json".format(api.user_id, item_id)
    result = api.get(url)
    log.debug("toggle_watched item info: {0}".format(result))

    user_data = result.get("UserData", None)
    if user_data is None:
        return

    if user_data.get("Played", False) is False:
        mark_item_watched(item_id)
    else:
        mark_item_unwatched(item_id)


def mark_item_watched(item_id):
    log.debug("Mark Item Watched: {0}".format(item_id))
    url = "/Users/{}/PlayedItems/{}".format(user_details.get('user_id'), item_id)
    api.post(url)
    check_for_new_content()
    home_window = HomeWindow()
    last_url = home_window.get_property("last_content_url")
    if last_url:
        log.debug("markWatched_lastUrl: {0}".format(last_url))
        home_window.set_property("skip_cache_for_" + last_url, "true")

    xbmc.executebuiltin("Container.Refresh")


def mark_item_unwatched(item_id):
    log.debug("Mark Item UnWatched: {0}".format(item_id))
    url = "/Users/{}/PlayedItems/{}".format(user_details.get('user_id'), item_id)
    api.delete(url)
    check_for_new_content()
    home_window = HomeWindow()
    last_url = home_window.get_property("last_content_url")
    if last_url:
        log.debug("markUnwatched_lastUrl: {0}".format(last_url))
        home_window.set_property("skip_cache_for_" + last_url, "true")

    xbmc.executebuiltin("Container.Refresh")


def mark_item_favorite(item_id):
    log.debug("Add item to favourites: {0}".format(item_id))
    url = "/Users/{}/FavoriteItems/{}".format(user_details.get('user_id'), item_id)
    api.post(url)
    check_for_new_content()
    home_window = HomeWindow()
    last_url = home_window.get_property("last_content_url")
    if last_url:
        home_window.set_property("skip_cache_for_" + last_url, "true")

    xbmc.executebuiltin("Container.Refresh")


def unmark_item_favorite(item_id):
    log.debug("Remove item from favourites: {0}".format(item_id))
    url = "/Users/{}/FavoriteItems/{}".format(user_details.get('user_id'), item_id)
    api.delete(url)
    check_for_new_content()
    home_window = HomeWindow()
    last_url = home_window.get_property("last_content_url")
    if last_url:
        home_window.set_property("skip_cache_for_" + last_url, "true")

    xbmc.executebuiltin("Container.Refresh")


def delete(item_id):

    item = api.delete("/Users/{}/Items/{}".format(user_details.get('user_id'), item_id))

    item_id = item.get("Id")
    item_name = item.get("Name", "")
    series_name = item.get("SeriesName", "")
    ep_number = item.get("IndexNumber", -1)

    final_name = ""

    if series_name:
        final_name += series_name + " - "

    if ep_number != -1:
        final_name += "Episode %02d - " % (ep_number,)

    final_name += item_name

    if not item.get("CanDelete", False):
        xbmcgui.Dialog().ok(translate_string(30135), translate_string(30417), final_name)
        return

    return_value = xbmcgui.Dialog().yesno(translate_string(30091), '{}\n{}'.format(final_name, translate_string(30092)))
    if return_value:
        log.debug('Deleting Item: {0}'.format(item_id))
        url = '/Items/{}'.format(item_id)
        progress = xbmcgui.DialogProgress()
        progress.create(translate_string(30052), translate_string(30053))
        api.delete(url)
        progress.close()
        check_for_new_content()
        home_window = HomeWindow()
        last_url = home_window.get_property("last_content_url")
        if last_url:
            home_window.set_property("skip_cache_for_" + last_url, "true")

        xbmc.executebuiltin("Container.Refresh")


def get_params():
    '''
    Retrieve the request data from Kodi
    '''

    plugin_path = sys.argv[0]
    paramstring = sys.argv[2]

    log.debug("Parameter string: {0}".format(paramstring))
    log.debug("Plugin Path string: {0}".format(plugin_path))

    param = dict(parse_qsl(paramstring[1:]))

    # add plugin path
    request_path = plugin_path.replace("plugin://plugin.video.jellycon", "")
    param["request_path"] = request_path

    log.debug("JellyCon -> Detected parameters: {0}".format(param))
    return param


def show_menu(params):
    log.debug("showMenu(): {0}".format(params))

    home_window = HomeWindow()
    settings = xbmcaddon.Addon()
    item_id = params["item_id"]

    url = "/Users/{}/Items/{}?format=json".format(api.user_id, item_id)
    result = api.get(url)
    log.debug("Menu item info: {0}".format(result))

    if result is None:
        return

    action_items = []

    if result["Type"] in ["Episode", "Movie", "Music", "Video", "Audio", "TvChannel", "Program"]:
        li = xbmcgui.ListItem(translate_string(30314), offscreen=True)
        li.setProperty('menu_id', 'play')
        action_items.append(li)

    if result["Type"] in ["Season", "MusicArtist", "MusicAlbum", "Playlist"]:
        li = xbmcgui.ListItem(translate_string(30317), offscreen=True)
        li.setProperty('menu_id', 'play_all')
        action_items.append(li)

    if result["Type"] in ["Episode", "Movie", "Video", "TvChannel", "Program"]:
        li = xbmcgui.ListItem(translate_string(30275), offscreen=True)
        li.setProperty('menu_id', 'transcode')
        action_items.append(li)

    if result["Type"] in ["Episode", "Movie", "Music", "Video", "Audio", "MusicArtist", "MusicAlbum"]:
        li = xbmcgui.ListItem(translate_string(30402), offscreen=True)
        li.setProperty('menu_id', 'add_to_playlist')
        action_items.append(li)

    if result["Type"] in ("Movie", "Series"):
        li = xbmcgui.ListItem(translate_string(30307), offscreen=True)
        li.setProperty('menu_id', 'play_trailer')
        action_items.append(li)

    if result["Type"] == "Episode" and result["ParentId"] is not None:
        li = xbmcgui.ListItem(translate_string(30327), offscreen=True)
        li.setProperty('menu_id', 'view_season')
        action_items.append(li)

    if result["Type"] in ("Series", "Season", "Episode"):
        li = xbmcgui.ListItem(translate_string(30354), offscreen=True)
        li.setProperty('menu_id', 'view_series')
        action_items.append(li)

    if result["Type"] == "Movie":
        li = xbmcgui.ListItem("Show Extras", offscreen=True)
        li.setProperty('menu_id', 'show_extras')
        action_items.append(li)

    user_data = result.get("UserData", None)
    if user_data:
        progress = user_data.get("PlaybackPositionTicks", 0) != 0
        played = user_data.get("Played", False)
        if not played or progress:
            li = xbmcgui.ListItem(translate_string(30270), offscreen=True)
            li.setProperty('menu_id', 'mark_watched')
            action_items.append(li)
        if played or progress:
            li = xbmcgui.ListItem(translate_string(30271), offscreen=True)
            li.setProperty('menu_id', 'mark_unwatched')
            action_items.append(li)

        if user_data.get("IsFavorite", False) is False:
            li = xbmcgui.ListItem(translate_string(30272), offscreen=True)
            li.setProperty('menu_id', 'jellyfin_set_favorite')
            action_items.append(li)
        else:
            li = xbmcgui.ListItem(translate_string(30273), offscreen=True)
            li.setProperty('menu_id', 'jellyfin_unset_favorite')
            action_items.append(li)

    can_delete = result.get("CanDelete", False)
    if can_delete:
        li = xbmcgui.ListItem(translate_string(30274), offscreen=True)
        li.setProperty('menu_id', 'delete')
        action_items.append(li)

    li = xbmcgui.ListItem(translate_string(30398), offscreen=True)
    li.setProperty('menu_id', 'refresh_server')
    action_items.append(li)

    li = xbmcgui.ListItem(translate_string(30281), offscreen=True)
    li.setProperty('menu_id', 'refresh_images')
    action_items.append(li)

    if result["Type"] in ["Movie", "Series"]:
        li = xbmcgui.ListItem(translate_string(30399), offscreen=True)
        li.setProperty('menu_id', 'hide')
        action_items.append(li)

    li = xbmcgui.ListItem(translate_string(30401), offscreen=True)
    li.setProperty('menu_id', 'info')
    action_items.append(li)

    window = xbmcgui.Window(xbmcgui.getCurrentWindowId())
    container_view_id = str(window.getFocusId())
    container_content_type = xbmc.getInfoLabel("Container.Content")
    view_key = "view-" + container_content_type
    current_default_view = settings.getSetting(view_key)
    view_match = container_view_id == current_default_view
    log.debug("View ID:{0} Content type:{1}".format(container_view_id, container_content_type))

    if container_content_type in ["movies", "tvshows", "seasons", "episodes", "sets"]:
        if view_match:
            li = xbmcgui.ListItem("Unset as default view", offscreen=True)
            li.setProperty('menu_id', 'unset_view')
            action_items.append(li)
        else:
            li = xbmcgui.ListItem("Set as default view", offscreen=True)
            li.setProperty('menu_id', 'set_view')
            action_items.append(li)

    action_menu = ActionMenu("ActionMenu.xml", PLUGINPATH, "default", "720p")
    action_menu.setActionItems(action_items)
    action_menu.doModal()
    selected_action_item = action_menu.getActionItem()
    selected_action = ""
    if selected_action_item is not None:
        selected_action = selected_action_item.getProperty('menu_id')
    log.debug("Menu Action Selected: {0}".format(selected_action))
    del action_menu

    if selected_action == "play":
        log.debug("Play Item")
        play_action(params)

    elif selected_action == "set_view":
        log.debug("Settign view type for {0} to {1}".format(view_key, container_view_id))
        settings.setSetting(view_key, container_view_id)

    elif selected_action == "unset_view":
        log.debug("Un-Settign view type for {0} to {1}".format(view_key, container_view_id))
        settings.setSetting(view_key, "")

    elif selected_action == "refresh_server":
        url = ("/Items/" + item_id + "/Refresh" +
               "?Recursive=true" +
               "&ImageRefreshMode=FullRefresh" +
               "&MetadataRefreshMode=FullRefresh" +
               "&ReplaceAllImages=true" +
               "&ReplaceAllMetadata=true")
        res = api.post(url)
        log.debug("Refresh Server Responce: {0}".format(res))

    elif selected_action == "hide":
        user_details = load_user_details()
        user_name = user_details["user_name"]
        hide_tag_string = "hide-" + user_name
        url = "/Items/{}/Tags/Add".format(item_id)
        post_tag_data = {"Tags": [{"Name": hide_tag_string}]}
        res = api.post(url, post_tag_data)
        log.debug("Add Tag Responce: {0}".format(res))

        check_for_new_content()

        last_url = home_window.get_property("last_content_url")
        if last_url:
            log.debug("markUnwatched_lastUrl: {0}".format(last_url))
            home_window.set_property("skip_cache_for_" + last_url, "true")

        xbmc.executebuiltin("Container.Refresh")

    elif selected_action == "play_all":
        play_action(params)

    elif selected_action == "play_trailer":
        play_item_trailer(item_id)

    elif selected_action == "transcode":
        params['force_transcode'] = 'true'

        force_max_stream_bitrate = settings.getSetting("force_max_stream_bitrate")
        initial_bitrate_value = int(force_max_stream_bitrate)
        bitrate_dialog = BitrateDialog("BitrateDialog.xml", PLUGINPATH, "default", "720p")
        bitrate_dialog.initial_bitrate_value = initial_bitrate_value
        bitrate_dialog.doModal()
        selected_transcode_value = bitrate_dialog.selected_transcode_value
        del bitrate_dialog
        log.debug("selected_transcode_value: {0}".format(selected_transcode_value))

        if selected_transcode_value > 0:
            settings.setSetting("force_max_stream_bitrate", str(selected_transcode_value))

            play_action(params)

    elif selected_action == "add_to_playlist":
        params["action"] = "add_to_playlist"
        play_action(params)

    elif selected_action == "jellyfin_set_favorite":
        mark_item_favorite(item_id)

    elif selected_action == "jellyfin_unset_favorite":
        unmark_item_favorite(item_id)

    elif selected_action == "mark_watched":
        mark_item_watched(item_id)

    elif selected_action == "mark_unwatched":
        mark_item_unwatched(item_id)

    elif selected_action == "delete":
        delete(item_id)

    elif selected_action == "show_extras":
        u = "/Users/{}/Items/{}/SpecialFeatures".format(api.user_id, item_id)
        action_url = ("plugin://plugin.video.jellycon/?url=" + quote(u) + "&mode=GET_CONTENT&media_type=Videos")
        built_in_command = 'ActivateWindow(Videos, ' + action_url + ', return)'
        xbmc.executebuiltin(built_in_command)

    elif selected_action == "view_season":
        xbmc.executebuiltin("Dialog.Close(all,true)")
        parent_id = result["ParentId"]
        series_id = result["SeriesId"]
        u = ('/Shows/' + series_id +
             '/Episodes'
             '?userId={}'.format(api.user_id) +
             '&seasonId=' + parent_id +
             '&IsVirtualUnAired=false' +
             '&IsMissing=false' +
             '&Fields=SpecialEpisodeNumbers,{}'.format(get_default_filters()) +
             '&format=json')
        action_url = ("plugin://plugin.video.jellycon/?url=" + quote(u) + "&mode=GET_CONTENT&media_type=Season")
        built_in_command = 'ActivateWindow(Videos, ' + action_url + ', return)'
        xbmc.executebuiltin(built_in_command)

    elif selected_action == "view_series":
        xbmc.executebuiltin("Dialog.Close(all,true)")

        series_id = result["SeriesId"]
        if not series_id:
            series_id = item_id

        u = ('/Shows/' + series_id +
             '/Seasons'
             '?userId={}'.format(api.user_id) +
             '&Fields={}'.format(get_default_filters()) +
             '&format=json')

        action_url = ("plugin://plugin.video.jellycon/?url=" + quote(u) + "&mode=GET_CONTENT&media_type=Series")

        if xbmc.getCondVisibility("Window.IsActive(home)"):
            built_in_command = 'ActivateWindow(Videos, ' + action_url + ', return)'
        else:
            built_in_command = 'Container.Update(' + action_url + ')'

        xbmc.executebuiltin(built_in_command)

    elif selected_action == "refresh_images":
        CacheArtwork().delete_cached_images(item_id)

    elif selected_action == "info":
        xbmc.executebuiltin("Dialog.Close(all,true)")
        xbmc.executebuiltin("Action(info)")


def show_content(params):
    log.debug("showContent Called: {0}".format(params))

    item_type = params.get("item_type")
    settings = xbmcaddon.Addon()
    group_movies = settings.getSetting('group_movies') == "true"

    if item_type.lower().find("movie") == -1:
        group_movies = False

    content_url = ("/Users/{}/Items".format(api.user_id) +
                   "?format=json" +
                   "&ImageTypeLimit=1" +
                   "&IsMissing=False" +
                   "&Fields={}".format(get_default_filters()) +
                   '&CollapseBoxSetItems=' + str(group_movies) +
                   '&GroupItemsIntoCollections=' + str(group_movies) +
                   "&Recursive=true" +
                   '&SortBy=Name' +
                   '&SortOrder=Ascending' +
                   "&IsVirtualUnaired=false" +
                   "&IncludeItemTypes=" + item_type)

    log.debug("showContent Content Url: {0}".format(content_url))
    get_content(content_url, params)


def search_results_person(params):

    handle = int(sys.argv[1])

    person_id = params.get("person_id")
    details_url = ('/Users/{}/Items'.format(api.user_id) +
                   '?PersonIds=' + person_id +
                   '&Recursive=true' +
                   '&Fields={}'.format(get_default_filters()) +
                   '&format=json')

    params["name_format"] = "Episode|episode_name_format"

    dir_items, detected_type, total_records = process_directory(details_url, None, params)

    log.debug('search_results_person results: {0}'.format(dir_items))
    log.debug('search_results_person detect_type: {0}'.format(detected_type))

    if detected_type is not None:
        # if the media type is not set then try to use the detected type
        log.debug("Detected content type: {0}".format(detected_type))
        content_type = None

        if detected_type == "Movie":
            content_type = 'movies'
        elif detected_type == "Episode":
            content_type = 'episodes'
        elif detected_type == "Series":
            content_type = 'tvshows'
        elif detected_type == "Music" or detected_type == "Audio" or detected_type == "Musicalbum":
            content_type = 'songs'

        if content_type:
            xbmcplugin.setContent(handle, content_type)

    if dir_items is not None:
        xbmcplugin.addDirectoryItems(handle, dir_items)

    xbmcplugin.endOfDirectory(handle, cacheToDisc=False)


def search_results(params):

    item_type = params.get('item_type')
    query_string = params.get('query')
    if query_string:
        log.debug("query_string : {0}".format(query_string))
        query_string = unquote(query_string)
        log.debug("query_string : {0}".format(query_string))

    item_type = item_type.lower()

    if item_type == 'movie':
        heading_type = translate_string(30231)
        content_type = 'movies'
    elif item_type == 'series':
        heading_type = translate_string(30229)
        content_type = 'tvshows'
    elif item_type == 'episode':
        heading_type = translate_string(30235)
        content_type = 'episodes'
        params["name_format"] = "Episode|episode_name_format"
    elif item_type == "music" or item_type == "audio" or item_type == "musicalbum":
        heading_type = 'Music'
        content_type = 'songs'
    elif item_type == "person":
        heading_type = 'Artists'
        content_type = 'artists'
    else:
        heading_type = item_type
        content_type = 'video'

    handle = int(sys.argv[1])

    if not query_string:
        home_window = HomeWindow()
        last_search = home_window.get_property("last_search")
        kb = xbmc.Keyboard()
        kb.setHeading(heading_type.capitalize() + ' ' + translate_string(30246).lower())
        kb.setDefault(last_search)
        kb.doModal()

        if kb.isConfirmed():
            user_input = kb.getText().strip()
        else:
            return

        home_window.set_property("last_search", user_input)
        log.debug('searchResults Called: {0}'.format(params))
        query = user_input

    else:
        query = query_string

    query = quote(query)
    log.debug("query : {0}".format(query))

    if (not item_type) or (not query):
        return

    # show a progress indicator if needed
    settings = xbmcaddon.Addon()
    progress = None
    if settings.getSetting('showLoadProgress') == "true":
        progress = xbmcgui.DialogProgress()
        progress.create(translate_string(30112))
        progress.update(0, translate_string(30113))

    # what type of search
    if item_type == "person":
        search_url = ("/Persons" +
                      "?searchTerm=" + query +
                      "&IncludePeople=true" +
                      "&IncludeMedia=false" +
                      "&IncludeGenres=false" +
                      "&IncludeStudios=false" +
                      "&IncludeArtists=false" +
                      "&Limit=16" +
                      "&Fields=PrimaryImageAspectRatio,BasicSyncInfo,ProductionYear" +
                      "&Recursive=true" +
                      "&EnableTotalRecordCount=false" +
                      "&ImageTypeLimit=1" +
                      "&userId={}".format(api.user_id))

        person_search_results = api.get(search_url)
        log.debug("Person Search Result : {0}".format(person_search_results))
        if person_search_results is None:
            return

        person_items = person_search_results.get("Items", [])

        server = settings.getSetting('server_address')
        list_items = []
        for item in person_items:
            person_id = item.get('Id')
            person_name = item.get('Name')
            person_thumbnail = get_art_url(item, "Primary", server=server)

            action_url = sys.argv[0] + "?mode=NEW_SEARCH_PERSON&person_id=" + person_id

            list_item = xbmcgui.ListItem(label=person_name, offscreen=True)
            list_item.setProperty("id", person_id)

            art_links = {}
            art_links["icon"] = "DefaultActor.png"
            if person_thumbnail:
                art_links["thumb"] = person_thumbnail
                art_links["poster"] = person_thumbnail
            list_item.setArt(art_links)

            item_tupple = (action_url, list_item, True)
            list_items.append(item_tupple)

        xbmcplugin.setContent(handle, 'artists')
        xbmcplugin.addDirectoryItems(handle, list_items)
        xbmcplugin.endOfDirectory(handle, cacheToDisc=False)

    else:
        search_url = ("/Users/{}/Items".format(api.user_id) +
                      "?searchTerm=" + query +
                      "&IncludePeople=false" +
                      "&IncludeMedia=true" +
                      "&IncludeGenres=false" +
                      "&IncludeStudios=false" +
                      "&IncludeArtists=false" +
                      "&IncludeItemTypes=" + item_type +
                      "&Limit=16" +
                      "&Fields={}".format(get_default_filters()) +
                      "&Recursive=true" +
                      "&EnableTotalRecordCount=false" +
                      "&ImageTypeLimit=1")

        # set content type
        xbmcplugin.setContent(handle, content_type)
        dir_items, detected_type, total_records = process_directory(search_url, progress, params)
        xbmcplugin.addDirectoryItems(handle, dir_items)
        xbmcplugin.endOfDirectory(handle, cacheToDisc=False)

    if progress is not None:
        progress.update(100, translate_string(30125))
        progress.close()


def play_action(params):
    log.debug("== ENTER: PLAY ==")

    log.debug("PLAY ACTION PARAMS: {0}".format(params))
    item_id = params.get("item_id")

    auto_resume = params.get("auto_resume", "-1")
    if auto_resume == 'None':
        auto_resume = '-1'
    if auto_resume:
        auto_resume = int(auto_resume)
    else:
        auto_resume = -1

    log.debug("AUTO_RESUME: {0}".format(auto_resume))

    force_transcode = params.get("force_transcode", None) is not None
    log.debug("FORCE_TRANSCODE: {0}".format(force_transcode))

    media_source_id = params.get("media_source_id", "")
    log.debug("media_source_id: {0}".format(media_source_id))

    subtitle_stream_index = params.get("subtitle_stream_index")
    log.debug("subtitle_stream_index: {0}".format(subtitle_stream_index))

    audio_stream_index = params.get("audio_stream_index")
    log.debug("audio_stream_index: {0}".format(audio_stream_index))

    action = params.get("action", "play")

    # set the current playing item id
    # set all the playback info, this will be picked up by the service
    # the service will then start the playback

    xbmc.Player().stop()

    play_info = {}
    play_info["action"] = action
    play_info["item_id"] = item_id
    play_info["auto_resume"] = str(auto_resume)
    play_info["force_transcode"] = force_transcode
    play_info["media_source_id"] = media_source_id
    play_info["subtitle_stream_index"] = subtitle_stream_index
    play_info["audio_stream_index"] = audio_stream_index
    log.info("Sending jellycon_play_action : {0}".format(play_info))
    play_file(play_info)


def play_item_trailer(item_id):
    log.debug("== ENTER: playTrailer ==")

    url = "/Users/{}/Items/{}/LocalTrailers?format=json".format(user_details.get('user_id'), item_id)

    result = api.get(url)

    if result is None:
        return

    log.debug("LocalTrailers {0}".format(result))
    count = 1

    trailer_names = []
    trailer_list = []
    for trailer in result:
        info = {}
        info["type"] = "local"
        name = trailer.get("Name")
        while not name or name in trailer_names:
            name = "Trailer " + str(count)
            count += 1
        info["name"] = name
        info["id"] = trailer.get("Id")
        count += 1
        trailer_names.append(name)
        trailer_list.append(info)

    url = "/Users/{}/Items/{}?format=json&Fields=RemoteTrailers".format(user_details.get('user_id'), item_id)
    result = api.get(url)
    log.debug("RemoteTrailers: {0}".format(result))
    count = 1

    if result is None:
        return

    remote_trailers = result.get("RemoteTrailers", [])
    for trailer in remote_trailers:
        info = {}
        info["type"] = "remote"
        url = trailer.get("Url", "none")
        if url.lower().find("youtube") != -1:
            info["url"] = url
            name = trailer.get("Name")
            while not name or name in trailer_names:
                name = "Trailer " + str(count)
                count += 1
            info["name"] = name
            trailer_names.append(name)
            trailer_list.append(info)

    log.debug("TrailerList: {0}".format(trailer_list))

    trailer_text = []
    for trailer in trailer_list:
        name = trailer.get("name") + " (" + trailer.get("type") + ")"
        trailer_text.append(name)

    dialog = xbmcgui.Dialog()
    resp = dialog.select(translate_string(30308), trailer_text)
    if resp > -1:
        trailer = trailer_list[resp]
        log.debug("SelectedTrailer: {0}".format(trailer))

        if trailer.get("type") == "local":
            params = {}
            params["item_id"] = trailer.get("id")
            play_action(params)

        elif trailer.get("type") == "remote":
            youtube_id = trailer.get("url").rsplit('=', 1)[1]
            youtube_plugin = "RunPlugin(plugin://plugin.video.youtube/play/?video_id=%s)" % youtube_id
            log.debug("youtube_plugin: {0}".format(youtube_plugin))

            xbmc.executebuiltin(youtube_plugin)
