import xbmc
import xbmcaddon
import xbmcgui
import xbmcvfs
import os
import simplejson
import hashlib
import urllib
from PIL import Image, ImageOps
from resources.lib.ImageOperations import MyGaussianBlur
from xml.dom.minidom import parse

ADDON = xbmcaddon.Addon()
ADDON_ID = ADDON.getAddonInfo('id')
ADDON_LANGUAGE = ADDON.getLocalizedString
ADDON_DATA_PATH = os.path.join(xbmc.translatePath("special://profile/addon_data/%s" % ADDON_ID))
HOME = xbmcgui.Window(10000)
SKINSETTINGS = xbmcgui.Window(10035)


def remove_quotes(label):
    if not label:
        return ""
    if label.startswith("'") and label.endswith("'") and len(label) > 2:
        label = label[1:-1]
        if label.startswith('"') and label.endswith('"') and len(label) > 2:
            label = label[1:-1]
    return label


def open_info_panel():
    listitems = ["Slot %i" % i for i in range(1, 20)]
    select_dialog = xbmcgui.Dialog()
    index = select_dialog.select("Choose Info Panel", listitems)
    if index == -1:
        return None
    HOME.setProperty("AllowedStyles", "_1_6_")
    SKINSETTINGS.setProperty("CustomYesNoDialog", "Icon%i" % index)
    prefix = xbmc.getInfoLabel("Window(skinsettings).Property(WidgetTargetPrefix)")
    selection = xbmc.getInfoLabel("Window(skinsettings).Property(WidgetSelection)")
    xbmc.executebuiltin("Skin.SetString(%s.%sTitle,InfoPanel %i)" % (prefix, selection, index))
    xbmc.executebuiltin("Skin.SetString(%s.%sContent,plugin://script.extendedinfo?info=iconpanel&&id=%i)" % (prefix, selection, index))
    xbmc.executebuiltin("ActivateWindow(1137)")


def AddArtToLibrary(type, media, folder, limit, silent=False):
    json_query = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.Get%ss", "params": {"properties": ["art", "file"], "sort": { "method": "label" } }, "id": 1}' % media.lower())
    json_query = unicode(json_query, 'utf-8', errors='ignore')
    json_response = simplejson.loads(json_query)
    if (json_response['result'] is not None) and ('%ss' % (media.lower()) in json_response['result']):
        # iterate through the results
        if not silent:
            progressDialog = xbmcgui.DialogProgress(ADDON_LANGUAGE(32016))
            progressDialog.create(ADDON_LANGUAGE(32016))
        for count, item in enumerate(json_response['result']['%ss' % media.lower()]):
            if not silent:
                if progressDialog.iscanceled():
                    return
            path = os.path.join(media_path(item['file']).encode("utf-8"), folder)
            file_list = xbmcvfs.listdir(path)[1]
            for i, file in enumerate(file_list):
                if i + 1 > limit:
                    break
                if not silent:
                    progressDialog.update((count * 100) / json_response['result']['limits']['total'], ADDON_LANGUAGE(32011) + ' %s: %s %i' % (item["label"], type, i + 1))
                    if progressDialog.iscanceled():
                        return
                file_path = os.path.join(path, file).encode('string-escape')
                if xbmcvfs.exists(file_path) and item['art'].get('%s%i' % (type, i), '') == "":
                    xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.Set%sDetails", "params": { "%sid": %i, "art": { "%s%i": "%s" }}, "id": 1 }' %
                                        (media, media.lower(), item.get('%sid' % media.lower()), type, i + 1, file_path))


def media_path(path):
    # Check for stacked movies
    try:
        path = os.path.split(path)[0].rsplit(' , ', 1)[1].replace(",,", ",")
    except:
        path = os.path.split(path)[0]
    # Fixes problems with rared movies and multipath
    if path.startswith("rar://"):
        path = os.path.split(urllib.url2pathname(path.replace("rar://", "")))[0]
    elif path.startswith("multipath://"):
        temp_path = path.replace("multipath://", "").split('%2f/')
        path = urllib.url2pathname(temp_path[0])
    return path


def import_skinsettings():
    data = read_from_file()
    if not data:
        log("backup not found")
    progressDialog = xbmcgui.DialogProgress(ADDON_LANGUAGE(32010))
    progressDialog.create(ADDON_LANGUAGE(32010))
    xbmc.sleep(200)
    for count, skinsetting in enumerate(data):
        if progressDialog.iscanceled():
            return
        if skinsetting[1].startswith(xbmc.getSkinDir()):
            progressDialog.update((count * 100) / len(data), ADDON_LANGUAGE(32011) + ' %s' % skinsetting[1])
            setting = skinsetting[1].replace(xbmc.getSkinDir() + ".", "")
            if skinsetting[0] == "string":
                if skinsetting[2] is not "":
                    xbmc.executebuiltin("Skin.SetString(%s,%s)" % (setting, skinsetting[2]))
                else:
                    xbmc.executebuiltin("Skin.Reset(%s)" % setting)
            elif skinsetting[0] == "bool":
                if skinsetting[2]:
                    xbmc.executebuiltin("Skin.SetBool(%s)" % setting)
                else:
                    xbmc.executebuiltin("Skin.Reset(%s)" % setting)
        xbmc.sleep(30)
    xbmcgui.Dialog().ok(ADDON_LANGUAGE(32005), ADDON_LANGUAGE(32009))


def export_skinsettings(filter_label=False):
    s_path = xbmc.translatePath('special://profile/addon_data/%s/settings.xml' % xbmc.getSkinDir()).decode("utf-8")
    if not xbmcvfs.exists(s_path):
        xbmcgui.Dialog().ok(ADDON_LANGUAGE(32007), ADDON_LANGUAGE(32008))
        log("settings.xml not found")
        return None
    log("settings.xml found")
    ls = []
    for count, skinsetting in enumerate(parse(s_path).documentElement.getElementsByTagName('setting')):
        s_id = skinsetting.attributes['id'].nodeValue
        s_type = skinsetting.attributes['type'].nodeValue
        if s_type == "string":
            s_value = xbmc.getInfoLabel("Skin.String(%s)" % s_id)
        else:
            s_value = bool(xbmc.getCondVisibility("Skin.HasSetting(%s)" % s_id))
        if not filter_label or filter_label in s_id:
            ls.append((s_type, s_id, s_value))
    if save_to_file(ls, xbmc.getSkinDir() + ".backup"):
        xbmcgui.Dialog().ok(ADDON_LANGUAGE(32005), ADDON_LANGUAGE(32006))


def Filter_Image(filterimage, radius):
    try:
        if not xbmcvfs.exists(ADDON_DATA_PATH):
            xbmcvfs.mkdir(ADDON_DATA_PATH)
        md5 = hashlib.md5(filterimage).hexdigest()
        filename = md5 + str(radius) + ".png"
        targetfile = os.path.join(ADDON_DATA_PATH, filename)
        cachedthumb = xbmc.getCacheThumbName(filterimage)
        xbmc_vid_cache_file = os.path.join("special://profile/Thumbnails/Video", cachedthumb[0], cachedthumb)
        xbmc_cache_file = os.path.join("special://profile/Thumbnails/", cachedthumb[0], cachedthumb[:-4] + ".jpg")
        if filterimage == "":
            return "", ""
        if not xbmcvfs.exists(targetfile):
            img = None
            for i in range(1, 4):
                try:
                    if xbmcvfs.exists(xbmc_cache_file):
                        log("image already in xbmc cache: " + xbmc_cache_file)
                        img = Image.open(xbmc.translatePath(xbmc_cache_file))
                        break
                    elif xbmcvfs.exists(xbmc_vid_cache_file):
                        log("image already in xbmc video cache: " + xbmc_vid_cache_file)
                        img = Image.open(xbmc.translatePath(xbmc_vid_cache_file))
                        break
                    else:
                        filterimage = urllib.unquote(filterimage.replace("image://", "")).decode('utf8')
                        if filterimage.endswith("/"):
                            filterimage = filterimage[:-1]
                        log("copy image from source: " + filterimage)
                        xbmcvfs.copy(filterimage, targetfile)
                        img = Image.open(targetfile)
                        break
                except:
                    log("Could not get image for %s (try %i)" % (filterimage, i))
                    xbmc.sleep(500)
            if not img:
                return "", ""
            img.thumbnail((200, 200), Image.ANTIALIAS)
            img = img.convert('RGB')
            imgfilter = MyGaussianBlur(radius=radius)
            img = img.filter(imgfilter)
            img.save(targetfile)
        else:
            log("blurred img already created: " + targetfile)
            img = Image.open(targetfile)
        imagecolor = Get_Colors(img)
        return targetfile, imagecolor
    except:
        return "", ""


def Get_Colors(img):
    width, height = img.size
    pixels = img.load()
    data = []
    for x in range(width / 2):
        for y in range(height / 2):
            cpixel = pixels[x * 2, y * 2]
            data.append(cpixel)
    r = 0
    g = 0
    b = 0
    counter = 0
    for x in range(len(data)):
        brightness = data[x][0] + data[x][1] + data[x][2]
        if brightness > 150 and brightness < 720:
            r += data[x][0]
            g += data[x][1]
            b += data[x][2]
            counter += 1
    if counter > 0:
        rAvg = int(r / counter)
        gAvg = int(g / counter)
        bAvg = int(b / counter)
        Avg = (rAvg + gAvg + bAvg) / 3
        minBrightness = 130
        if Avg < minBrightness:
            Diff = minBrightness - Avg
            if rAvg <= (255 - Diff):
                rAvg += Diff
            else:
                rAvg = 255
            if gAvg <= (255 - Diff):
                gAvg += Diff
            else:
                gAvg = 255
            if bAvg <= (255 - Diff):
                bAvg += Diff
            else:
                bAvg = 255
        imagecolor = "FF%s%s%s" % (format(rAvg, '02x'), format(gAvg, '02x'), format(bAvg, '02x'))
    else:
        imagecolor = "FFF0F0F0"
    log("Average Color: " + imagecolor)
    return imagecolor


def image_recolorize(src, black="#000099", white="#99CCFF"):
    # img = image_recolorize(img, black="#000000", white="#FFFFFF")
    """
    Returns a recolorized version of the initial image using a two-tone
    approach. The color in the black argument is used to replace black pixels
    and the color in the white argument is used to replace white pixels.

    The defaults set the image to a blue hued image.
    """
    return ImageOps.colorize(ImageOps.grayscale(src), black, white)


def save_to_file(content, filename, path=""):
    if path == "":
        path = get_browse_dialog()
        if not path:
            return ""
        text_file_path = "%s%s.txt" % (path, filename)
    else:
        if not xbmcvfs.exists(path):
            xbmcvfs.mkdir(path)
        text_file_path = os.path.join(path, filename + ".txt")
    log("save to textfile: " + text_file_path)
    text_file = xbmcvfs.File(text_file_path, "w")
    simplejson.dump(content, text_file)
    text_file.close()
    return True


def read_from_file(path=""):
    if path == "":
        path = get_browse_dialog(dlg_type=1)
    if xbmcvfs.exists(path):
        f = open(path)
        fc = simplejson.load(f)
        log("loaded textfile " + path)
        return fc
    else:
        return False


def JumpToLetter(letter):
    if not xbmc.getInfoLabel("ListItem.Sortletter")[0] == letter:
        xbmc.executebuiltin("SetFocus(50)")
        if letter in ["A", "B", "C", "2"]:
            jumpsms_id = "2"
        elif letter in ["D", "E", "F", "3"]:
            jumpsms_id = "3"
        elif letter in ["G", "H", "I", "4"]:
            jumpsms_id = "4"
        elif letter in ["J", "K", "L", "5"]:
            jumpsms_id = "5"
        elif letter in ["M", "N", "O", "6"]:
            jumpsms_id = "6"
        elif letter in ["P", "Q", "R", "S", "7"]:
            jumpsms_id = "7"
        elif letter in ["T", "U", "V", "8"]:
            jumpsms_id = "8"
        elif letter in ["W", "X", "Y", "Z", "9"]:
            jumpsms_id = "9"
        else:
            jumpsms_id = None
        if jumpsms_id:
            for i in range(1, 5):
                # xbmc.executebuiltin("jumpsms" + jumpsms_id)
                xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "method": "Input.ExecuteAction", "params": { "action": "jumpsms%s" }, "id": 1 }' % (jumpsms_id))
                # prettyprint(response)
                xbmc.sleep(15)
                if xbmc.getInfoLabel("ListItem.Sortletter")[0] == letter:
                    break
        xbmc.executebuiltin("SetFocus(24000)")


def CreateDialogSelect(header):
    selectionlist = []
    indexlist = []
    for i in range(1, 20):
        label = xbmc.getInfoLabel("Window.Property(Dialog.%i.Label)" % (i))
        if label == "":
            break
        elif label != "none" and label != "-":
            selectionlist.append(label)
            indexlist.append(i)
    if selectionlist:
        select_dialog = xbmcgui.Dialog()
        index = select_dialog.select(header, selectionlist)
        if index > -1:
            value = xbmc.getInfoLabel("Window.Property(Dialog.%i.Builtin)" % (indexlist[index]))
            for builtin in value.split("||"):
                xbmc.executebuiltin(builtin)
                xbmc.sleep(30)
    for i in range(1, 20):
        xbmc.executebuiltin("ClearProperty(Dialog.%i.Builtin)" % (i))
        xbmc.executebuiltin("ClearProperty(Dialog.%i.Label)" % (i))


def CreateDialogOK(header, line1):
    dialog = xbmcgui.Dialog()
    dialog.ok(header, line1)


def CreateDialogYesNo(header="", line1="", nolabel="", yeslabel="", noaction="", yesaction=""):
    if yeslabel == "":
        yeslabel = xbmc.getInfoLabel("Window.Property(Dialog.yes.Label)")
        if yeslabel == "":
            yeslabel = xbmc.getLocalizedString(107)
    if nolabel == "":
        nolabel = xbmc.getInfoLabel("Window.Property(Dialog.no.Label)")
        if nolabel == "":
            nolabel = xbmc.getLocalizedString(106)
    if yesaction == "":
        yesaction = xbmc.getInfoLabel("Window.Property(Dialog.yes.Builtin)")
    if noaction == "":
        noaction = xbmc.getInfoLabel("Window.Property(Dialog.no.Builtin)")
    dialog = xbmcgui.Dialog()
    ret = dialog.yesno(heading=header, line1=line1, nolabel=nolabel, yeslabel=yeslabel)  # autoclose missing
    if ret:
        for builtin in yesaction.split("||"):
            xbmc.executebuiltin(builtin)
            xbmc.sleep(30)
    else:
        for builtin in noaction.split("||"):
            xbmc.executebuiltin(builtin)
            xbmc.sleep(30)
    xbmc.executebuiltin("ClearProperty(Dialog.yes.Label")
    xbmc.executebuiltin("ClearProperty(Dialog.no.Label")
    xbmc.executebuiltin("ClearProperty(Dialog.yes.Builtin")
    xbmc.executebuiltin("ClearProperty(Dialog.no.Builtin")
    return ret


def CreateNotification(header="", message="", icon=None, time=5000, sound=True):
    sound = sound not in ["False", "false"]
    dialog = xbmcgui.Dialog()
    dialog.notification(heading=header, message=message, icon=icon, time=time, sound=sound)


def GetSortLetters(path, focusedletter):
    listitems = []
    letterlist = []
    HOME.clearProperty("LetterList")
    if ADDON.getSetting("FolderPath") == path:
        letterlist = ADDON.getSetting("LetterList")
        letterlist = letterlist.split()
    else:
        if path:
            json_query = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "Files.GetDirectory", "params": {"directory": "%s", "media": "files"}, "id": 1}' % (path))
            json_query = unicode(json_query, 'utf-8', errors='ignore')
            json_response = simplejson.loads(json_query)
            if "result" in json_response and "files" in json_response["result"]:
                for movie in json_response["result"]["files"]:
                    sortletter = movie["label"].replace("The ", "")[0]
                    if sortletter not in letterlist:
                        letterlist.append(sortletter)
            ADDON.setSetting("LetterList", " ".join(letterlist))
            ADDON.setSetting("FolderPath", path)
    HOME.setProperty("LetterList", "".join(letterlist))
    if letterlist and focusedletter:
        startord = ord("A")
        for i in range(0, 26):
            letter = chr(startord + i)
            if letter == focusedletter:
                label = "[B][COLOR FFFF3333]%s[/COLOR][/B]" % letter
            elif letter in letterlist:
                label = letter
            else:
                label = "[COLOR 55FFFFFF]%s[/COLOR]" % letter
            listitem = {"label": label}
            listitems.append(listitem)
    return listitems


def GetFavouriteswithType(favtype):
    favs = GetFavourites()
    favlist = []
    for fav in favs:
        if fav["Type"] == favtype:
            favlist.append(fav)
    return favlist


def GetFavPath(fav):
    if fav["type"] == "media":
        path = "PlayMedia(%s)" % (fav["path"])
    elif fav["type"] == "script":
        path = "RunScript(%s)" % (fav["path"])
    else:
        path = "ActivateWindow(%s,%s)" % (fav["window"], fav["windowparameter"])
    return path


def GetFavourites():
    items = []
    json_query = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "Favourites.GetFavourites", "params": {"type": null, "properties": ["path", "thumbnail", "window", "windowparameter"]}, "id": 1}')
    json_query = unicode(json_query, 'utf-8', errors='ignore')
    json_query = simplejson.loads(json_query)
    if json_query["result"]["limits"]["total"] > 0:
        for fav in json_query["result"]["favourites"]:
            path = GetFavPath(fav)
            newitem = {'Label': fav["title"],
                       'Thumb': fav["thumbnail"],
                       'Type': fav["type"],
                       'Builtin': path,
                       'Path': "plugin://script.extendedinfo/?info=action&&id=" + path}
            items.append(newitem)
    return items


def log(txt):
    if isinstance(txt, str):
        txt = txt.decode("utf-8")
    message = u'%s: %s' % (ADDON_ID, txt)
    xbmc.log(msg=message.encode("utf-8"), level=xbmc.LOGDEBUG)


def get_browse_dialog(default="", heading="Browse", dlg_type=3, shares="files", mask="", use_thumbs=False, treat_as_folder=False):
    dialog = xbmcgui.Dialog()
    value = dialog.browse(dlg_type, heading, shares, mask, use_thumbs, treat_as_folder, default)
    return value


def Notify(header, line='', line2='', line3=''):
    xbmc.executebuiltin('Notification(%s, %s, %s, %s)' % (header, line, line2, line3))


def prettyprint(string):
    log(simplejson.dumps(string, sort_keys=True, indent=4, separators=(',', ': ')))


def passHomeDataToSkin(data, debug=False):
    if data is not None:
        for (key, value) in data.iteritems():
            HOME.setProperty('%s' % (str(key)), unicode(value))
            if debug:
                log('%s' % (str(key)) + unicode(value))


def passDataToSkin(name, data, prefix="", debug=False):
        if prefix and not prefix.endswith("."):
            prefix += "."
        SetWindowProperties(name, data, prefix, debug)


def SetWindowProperties(name, data, prefix="", debug=False):
    if data is not None:
        # log( "%s%s.Count = %s" % (prefix, name, str(len(data)) ) )
        for (count, result) in enumerate(data):
            if debug:
                log("%s%s.%i = %s" % (prefix, name, count + 1, str(result)))
            for (key, value) in result.iteritems():
                HOME.setProperty('%s%s.%i.%s' % (prefix, name, count + 1, str(key)), unicode(value))
                if debug:
                    log('%s%s.%i.%s --> ' % (prefix, name, count + 1, str(key)) + unicode(value))
        HOME.setProperty('%s%s.Count' % (prefix, name), str(len(data)))
    else:
        HOME.setProperty('%s%s.Count' % (prefix, name), '0')
        log("%s%s.Count = None" % (prefix, name))