# -*- coding: utf-8 -*-
import os

try:
    from urllib import urlencode
except:
    from urllib.parse import urlencode

import xml.etree.ElementTree
import xbmcvfs
import xbmcgui
import database.database
import database.emby_db
import helper.api
import helper.loghandler

class Views():
    def __init__(self, Embyserver):
        self.EmbyServer = Embyserver
        self.limit = 25
        self.media_folders = None
        self.LOG = helper.loghandler.LOG('EMBY.emby.views.Views')
        self.APIHelper = helper.api.API(self.EmbyServer.Utils)
        self.LibraryIcons = {}
        self.NODES = {
            'tvshows': [
                ('letter', "A-Z", 'special://home/addons/plugin.video.emby-next-gen/resources/letter.png'),
                ('all', None, 'DefaultTVShows.png'),
                ('recentlyadded', self.EmbyServer.Utils.Translate(30170), 'DefaultRecentlyAddedEpisodes.png'),
                ('recentlyaddedepisodes', self.EmbyServer.Utils.Translate(30175), 'DefaultRecentlyAddedEpisodes.png'),
                ('inprogress', self.EmbyServer.Utils.Translate(30171), 'DefaultInProgressShows.png'),
                ('inprogressepisodes', self.EmbyServer.Utils.Translate(30178), 'DefaultInProgressShows.png'),
                ('genres', "Genres", 'DefaultGenre.png'),
                ('random', self.EmbyServer.Utils.Translate(30229), 'special://home/addons/plugin.video.emby-next-gen/resources/random.png'),
                ('recommended', self.EmbyServer.Utils.Translate(30230), 'DefaultFavourites.png'),
                ('years', self.EmbyServer.Utils.Translate(33218), 'DefaultYear.png'),
                ('actors', self.EmbyServer.Utils.Translate(33219), 'DefaultActor.png'),
                ('tags', self.EmbyServer.Utils.Translate(33220), 'DefaultTags.png'),
                ('unwatched', "Unwatched TV Shows", 'OverlayUnwatched.png'),
                ('unwatchedepisodes', "Unwatched Episodes", 'OverlayUnwatched.png'),
                ('studios', "Studios", 'DefaultStudios.png'),
                ('recentlyplayed', 'Recently played TV Show', 'DefaultMusicRecentlyPlayed.png'),
                ('recentlyplayedepisode', 'Recently played Episode', 'DefaultMusicRecentlyPlayed.png'),
                ('nextepisodes', self.EmbyServer.Utils.Translate(30179), 'DefaultInProgressShows.png')
            ],
            'movies': [
                ('letter', "A-Z", 'special://home/addons/plugin.video.emby-next-gen/resources/letter.png'),
                ('all', None, 'DefaultMovies.png'),
                ('recentlyadded', self.EmbyServer.Utils.Translate(30174), 'DefaultRecentlyAddedMovies.png'),
                ('inprogress', self.EmbyServer.Utils.Translate(30177), 'DefaultInProgressShows.png'),
                ('unwatched', self.EmbyServer.Utils.Translate(30189), 'OverlayUnwatched.png'),
                ('sets', "Sets", 'DefaultSets.png'),
                ('genres', "Genres", 'DefaultGenre.png'),
                ('random', self.EmbyServer.Utils.Translate(30229), 'special://home/addons/plugin.video.emby-next-gen/resources/random.png'),
                ('recommended', self.EmbyServer.Utils.Translate(30230), 'DefaultFavourites.png'),
                ('years', self.EmbyServer.Utils.Translate(33218), 'DefaultYear.png'),
                ('actors', self.EmbyServer.Utils.Translate(33219), 'DefaultActor.png'),
                ('tags', self.EmbyServer.Utils.Translate(33220), 'DefaultTags.png'),
                ('studios', "Studios", 'DefaultStudios.png'),
                ('recentlyplayed', 'Recently played', 'DefaultMusicRecentlyPlayed.png'),
                ('directors', 'Directors', 'DefaultDirector.png'),
                ('countries', 'Countries', 'DefaultCountry.png')
            ],
            'musicvideos': [
                ('letter', "A-Z", 'special://home/addons/plugin.video.emby-next-gen/resources/letter.png'),
                ('all', None, 'DefaultMusicVideos.png'),
                ('recentlyadded', self.EmbyServer.Utils.Translate(30256), 'DefaultRecentlyAddedMusicVideos.png'),
                ('years', self.EmbyServer.Utils.Translate(33218), 'DefaultMusicYears.png'),
                ('genres', "Genres", 'DefaultGenre.png'),
                ('inprogress', self.EmbyServer.Utils.Translate(30257), 'DefaultInProgressShows.png'),
                ('random', self.EmbyServer.Utils.Translate(30229), 'special://home/addons/plugin.video.emby-next-gen/resources/random.png'),
                ('unwatched', self.EmbyServer.Utils.Translate(30258), 'OverlayUnwatched.png'),
                ('artists', "Artists", 'DefaultMusicArtists.png'),
                ('albums', "Albums", 'DefaultMusicAlbums.png'),
                ('recentlyplayed', 'Recently played', 'DefaultMusicRecentlyPlayed.png')
            ],
            'music': [
                ('letter', "A-Z", 'special://home/addons/plugin.video.emby-next-gen/resources/letter.png'),
                ('all', None, 'DefaultAddonMusic.png'),
                ('years', self.EmbyServer.Utils.Translate(33218), 'DefaultMusicYears.png'),
                ('genres', "Genres", 'DefaultMusicGenres.png'),
                ('artists', "Artists", 'DefaultMusicArtists.png'),
                ('albums', "Albums", 'DefaultMusicAlbums.png'),
                ('recentlyaddedalbums', 'Recently added albums', 'DefaultMusicRecentlyAdded.png'),
                ('recentlyaddedsongs', 'Recently added songs', 'DefaultMusicRecentlyAdded.png'),
                ('recentlyplayed', 'Recently played', 'DefaultMusicRecentlyPlayed.png'),
                ('randomalbums', 'Random albums', 'special://home/addons/plugin.video.emby-next-gen/resources/random.png'),
                ('randomsongs', 'Random songs', 'special://home/addons/plugin.video.emby-next-gen/resources/random.png')
            ]
        }

    def IconDownload(self, URL, FileID):
        request = {'type': "GET", 'url': URL, 'params': {}}
        Filename = self.EmbyServer.Utils.PathToFilenameReplaceSpecialCharecters(FileID)# + ".jpg")
        FilePath = self.EmbyServer.Utils.translatePath("special://profile/addon_data/plugin.video.emby-next-gen/temp/") + Filename

        if not xbmcvfs.exists(FilePath):
            return self.EmbyServer.Utils.download_file_from_Embyserver(request, Filename, self.EmbyServer)

        return FilePath

    def add_favorites(self, index, view):
        path = self.EmbyServer.Utils.translatePath("special://profile/library/video")
        filepath = os.path.join(path, "emby_%s.xml" % view['Tag'].replace(" ", ""))

        try:
            xmlData = xml.etree.ElementTree.parse(filepath).getroot()
        except Exception:
            if view['Media'] == 'episodes':
                xmlData = xml.etree.ElementTree.Element('node', {'order': str(index), 'type': "folder"})
            else:
                xmlData = xml.etree.ElementTree.Element('node', {'order': str(index), 'type': "filter"})

            xml.etree.ElementTree.SubElement(xmlData, 'icon').text = self.EmbyServer.Utils.translatePath("special://home/addons/plugin.video.emby-next-gen/resources/DefaultFavourites.png")
            xml.etree.ElementTree.SubElement(xmlData, 'label')
            xml.etree.ElementTree.SubElement(xmlData, 'match')
            xml.etree.ElementTree.SubElement(xmlData, 'content')

        label = xmlData.find('label')
        label.text = view['Name']
        content = xmlData.find('content')
        content.text = view['Media']
        match = xmlData.find('match')
        match.text = "all"

        if view['Media'] != 'episodes':
            for rule in xmlData.findall('.//value'):
                if rule.text == view['Tag']:
                    break
            else:
                rule = xml.etree.ElementTree.SubElement(xmlData, 'rule', {'field': "tag", 'operator': "is"})
                xml.etree.ElementTree.SubElement(rule, 'value').text = view['Tag']

            self.node_all(xmlData)
        else:
            params = {
                'mode': "browse",
                'type': "Episode",
                'folder': 'FavEpisodes'
            }
            path = "%s?%s" % ("plugin://plugin.video.emby-next-gen/", urlencode(params))
            self.node_favepisodes(xmlData, path)

        self.EmbyServer.Utils.indent(xmlData, 0)
        self.EmbyServer.Utils.write_xml(xml.etree.ElementTree.tostring(xmlData, 'UTF-8'), filepath)

    def update_nodes(self):
        index = 0

        #Favorites
        for single in [{'Name': self.EmbyServer.Utils.Translate('fav_movies'), 'Tag': "Favorite movies", 'Media': "movies"}, {'Name': self.EmbyServer.Utils.Translate('fav_tvshows'), 'Tag': "Favorite tvshows", 'Media': "tvshows"}, {'Name': self.EmbyServer.Utils.Translate('fav_episodes'), 'Tag': "Favorite episodes", 'Media': "episodes"}]:
            self.add_favorites(index, single)
            index += 1

        #Specific nodes
        with database.database.Database(self.EmbyServer.Utils, 'emby', False) as embydb:
            db = database.emby_db.EmbyDatabase(embydb.cursor)

            #update nodes and playlist
            for library in self.EmbyServer.Utils.SyncData['Whitelist']:
                library = library.replace('Mixed:', "")
                view = db.get_view(library)

                if view:
                    view = {'LibraryId': library, 'Name': view[1], 'Tag': view[1], 'Media': view[2], "Icon": self.LibraryIcons[library], 'NameClean': self.EmbyServer.Utils.StringDecode(view[1]).replace(" ", ""), 'MediaClean': view[2].replace(" ", "")}

                    if view['Media'] == 'music':
                        node_path = self.EmbyServer.Utils.translatePath("special://profile/library/music")
                        playlist_path = self.EmbyServer.Utils.translatePath("special://profile/playlists/music")
                    else:
                        node_path = self.EmbyServer.Utils.translatePath("special://profile/library/video")
                        playlist_path = self.EmbyServer.Utils.translatePath("special://profile/playlists/video")

                    if view['Media'] == 'mixed':
                        for media in ('movies', 'tvshows'):
                            view['Media'] = media
                            view['MediaClean'] = media.replace(" ", "")
                            self.add_playlist(playlist_path, view, True)
                            self.add_nodes(node_path, view)

                        index += 1 # Compensate for the duplicate.
                    else:
                        self.add_playlist(playlist_path, view, False)
                        self.add_nodes(node_path, view)

                    index += 1

        node_path = self.EmbyServer.Utils.translatePath("special://profile/library/video")
        playlist_path = self.EmbyServer.Utils.translatePath("special://profile/playlists/video")
        self.window_nodes()

    def window_nodes(self):
        with database.database.Database(self.EmbyServer.Utils, 'emby', False) as embydb:
            libraries = database.emby_db.EmbyDatabase(embydb.cursor).get_views()

        for library in libraries:
            if library[0] in self.LibraryIcons:
                icon = self.LibraryIcons[library[0]]
            else:
                icon = None

            if not icon:
                if library[2] == 'tvshows':
                    icon = 'DefaultTVShows.png'
                elif library[2] == 'movies':
                    icon = 'DefaultMovies.png'
                elif library[2] == 'musicvideos':
                    icon = 'DefaultMusicVideos.png'
                elif library[2] == 'music':
                    icon = 'DefaultMusicVideos.png'
                else:
                    icon = self.EmbyServer.Utils.translatePath("special://home/addons/plugin.video.emby-next-gen/resources/icon.png")

            view = {'LibraryId': library[0], 'Name': library[1], 'Tag': library[1], 'Media': library[2], 'Icon': icon, 'NameClean': self.EmbyServer.Utils.StringDecode(library[1]).replace(" ", ""), 'MediaClean': library[2].replace(" ", "")}

            if library[0] in [x.replace('Mixed:', "") for x in self.EmbyServer.Utils.SyncData['Whitelist']]: # Synced libraries
                if view['Media'] in ('movies', 'tvshows', 'musicvideos', 'mixed', 'music'):
                    if view['Media'] == 'mixed':
                        for media in ('movies', 'tvshows'):
                            temp_view = view
                            temp_view['Media'] = media
                            temp_view['MediaClean'] = media.replace(" ", "")
                            self.window_node(temp_view, False, True)
                    else:
                        self.window_node(view, False, False)
            else: #Dynamic entry
                self.window_node(view, True, False)

    #Leads to another listing of nodes
    def window_node(self, view, dynamic, mixed):
        NodeData = {}

        if dynamic:
            params = {
                'mode': "browse",
                'type': view['Media'],
                'name': view['Name'].encode('utf-8'),
                'server': self.EmbyServer.server_id
            }

            if view.get('LibraryId'):
                params['id'] = view['LibraryId']

            path = "%s?%s" % ("plugin://plugin.video.emby-next-gen/", urlencode(params))
            NodeData['title'] = "%s (%s)" % (view['Name'], self.EmbyServer.Data['auth.server-name'])
        else:
            if view['Media'] == 'music':
                path = "library://music/emby_%s_%s" % (view['MediaClean'], view['NameClean'])
            else:
                path = "library://video/emby_%s_%s" % (view['MediaClean'], view['NameClean'])

            if mixed:
                NodeData['title'] = "%s (%s)" % (view['Name'], view['Media'])
            else:
                NodeData['title'] = view['Name']

        NodeData['path'] = path
        NodeData['id'] = view['LibraryId']
        NodeData['type'] = view['Media']
        NodeData['icon'] = view['Icon']
        self.EmbyServer.Nodes.append(NodeData)

    def update_views(self):
        ViewsData = self.EmbyServer.API.get_views()['Items']
        Total = len(ViewsData)
        Counter = 1
        Progress = xbmcgui.DialogProgressBG()
        Progress.create(self.EmbyServer.Utils.Translate('addon_name'), "Update views")
        self.EmbyServer.Utils.SyncData['SortedViews'] = [x['Id'] for x in ViewsData]

        with database.database.Database(self.EmbyServer.Utils, 'emby', True) as embydb:
            for library in ViewsData:
                Percent = int(Counter / Total * 100)
                Counter += 1
                Progress.update(Percent, message="Update views")

                if library['Type'] == 'Channel':
                    library['Media'] = "channels"
                else:
                    library['Media'] = library.get('CollectionType', "mixed")

                database.emby_db.EmbyDatabase(embydb.cursor).add_view(library['Id'], library['Name'], library['Media'], self.EmbyServer.server_id)

                #Cache artwork
                icon = self.APIHelper.get_artwork(library['Id'], 'Primary', None, [('Index', 0), ('api_key', self.EmbyServer.Data['auth.token'])], self.EmbyServer.Data['auth.server'])
                iconpath = self.IconDownload(icon, "%s_%s" % (self.EmbyServer.Data['auth.server-name'], library['Id']))
                self.LibraryIcons[library['Id']] = iconpath

        Progress.close()

    def remove_library(self, view_id):
        self.delete_playlist_by_id(view_id)
        self.delete_node_by_id(view_id)
        whitelist = self.EmbyServer.Utils.SyncData['Whitelist']

        if view_id in whitelist:
            whitelist.remove(view_id)

        self.EmbyServer.Utils.save_sync(self.EmbyServer.Utils.SyncData)
        self.update_nodes()

    #Create or update the xps file
    def add_playlist(self, path, view, mixed):
        filepath = os.path.join(path, "emby_%s.xsp" % (view['Name'].replace(" ", "_")))

        try:
            xmlData = xml.etree.ElementTree.parse(filepath).getroot()
        except Exception:
            xmlData = xml.etree.ElementTree.Element('smartplaylist', {'type': view['Media']})
            xml.etree.ElementTree.SubElement(xmlData, 'name')
            xml.etree.ElementTree.SubElement(xmlData, 'match')

        name = xmlData.find('name')
        name.text = view['Name'] if not mixed else "%s (%s)" % (view['Name'], view['Media'])
        match = xmlData.find('match')
        match.text = "all"

        for rule in xmlData.findall('.//value'):
            if rule.text == view['Tag']:
                break
        else:
            rule = xml.etree.ElementTree.SubElement(xmlData, 'rule', {'field': "tag", 'operator': "is"})
            xml.etree.ElementTree.SubElement(rule, 'value').text = view['Tag']

        self.EmbyServer.Utils.indent(xmlData, 0)
        self.EmbyServer.Utils.write_xml(xml.etree.ElementTree.tostring(xmlData, 'UTF-8'), filepath)

    #Create or update the video node file
    def add_nodes(self, path, view):
        folder = os.path.join(path, "emby_%s_%s" % (view['MediaClean'], view['NameClean']))

        if not xbmcvfs.exists(folder):
            xbmcvfs.mkdir(folder)

        #index.xml (root)
        filepath = os.path.join(folder, "index.xml")

        if not xbmcvfs.exists(filepath):
            xmlData = xml.etree.ElementTree.Element('node', {'order': "0"})
            xml.etree.ElementTree.SubElement(xmlData, 'label').text = "EMBY: %s (%s)" % (view['Name'], view['Media'])

            if view['Icon']:
                Icon = view['Icon']
            else:
                if view['Media'] == 'tvshows':
                    Icon = 'DefaultTVShows.png'
                elif view['Media'] == 'movies':
                    Icon = 'DefaultMovies.png'
                elif view['Media'] == 'musicvideos':
                    Icon = 'DefaultMusicVideos.png'
                elif view['Media'] == 'music':
                    Icon = 'DefaultMusicVideos.png'
                else:
                    Icon = self.EmbyServer.Utils.translatePath("special://home/addons/plugin.video.emby-next-gen/resources/icon.png")

            xml.etree.ElementTree.SubElement(xmlData, 'icon').text = Icon
            self.EmbyServer.Utils.indent(xmlData, 0)
            self.EmbyServer.Utils.write_xml(xml.etree.ElementTree.tostring(xmlData, 'UTF-8'), filepath)

        #specific nodes
        for node in self.NODES[view['Media']]:
            if node[1]:
                xml_label = node[1] #Specific
            else:
                xml_label = view['Name'] #All

            if node[0] == "letter":
                self.node_letter(view, folder, node)
            else:
                filepath = os.path.join(folder, "%s.xml" % node[0])

                if not xbmcvfs.exists(filepath):
                    if node[0] == 'nextepisodes':
                        NodeType = 'folder'
                    else:
                        NodeType = 'filter'

                    xmlData = xml.etree.ElementTree.Element('node', {'order': str(self.NODES[view['Media']].index(node)), 'type': NodeType})
                    xml.etree.ElementTree.SubElement(xmlData, 'label').text = xml_label
                    xml.etree.ElementTree.SubElement(xmlData, 'match').text = "all"
                    xml.etree.ElementTree.SubElement(xmlData, 'content')
                    xml.etree.ElementTree.SubElement(xmlData, 'icon').text = node[2]
                    operator = "is"
                    field = "tag"
                    content = xmlData.find('content')

                    if view['Media'] == "music":
                        if node[0] in ("genres", "artists"):
                            content.text = "artists"
                            field = "disambiguation"

                        elif node[0] in ("years", "recentlyaddedalbums", "randomalbums", "albums"):
                            content.text = "albums"
                            field = "type"

                        elif node[0] in ("recentlyaddedsongs", "randomsongs", "all", "recentlyplayed"):
                            content.text = "songs"
                            operator = "contains"
                            field = "comment"
                    else:
                        if node[0] in ("recentlyaddedepisodes", "inprogressepisodes", "recentlyplayedepisode"):
                            content.text = "episodes"
                        else:
                            content.text = view['Media']

                    for rule in xmlData.findall('.//value'):
                        if rule.text == view['Tag']:
                            break
                    else:
                        rule = xml.etree.ElementTree.SubElement(xmlData, 'rule', {'field': field, 'operator': operator})
                        xml.etree.ElementTree.SubElement(rule, 'value').text = view['Tag']

                    if node[0] == 'nextepisodes':
                        self.node_nextepisodes(xmlData, view['Name'])
                    else:
                        getattr(self, 'node_' + node[0])(xmlData) # get node function based on node type

                    self.EmbyServer.Utils.indent(xmlData, 0)
                    self.EmbyServer.Utils.write_xml(xml.etree.ElementTree.tostring(xmlData, 'UTF-8'), filepath)

    def node_letter(self, View, folder, node):
        Index = 1
        FolderPath = os.path.join(folder, "letter/")

        if not xbmcvfs.exists(FolderPath):
            xbmcvfs.mkdir(FolderPath)

        #index.xml
        FileName = os.path.join(FolderPath, "index.xml")

        if not xbmcvfs.exists(FileName):
            xmlData = xml.etree.ElementTree.Element('node')
            xmlData.set('order', '0')
            xmlData.set('type', "folder")
            xml.etree.ElementTree.SubElement(xmlData, "label").text = node[1]
            xml.etree.ElementTree.SubElement(xmlData, 'icon').text = self.EmbyServer.Utils.translatePath(node[2])
            self.EmbyServer.Utils.indent(xmlData, 0)
            self.EmbyServer.Utils.write_xml(xml.etree.ElementTree.tostring(xmlData, 'UTF-8'), FileName)

        #0-9.xml
        FileName = os.path.join(FolderPath, "0-9.xml")

        if not xbmcvfs.exists(FileName):
            xmlData = xml.etree.ElementTree.Element('node')
            xmlData.set('order', str(Index))
            xmlData.set('type', "filter")
            xml.etree.ElementTree.SubElement(xmlData, "label").text = "0-9"
            xml.etree.ElementTree.SubElement(xmlData, "match").text = "all"

            if View['Media'] == "music":
                xml.etree.ElementTree.SubElement(xmlData, "content").text = "artists"
            else:
                xml.etree.ElementTree.SubElement(xmlData, "content").text = View['Media']

            xmlRule = xml.etree.ElementTree.SubElement(xmlData, "rule")
            xmlRule.text = View['Tag']

            if View['Media'] == "music":
                xmlRule.set('field', "disambiguation")
            else:
                xmlRule.set('field', "tag")

            xmlRule.set('operator', "is")
            xmlRule = xml.etree.ElementTree.SubElement(xmlData, "rule")

            if View['Media'] == "music":
                xmlRule.set('field', "artist")
            else:
                xmlRule.set('field', "sorttitle")

            xmlRule.set('operator', "startswith")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = "0"
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = "1"
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = "2"
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = "3"
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = "4"
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = "5"
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = "6"
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = "7"
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = "8"
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = "9"
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("&")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("Ä")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("Ö")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("Ü")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("!")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("(")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode(")")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("@")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("#")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("$")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("^")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("*")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("-")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("=")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("+")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("{")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("}")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("[")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("]")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("?")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode(":")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode(";")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("'")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode(",")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode(".")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("<")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode(">")
            xml.etree.ElementTree.SubElement(xmlRule, "value").text = self.EmbyServer.Utils.StringDecode("~")
            xml.etree.ElementTree.SubElement(xmlData, 'order', {'direction': "ascending"}).text = "sorttitle"
            self.EmbyServer.Utils.indent(xmlData, 0)
            self.EmbyServer.Utils.write_xml(xml.etree.ElementTree.tostring(xmlData, 'UTF-8'), FileName)

            #Alphabetically
            FileNames = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]

            for FileName in FileNames:
                Index += 1
                FilePath = os.path.join(FolderPath, "%s.xml" % FileName)

                if not xbmcvfs.exists(FilePath):
                    xmlData = xml.etree.ElementTree.Element('node')
                    xmlData.set('order', str(Index))
                    xmlData.set('type', "filter")
                    xml.etree.ElementTree.SubElement(xmlData, "label").text = FileName
                    xml.etree.ElementTree.SubElement(xmlData, "match").text = "all"

                    if View['Media'] == "music":
                        xml.etree.ElementTree.SubElement(xmlData, "content").text = "artists"
                    else:
                        xml.etree.ElementTree.SubElement(xmlData, "content").text = View['Media']

                    xmlRule = xml.etree.ElementTree.SubElement(xmlData, "rule")
                    xmlRule.text = View['Tag']

                    if View['Media'] == "music":
                        xmlRule.set('field', "disambiguation")
                    else:
                        xmlRule.set('field', "tag")

                    xmlRule.set('operator', "is")
                    xmlRule = xml.etree.ElementTree.SubElement(xmlData, "rule")
                    xmlRule.text = FileName

                    if View['Media'] == "music":
                        xmlRule.set('field', "artist")
                    else:
                        xmlRule.set('field', "sorttitle")

                    xmlRule.set('operator', "startswith")
                    xml.etree.ElementTree.SubElement(xmlData, 'order', {'direction': "ascending"}).text = "sorttitle"
                    self.EmbyServer.Utils.indent(xmlData, 0)
                    self.EmbyServer.Utils.write_xml(xml.etree.ElementTree.tostring(xmlData, 'UTF-8'), FilePath)

    def delete_playlist(self, path):
        xbmcvfs.delete(path)
        self.LOG.info("DELETE playlist %s" % path)

    #Remove all emby playlists
    def delete_playlists(self):
        path = self.EmbyServer.Utils.translatePath("special://profile/playlists/video/")
        _, files = xbmcvfs.listdir(path)

        for filename in files:
            if filename.startswith('emby'):
                self.delete_playlist(os.path.join(path, filename))

    #Remove playlist based based on view_id
    def delete_playlist_by_id(self, view_id):
        path = self.EmbyServer.Utils.translatePath("special://profile/playlists/video/")
        _, files = xbmcvfs.listdir(path)

        for filename in files:
            if filename.startswith('emby') and filename.endswith('%s.xsp' % view_id):
                self.delete_playlist(os.path.join(path, filename))

    def delete_node(self, path):
        xbmcvfs.delete(path)
        self.LOG.info("DELETE node %s" % path)

    #Remove node and children files
    def delete_nodes(self):
        path = self.EmbyServer.Utils.translatePath("special://profile/library/video/")
        dirs, files = xbmcvfs.listdir(path)

        for filename in files:
            if filename.startswith('emby'):
                self.delete_node(os.path.join(path, filename))

        for directory in dirs:
            if directory.startswith('emby'):
                _, files = xbmcvfs.listdir(os.path.join(path, directory))

                for filename in files:
                    self.delete_node(os.path.join(path, directory, filename))

                xbmcvfs.rmdir(os.path.join(path, directory))

    def delete_node_by_id(self, view_id):
        path = self.EmbyServer.Utils.translatePath("special://profile/library/video/")
        dirs, files = xbmcvfs.listdir(path)

        for directory in dirs:
            if directory.startswith('emby') and directory.endswith(view_id):
                _, files = xbmcvfs.listdir(os.path.join(path, directory))

                for filename in files:
                    self.delete_node(os.path.join(path, directory, filename))

                xbmcvfs.rmdir(os.path.join(path, directory))

    #Nodes
    def node_all(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "sorttitle":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle"

    def node_recentlyplayed(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "lastplayed":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "lastplayed"

    def node_directors(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "directors":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "directors"

        for rule in root.findall('.//group'):
            rule.text = "directors"
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'group').text = "directors"

    def node_countries(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "countries":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "countries"

        for rule in root.findall('.//group'):
            rule.text = "countries"
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'group').text = "countries"

    def node_nextepisodes(self, root, LibraryName):
        params = {
            'libraryname': LibraryName,
            'mode': "nextepisodes",
            'limit': 25
        }
        path = "%s?%s" % ("plugin://plugin.video.emby-next-gen/", urlencode(params))

        for rule in root.findall('.//path'):
            rule.text = path
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'path').text = path

        for rule in root.findall('.//content'):
            rule.text = "episodes"
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'content').text = "episodes"

    def node_years(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "title":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "title"

        for rule in root.findall('.//group'):
            rule.text = "years"
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'group').text = "years"

    def node_actors(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "title":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "title"

        for rule in root.findall('.//group'):
            rule.text = "actors"
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'group').text = "actors"

    def node_artists(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "artists":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "artists"

        for rule in root.findall('.//group'):
            rule.text = "artists"
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'group').text = "artists"

    def node_albums(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "albums":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "albums"

        for rule in root.findall('.//group'):
            rule.text = "albums"
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'group').text = "albums"

    def node_studios(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "title":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "title"

        for rule in root.findall('.//group'):
            rule.text = "studios"
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'group').text = "studios"

    def node_tags(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "title":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "title"

        for rule in root.findall('.//group'):
            rule.text = "tags"
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'group').text = "tags"

    def node_recentlyadded(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "dateadded":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "dateadded"

        for rule in root.findall('.//limit'):
            rule.text = str(self.limit)
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'limit').text = str(self.limit)

        for rule in root.findall('.//rule'):
            if rule.attrib['field'] == 'playcount':
                rule.find('value').text = "0"
                break
        else:
            rule = xml.etree.ElementTree.SubElement(root, 'rule', {'field': "playcount", 'operator': "is"})
            xml.etree.ElementTree.SubElement(rule, 'value').text = "0"

    def node_inprogress(self, root):
        for rule in root.findall('.//rule'):
            if rule.attrib['field'] == 'inprogress':
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'rule', {'field': "inprogress", 'operator': "true"})
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "lastplayed"

        for rule in root.findall('.//limit'):
            rule.text = str(self.limit)
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'limit').text = str(self.limit)

    def node_genres(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "sorttitle":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle"

        for rule in root.findall('.//group'):
            rule.text = "genres"
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'group').text = "genres"

    def node_unwatched(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "sorttitle":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle"

        for rule in root.findall('.//rule'):
            if rule.attrib['field'] == 'playcount':
                rule.find('value').text = "0"
                break
        else:
            rule = xml.etree.ElementTree.SubElement(root, "rule", {'field': "playcount", 'operator': "is"})
            xml.etree.ElementTree.SubElement(rule, 'value').text = "0"

    def node_unwatchedepisodes(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "sorttitle":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle"

        for rule in root.findall('.//rule'):
            if rule.attrib['field'] == 'playcount':
                rule.find('value').text = "0"
                break
        else:
            rule = xml.etree.ElementTree.SubElement(root, "rule", {'field': "playcount", 'operator': "is"})
            xml.etree.ElementTree.SubElement(rule, 'value').text = "0"

        content = root.find('content')
        content.text = "episodes"

    def node_sets(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "sorttitle":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle"

        for rule in root.findall('.//group'):
            rule.text = "sets"
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'group').text = "sets"

    def node_random(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "random":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "ascending"}).text = "random"

        for rule in root.findall('.//limit'):
            rule.text = str(self.limit)
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'limit').text = str(self.limit)

    def node_recommended(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "rating":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "rating"

        for rule in root.findall('.//limit'):
            rule.text = str(self.limit)
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'limit').text = str(self.limit)

        for rule in root.findall('.//rule'):
            if rule.attrib['field'] == 'playcount':
                rule.find('value').text = "0"
                break
        else:
            rule = xml.etree.ElementTree.SubElement(root, 'rule', {'field': "playcount", 'operator': "is"})
            xml.etree.ElementTree.SubElement(rule, 'value').text = "0"

        for rule in root.findall('.//rule'):
            if rule.attrib['field'] == 'rating':
                rule.find('value').text = "7"
                break
        else:
            rule = xml.etree.ElementTree.SubElement(root, 'rule', {'field': "rating", 'operator': "greaterthan"})
            xml.etree.ElementTree.SubElement(rule, 'value').text = "7"

    def node_recentlyepisodes(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "dateadded":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "dateadded"

        for rule in root.findall('.//limit'):
            rule.text = str(self.limit)
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'limit').text = str(self.limit)

        for rule in root.findall('.//rule'):
            if rule.attrib['field'] == 'playcount':
                rule.find('value').text = "0"
                break
        else:
            rule = xml.etree.ElementTree.SubElement(root, 'rule', {'field': "playcount", 'operator': "is"})
            xml.etree.ElementTree.SubElement(rule, 'value').text = "0"

        content = root.find('content')
        content.text = "episodes"

    def node_inprogressepisodes(self, root):
        for rule in root.findall('.//limit'):
            rule.text = str(self.limit)
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'limit').text = str(self.limit)

        for rule in root.findall('.//rule'):
            if rule.attrib['field'] == 'inprogress':
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'rule', {'field': "inprogress", 'operator':"true"})
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "lastplayed"

        content = root.find('content')
        content.text = "episodes"

    def node_favepisodes(self, root, path):
        for rule in root.findall('.//path'):
            rule.text = path
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'path').text = path

        for rule in root.findall('.//content'):
            rule.text = "episodes"
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'content').text = "episodes"

    def node_randomalbums(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "random":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "ascending"}).text = "random"

        for rule in root.findall('.//limit'):
            rule.text = str(self.limit)
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'limit').text = str(self.limit)

    def node_randomsongs(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "random":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "ascending"}).text = "random"

        for rule in root.findall('.//limit'):
            rule.text = str(self.limit)
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'limit').text = str(self.limit)

    def node_recentlyaddedsongs(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "dateadded":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "dateadded"

        for rule in root.findall('.//limit'):
            rule.text = str(self.limit)
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'limit').text = str(self.limit)

    def node_recentlyaddedalbums(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "dateadded":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "dateadded"

        for rule in root.findall('.//limit'):
            rule.text = str(self.limit)
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'limit').text = str(self.limit)

    def node_recentlyaddedepisodes(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "dateadded":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "dateadded"

        for rule in root.findall('.//limit'):
            rule.text = str(self.limit)
            break
        else:
            xml.etree.ElementTree.SubElement(root, 'limit').text = str(self.limit)

        for rule in root.findall('.//rule'):
            if rule.attrib['field'] == 'playcount':
                rule.find('value').text = "0"
                break
        else:
            rule = xml.etree.ElementTree.SubElement(root, 'rule', {'field': "playcount", 'operator': "is"})
            xml.etree.ElementTree.SubElement(rule, 'value').text = "0"

    def node_recentlyplayedepisode(self, root):
        for rule in root.findall('.//order'):
            if rule.text == "lastplayed":
                break
        else:
            xml.etree.ElementTree.SubElement(root, 'order', {'direction': "descending"}).text = "lastplayed"
