# -*- coding: utf-8 -*-
from __future__ import division, absolute_import, print_function, unicode_literals

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

import os
import shutil
import xml.etree.ElementTree as etree

from six.moves.urllib.parse import urlencode
from kodi_six import xbmc, xbmcvfs

from database import Database, jellyfin_db, get_sync, save_sync
from helper import translate, api, window, event
from jellyfin import Jellyfin
from helper import LazyLogger

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

LOG = LazyLogger(__name__)
NODES = {
    'tvshows': [
        ('all', None),
        ('recent', translate(30170)),
        ('recentepisodes', translate(30175)),
        ('inprogress', translate(30171)),
        ('inprogressepisodes', translate(30178)),
        ('nextepisodes', translate(30179)),
        ('genres', 135),
        ('random', translate(30229)),
        ('recommended', translate(30230))
    ],
    'movies': [
        ('all', None),
        ('recent', translate(30174)),
        ('inprogress', translate(30177)),
        ('unwatched', translate(30189)),
        ('sets', 20434),
        ('genres', 135),
        ('random', translate(30229)),
        ('recommended', translate(30230))
    ],
    'musicvideos': [
        ('all', None),
        ('recent', translate(30256)),
        ('inprogress', translate(30257)),
        ('unwatched', translate(30258))
    ]
}
DYNNODES = {
    'tvshows': [
        ('all', None),
        ('RecentlyAdded', translate(30170)),
        ('recentepisodes', translate(30175)),
        ('InProgress', translate(30171)),
        ('inprogressepisodes', translate(30178)),
        ('nextepisodes', translate(30179)),
        ('Genres', translate(135)),
        ('Random', translate(30229)),
        ('recommended', translate(30230))
    ],
    'movies': [
        ('all', None),
        ('RecentlyAdded', translate(30174)),
        ('InProgress', translate(30177)),
        ('Boxsets', translate(20434)),
        ('Favorite', translate(33168)),
        ('FirstLetter', translate(33171)),
        ('Genres', translate(135)),
        ('Random', translate(30229)),
        # ('Recommended', translate(30230))
    ],
    'musicvideos': [
        ('all', None),
        ('RecentlyAdded', translate(30256)),
        ('InProgress', translate(30257)),
        ('Unwatched', translate(30258))
    ],
    'homevideos': [
        ('all', None),
        ('RecentlyAdded', translate(33167)),
        ('InProgress', translate(33169)),
        ('Favorite', translate(33168))
    ],
    'books': [
        ('all', None),
        ('RecentlyAdded', translate(33167)),
        ('InProgress', translate(33169)),
        ('Favorite', translate(33168))
    ],
    'audiobooks': [
        ('all', None),
        ('RecentlyAdded', translate(33167)),
        ('InProgress', translate(33169)),
        ('Favorite', translate(33168))
    ],
    'music': [
        ('all', None),
        ('RecentlyAdded', translate(33167)),
        ('Favorite', translate(33168))
    ]
}

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


def verify_kodi_defaults():

    ''' Make sure we have the kodi default folder in place.
    '''
    node_path = xbmc.translatePath("special://profile/library/video")

    if not os.path.exists(node_path):
        try:
            shutil.copytree(
                src=xbmc.translatePath("special://xbmc/system/library/video"),
                dst=xbmc.translatePath("special://profile/library/video"))
        except Exception as error:
            LOG.warning(error)
            xbmcvfs.mkdir(node_path)

    for index, node in enumerate(['movies', 'tvshows', 'musicvideos']):
        file = os.path.join(node_path, node, "index.xml")

        if xbmcvfs.exists(file):

            xml = etree.parse(file).getroot()
            xml.set('order', str(17 + index))
            tree = etree.ElementTree(xml)
            tree.write(file)

    playlist_path = xbmc.translatePath("special://profile/playlists/video")

    if not xbmcvfs.exists(playlist_path):
        xbmcvfs.mkdirs(playlist_path)


class Views(object):

    sync = None
    limit = 25
    media_folders = None

    def __init__(self):

        self.sync = get_sync()
        self.server = Jellyfin()

    def add_library(self, view):

        ''' Add entry to view table in jellyfin database.
        '''
        with Database('jellyfin') as jellyfindb:
            jellyfin_db.JellyfinDatabase(jellyfindb.cursor).add_view(view['Id'], view['Name'], view['Media'])

    def remove_library(self, view_id):

        ''' Remove entry from view table in jellyfin database.
        '''
        with Database('jellyfin') as jellyfindb:
            jellyfin_db.JellyfinDatabase(jellyfindb.cursor).remove_view(view_id)

        self.delete_playlist_by_id(view_id)
        self.delete_node_by_id(view_id)

    def get_libraries(self):

        try:
            libraries = self.server.jellyfin.get_media_folders()['Items']
            library_ids = [x['Id'] for x in libraries]
            for view in self.server.jellyfin.get_views()['Items']:
                if view['Id'] not in library_ids:
                    libraries.append(view)

        except Exception as error:
            LOG.exception(error)
            raise IndexError("Unable to retrieve libraries: %s" % error)

        return libraries

    def get_views(self):

        ''' Get the media folders. Add or remove them. Do not proceed if issue getting libraries.
        '''
        try:
            libraries = self.get_libraries()
        except IndexError as error:
            LOG.exception(error)

            return

        self.sync['SortedViews'] = [x['Id'] for x in libraries]

        for library in libraries:

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

            self.add_library(library)

        with Database('jellyfin') as jellyfindb:

            views = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views()
            removed = []

            for view in views:

                if view[0] not in self.sync['SortedViews']:
                    removed.append(view[0])

            if removed:
                event('RemoveLibrary', {'Id': ','.join(removed)})

        save_sync(self.sync)

    def get_nodes(self):

        ''' Set up playlists, video nodes, window prop.
        '''
        node_path = xbmc.translatePath("special://profile/library/video")
        playlist_path = xbmc.translatePath("special://profile/playlists/video")
        index = 0

        with Database('jellyfin') as jellyfindb:
            db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)

            for library in self.sync['Whitelist']:

                library = library.replace('Mixed:', "")
                view = db.get_view(library)

                if view:
                    view = {'Id': library, 'Name': view[0], 'Tag': view[0], 'Media': view[1]}

                    if view['Media'] == 'mixed':
                        for media in ('movies', 'tvshows'):

                            temp_view = dict(view)
                            temp_view['Media'] = media
                            self.add_playlist(playlist_path, temp_view, True)
                            self.add_nodes(node_path, temp_view, True)

                        index += 1  # Compensate for the duplicate.
                    else:
                        if view['Media'] in ('movies', 'tvshows', 'musicvideos'):
                            self.add_playlist(playlist_path, view)

                        if view['Media'] not in ('music',):
                            self.add_nodes(node_path, view)

                    index += 1

        for single in [{'Name': translate('fav_movies'), 'Tag': "Favorite movies", 'Media': "movies"},
                       {'Name': translate('fav_tvshows'), 'Tag': "Favorite tvshows", 'Media': "tvshows"},
                       {'Name': translate('fav_episodes'), 'Tag': "Favorite episodes", 'Media': "episodes"}]:

            self.add_single_node(node_path, index, "favorites", single)
            index += 1

        self.window_nodes()

    def add_playlist(self, path, view, mixed=False):

        ''' Create or update the xps file.
        '''
        file = os.path.join(path, "jellyfin%s%s.xsp" % (view['Media'], view['Id']))

        try:
            if os.path.isfile(file):
                xml = etree.parse(file).getroot()
            else:
                xml = etree.Element('smartplaylist', {'type': view['Media']})
                etree.SubElement(xml, 'name')
                etree.SubElement(xml, 'match')
        except Exception:
            LOG.warning("Unable to parse file '%s'", file)
            xml = etree.Element('smartplaylist', {'type': view['Media']})
            etree.SubElement(xml, 'name')
            etree.SubElement(xml, 'match')

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

        match = xml.find('match')
        match.text = "all"

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

        tree = etree.ElementTree(xml)
        tree.write(file)

    def add_nodes(self, path, view, mixed=False):

        ''' Create or update the video node file.
        '''
        folder = os.path.join(path, "jellyfin%s%s" % (view['Media'], view['Id']))

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

        self.node_index(folder, view, mixed)

        if view['Media'] == 'tvshows':
            self.node_tvshow(folder, view)
        else:
            self.node(folder, view)

    def add_single_node(self, path, index, item_type, view):

        file = os.path.join(path, "jellyfin_%s.xml" % view['Tag'].replace(" ", ""))

        try:
            if os.path.isfile(file):
                xml = etree.parse(file).getroot()
            else:
                xml = self.node_root('folder' if item_type == 'favorites' and view['Media'] == 'episodes' else 'filter', index)
                etree.SubElement(xml, 'label')
                etree.SubElement(xml, 'match')
                etree.SubElement(xml, 'content')
        except Exception:
            LOG.warning("Unable to parse file '%s'", file)
            xml = self.node_root('folder' if item_type == 'favorites' and view['Media'] == 'episodes' else 'filter', index)
            etree.SubElement(xml, 'label')
            etree.SubElement(xml, 'match')
            etree.SubElement(xml, 'content')

        label = xml.find('label')
        label.text = view['Name']

        content = xml.find('content')
        content.text = view['Media']

        match = xml.find('match')
        match.text = "all"

        if view['Media'] != 'episodes':

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

        if item_type == 'favorites' and view['Media'] == 'episodes':
            path = self.window_browse(view, 'FavEpisodes')
            self.node_favepisodes(xml, path)
        else:
            self.node_all(xml)

        tree = etree.ElementTree(xml)
        tree.write(file)

    def node_root(self, root, index):

        ''' Create the root element
        '''
        if root == 'main':
            element = etree.Element('node', {'order': str(index)})
        elif root == 'filter':
            element = etree.Element('node', {'order': str(index), 'type': "filter"})
        else:
            element = etree.Element('node', {'order': str(index), 'type': "folder"})

        etree.SubElement(element, 'icon').text = "special://home/addons/plugin.video.jellyfin/resources/icon.png"

        return element

    def node_index(self, folder, view, mixed=False):

        file = os.path.join(folder, "index.xml")
        index = self.sync['SortedViews'].index(view['Id'])

        try:
            if os.path.isfile(file):
                xml = etree.parse(file).getroot()
                xml.set('order', str(index))
            else:
                xml = self.node_root('main', index)
                etree.SubElement(xml, 'label')
        except Exception as error:
            LOG.exception(error)
            xml = self.node_root('main', index)
            etree.SubElement(xml, 'label')

        label = xml.find('label')
        label.text = view['Name'] if not mixed else "%s (%s)" % (view['Name'], translate(view['Media']))

        tree = etree.ElementTree(xml)
        tree.write(file)

    def node(self, folder, view):

        for node in NODES[view['Media']]:

            xml_name = node[0]
            xml_label = node[1] or view['Name']
            file = os.path.join(folder, "%s.xml" % xml_name)
            self.add_node(NODES[view['Media']].index(node), file, view, xml_name, xml_label)

    def node_tvshow(self, folder, view):

        for node in NODES[view['Media']]:

            xml_name = node[0]
            xml_label = node[1] or view['Name']
            xml_index = NODES[view['Media']].index(node)
            file = os.path.join(folder, "%s.xml" % xml_name)

            if xml_name == 'nextepisodes':
                path = self.window_nextepisodes(view)
                self.add_dynamic_node(xml_index, file, view, xml_name, xml_label, path)
            else:
                self.add_node(xml_index, file, view, xml_name, xml_label)

    def add_node(self, index, file, view, node, name):

        try:
            if os.path.isfile(file):
                xml = etree.parse(file).getroot()
            else:
                xml = self.node_root('filter', index)
                etree.SubElement(xml, 'label')
                etree.SubElement(xml, 'match')
                etree.SubElement(xml, 'content')

        except Exception:
            LOG.warning("Unable to parse file '%s'", file)
            xml = self.node_root('filter', index)
            etree.SubElement(xml, 'label')
            etree.SubElement(xml, 'match')
            etree.SubElement(xml, 'content')

        label = xml.find('label')
        label.text = str(name) if type(name) == int else name

        content = xml.find('content')
        content.text = view['Media']

        match = xml.find('match')
        match.text = "all"

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

        getattr(self, 'node_' + node)(xml)  # get node function based on node type
        tree = etree.ElementTree(xml)
        tree.write(file)

    def add_dynamic_node(self, index, file, view, node, name, path):

        try:
            if os.path.isfile(file):
                xml = etree.parse(file).getroot()
            else:
                xml = self.node_root('folder', index)
                etree.SubElement(xml, 'label')
                etree.SubElement(xml, 'content')
        except Exception:
            LOG.warning("Unable to parse file '%s'", file)
            xml = self.node_root('folder', index)
            etree.SubElement(xml, 'label')
            etree.SubElement(xml, 'content')

        # Migration for https://github.com/jellyfin/jellyfin-kodi/issues/239
        if xml.attrib.get('type') == 'filter':
            xml.attrib = {'type': 'folder', 'order': '5'}

        label = xml.find('label')
        label.text = name

        getattr(self, 'node_' + node)(xml, path)
        tree = etree.ElementTree(xml)
        tree.write(file)

    def node_all(self, root):

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

    def node_nextepisodes(self, root, path):

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

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

    def node_recent(self, root):

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

        for rule in root.findall('.//limit'):
            rule.text = str(self.limit)
            break
        else:
            etree.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 = etree.SubElement(root, 'rule', {'field': "playcount", 'operator': "is"})
            etree.SubElement(rule, 'value').text = "0"

    def node_inprogress(self, root):

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

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

    def node_genres(self, root):

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

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

    def node_unwatched(self, root):

        for rule in root.findall('.//order'):
            if rule.text == "sorttitle":
                break
        else:
            etree.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 = etree.SubElement(root, "rule", {'field': "playcount", 'operator': "is"})
            etree.SubElement(rule, 'value').text = "0"

    def node_sets(self, root):

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

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

    def node_random(self, root):

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

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

    def node_recommended(self, root):

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

        for rule in root.findall('.//limit'):
            rule.text = str(self.limit)
            break
        else:
            etree.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 = etree.SubElement(root, 'rule', {'field': "playcount", 'operator': "is"})
            etree.SubElement(rule, 'value').text = "0"

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

    def node_recentepisodes(self, root):

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

        for rule in root.findall('.//limit'):
            rule.text = str(self.limit)
            break
        else:
            etree.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 = etree.SubElement(root, 'rule', {'field': "playcount", 'operator': "is"})
            etree.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:
            etree.SubElement(root, 'limit').text = str(self.limit)

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

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

    def node_favepisodes(self, root, path):

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

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

    def order_media_folders(self, folders):

        ''' Returns a list of sorted media folders based on the Jellyfin views.
            Insert them in SortedViews and remove Views that are not in media folders.
        '''
        if not folders:
            return folders

        sorted_views = list(self.sync['SortedViews'])
        unordered = [x[0] for x in folders]
        grouped = [x for x in unordered if x not in sorted_views]

        for library in grouped:
            sorted_views.append(library)

        sorted_folders = [x for x in sorted_views if x in unordered]

        return [folders[unordered.index(x)] for x in sorted_folders]

    def window_nodes(self):

        ''' Just read from the database and populate based on SortedViews
            Setup the window properties that reflect the jellyfin server views and more.
        '''
        self.window_clear()
        self.window_clear('Jellyfin.wnodes')

        with Database('jellyfin') as jellyfindb:
            libraries = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views()

        libraries = self.order_media_folders(libraries or [])
        index = 0
        windex = 0

        try:
            self.media_folders = self.get_libraries()
        except IndexError as error:
            LOG.exception(error)

        for library in (libraries or []):
            view = {'Id': library[0], 'Name': library[1], 'Tag': library[1], 'Media': library[2]}

            if library[0] in [x.replace('Mixed:', "") for x in self.sync['Whitelist']]:  # Synced libraries

                if view['Media'] in ('movies', 'tvshows', 'musicvideos', 'mixed'):

                    if view['Media'] == 'mixed':
                        for media in ('movies', 'tvshows'):

                            for node in NODES[media]:

                                temp_view = dict(view)
                                temp_view['Media'] = media
                                temp_view['Name'] = "%s (%s)" % (view['Name'], translate(media))
                                self.window_node(index, temp_view, *node)
                                self.window_wnode(windex, temp_view, *node)

                            # Add one to compensate for the duplicate.
                            index += 1
                            windex += 1
                    else:
                        for node in NODES[view['Media']]:

                            self.window_node(index, view, *node)

                            if view['Media'] in ('movies', 'tvshows'):
                                self.window_wnode(windex, view, *node)

                        if view['Media'] in ('movies', 'tvshows'):
                            windex += 1

                elif view['Media'] == 'music':
                    self.window_node(index, view, 'music')
            else:  # Dynamic entry
                if view['Media'] in ('homevideos', 'books', 'playlists'):
                    self.window_wnode(windex, view, 'browse')
                    windex += 1

                self.window_node(index, view, 'browse')

            index += 1

        for single in [{'Name': translate('fav_movies'), 'Tag': "Favorite movies", 'Media': "movies"},
                       {'Name': translate('fav_tvshows'), 'Tag': "Favorite tvshows", 'Media': "tvshows"},
                       {'Name': translate('fav_episodes'), 'Tag': "Favorite episodes", 'Media': "episodes"}]:

            self.window_single_node(index, "favorites", single)
            index += 1

        window('Jellyfin.nodes.total', str(index))
        window('Jellyfin.wnodes.total', str(windex))

    def window_node(self, index, view, node=None, node_label=None):

        ''' Leads to another listing of nodes.
        '''
        if view['Media'] in ('homevideos', 'photos'):
            path = self.window_browse(view, None if node in ('all', 'browse') else node)
        elif node == 'nextepisodes':
            path = self.window_nextepisodes(view)
        elif node == 'music':
            path = self.window_music(view)
        elif node == 'browse':
            path = self.window_browse(view)
        else:
            path = self.window_path(view, node)

        if node == 'music':
            window_path = "ActivateWindow(Music,%s,return)" % path
        elif node in ('browse', 'homevideos', 'photos'):
            window_path = path
        else:
            window_path = "ActivateWindow(Videos,%s,return)" % path

        node_label = translate(node_label) if type(node_label) == int else node_label
        node_label = node_label or view['Name']

        if node in ('all', 'music'):

            window_prop = "Jellyfin.nodes.%s" % index
            window('%s.index' % window_prop, path.replace('all.xml', ""))  # dir
            window('%s.title' % window_prop, view['Name'])
            window('%s.content' % window_prop, path)

        elif node == 'browse':

            window_prop = "Jellyfin.nodes.%s" % index
            window('%s.title' % window_prop, view['Name'])
        else:
            window_prop = "Jellyfin.nodes.%s.%s" % (index, node)
            window('%s.title' % window_prop, node_label)
            window('%s.content' % window_prop, path)

        window('%s.id' % window_prop, view['Id'])
        window('%s.path' % window_prop, window_path)
        window('%s.type' % window_prop, view['Media'])
        self.window_artwork(window_prop, view['Id'])

    def window_single_node(self, index, item_type, view):

        ''' Single destination node.
        '''
        path = "library://video/jellyfin_%s.xml" % view['Tag'].replace(" ", "")
        window_path = "ActivateWindow(Videos,%s,return)" % path

        window_prop = "Jellyfin.nodes.%s" % index
        window('%s.title' % window_prop, view['Name'])
        window('%s.path' % window_prop, window_path)
        window('%s.content' % window_prop, path)
        window('%s.type' % window_prop, item_type)

    def window_wnode(self, index, view, node=None, node_label=None):

        ''' Similar to window_node, but does not contain music, musicvideos.
            Contains books, audiobooks.
        '''
        if view['Media'] in ('homevideos', 'photos', 'books', 'playlists'):
            path = self.window_browse(view, None if node in ('all', 'browse') else node)
        else:
            path = self.window_path(view, node)

        if node in ('browse', 'homevideos', 'photos', 'books', 'playlists'):
            window_path = path
        else:
            window_path = "ActivateWindow(Videos,%s,return)" % path

        node_label = translate(node_label) if type(node_label) == int else node_label
        node_label = node_label or view['Name']

        if node == 'all':

            window_prop = "Jellyfin.wnodes.%s" % index
            window('%s.index' % window_prop, path.replace('all.xml', ""))  # dir
            window('%s.title' % window_prop, view['Name'])
            window('%s.content' % window_prop, path)

        elif node == 'browse':

            window_prop = "Jellyfin.wnodes.%s" % index
            window('%s.title' % window_prop, view['Name'])
            window('%s.content' % window_prop, path)
        else:
            window_prop = "Jellyfin.wnodes.%s.%s" % (index, node)
            window('%s.title' % window_prop, node_label)
            window('%s.content' % window_prop, path)

        window('%s.id' % window_prop, view['Id'])
        window('%s.path' % window_prop, window_path)
        window('%s.type' % window_prop, view['Media'])
        self.window_artwork(window_prop, view['Id'])

        LOG.debug("--[ wnode/%s/%s ] %s", index, window('%s.title' % window_prop), window('%s.artwork' % window_prop))

    def window_artwork(self, prop, view_id):

        if not self.server.logged_in:
            window('%s.artwork' % prop, clear=True)

        elif self.server.logged_in and self.media_folders is not None:
            for library in self.media_folders:

                if library['Id'] == view_id and 'Primary' in library.get('ImageTags', {}):
                    server_address = self.server.auth.get_server_info(self.server.auth.server_id)['address']
                    artwork = api.API(None, server_address).get_artwork(view_id, 'Primary')
                    window('%s.artwork' % prop, artwork)

                    break
            else:
                window('%s.artwork' % prop, clear=True)

    def window_path(self, view, node):
        return "library://video/jellyfin%s%s/%s.xml" % (view['Media'], view['Id'], node)

    def window_music(self, view):
        return "library://music/"

    def window_nextepisodes(self, view):

        params = {
            'id': view['Id'],
            'mode': "nextepisodes",
            'limit': self.limit
        }
        return "%s?%s" % ("plugin://plugin.video.jellyfin/", urlencode(params))

    def window_browse(self, view, node=None):

        params = {
            'mode': "browse",
            'type': view['Media']
        }

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

        if node:
            params['folder'] = node

        return "%s?%s" % ("plugin://plugin.video.jellyfin/", urlencode(params))

    def window_clear(self, name=None):

        ''' Clearing window prop setup for Views.
        '''
        total = int(window((name or 'Jellyfin.nodes') + '.total') or 0)
        props = [

            "index", "id", "path", "artwork", "title", "content", "type"
            "inprogress.content", "inprogress.title",
            "inprogress.content", "inprogress.path",
            "nextepisodes.title", "nextepisodes.content",
            "nextepisodes.path", "unwatched.title",
            "unwatched.content", "unwatched.path",
            "recent.title", "recent.content", "recent.path",
            "recentepisodes.title", "recentepisodes.content",
            "recentepisodes.path", "inprogressepisodes.title",
            "inprogressepisodes.content", "inprogressepisodes.path"
        ]
        for i in range(total):
            for prop in props:
                window('Jellyfin.nodes.%s.%s' % (str(i), prop), clear=True)

        for prop in props:
            window('Jellyfin.nodes.%s' % prop, clear=True)

    def delete_playlist(self, path):

        xbmcvfs.delete(path)
        LOG.info("DELETE playlist %s", path)

    def delete_playlists(self):

        ''' Remove all jellyfin playlists.
        '''
        path = xbmc.translatePath("special://profile/playlists/video/")
        _, files = xbmcvfs.listdir(path)
        for file in files:
            if file.startswith('jellyfin'):
                self.delete_playlist(os.path.join(path, file))

    def delete_playlist_by_id(self, view_id):

        ''' Remove playlist based based on view_id.
        '''
        path = xbmc.translatePath("special://profile/playlists/video/")
        _, files = xbmcvfs.listdir(path)
        for file in files:
            file = file

            if file.startswith('jellyfin') and file.endswith('%s.xsp' % view_id):
                self.delete_playlist(os.path.join(path, file))

    def delete_node(self, path):

        xbmcvfs.delete(path)
        LOG.info("DELETE node %s", path)

    def delete_nodes(self):

        ''' Remove node and children files.
        '''
        path = xbmc.translatePath("special://profile/library/video/")
        dirs, files = xbmcvfs.listdir(path)

        for file in files:

            if file.startswith('jellyfin'):
                self.delete_node(os.path.join(path, file))

        for directory in dirs:

            if directory.startswith('jellyfin'):
                _, files = xbmcvfs.listdir(os.path.join(path, directory))

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

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

    def delete_node_by_id(self, view_id):

        ''' Remove node and children files based on view_id.
        '''
        path = xbmc.translatePath("special://profile/library/video/")
        dirs, files = xbmcvfs.listdir(path)

        for directory in dirs:

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

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

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