/*
 *      Copyright (C) 2005-2013 Team XBMC
 *      http://xbmc.org
 *
 *  This Program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  This Program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with XBMC; see the file COPYING.  If not, see
 *  <http://www.gnu.org/licenses/>.
 *
 */

var MediaLibrary = function () {
    this.init();
};
MediaLibrary.prototype = {
    playlists: {},

    init: function () {
        this.bindControls();
        this.getPlaylists();
    },
    bindControls: function () {
        $('#musicLibrary').click(jQuery.proxy(this.musicLibraryOpen, this));
        $('#movieLibrary').click(jQuery.proxy(this.movieLibraryOpen, this));
        $('#tvshowLibrary').click(jQuery.proxy(this.tvshowLibraryOpen, this));
        $('#pictureLibrary').click(jQuery.proxy(this.pictureLibraryOpen, this));
        $('#remoteControl').click(jQuery.proxy(this.remoteControlOpen, this));
        $('#profiles').click(jQuery.proxy(this.profilesOpen, this));
        $('#overlay').click(jQuery.proxy(this.hideOverlay, this));
        $(window).resize(jQuery.proxy(this.updatePlayButtonLocation, this));
        $(document).on('keydown', jQuery.proxy(this.handleKeyPress, this));
        $(document).on('contextmenu', jQuery.proxy(this.handleContextMenu, this));
    },
    resetPage: function () {
        $('#musicLibrary').removeClass('selected');
        $('#movieLibrary').removeClass('selected');
        $('#tvshowLibrary').removeClass('selected');
        $('#remoteControl').removeClass('selected');
        $('#pictureLibrary').removeClass('selected');
        $('#profiles').removeClass('selected');
        this.hideOverlay();
    },
    replaceAll: function (haystack, needle, thread) {
        return (haystack || '').split(needle || '').join(thread || '');
    },
    getPlaylists: function () {
        xbmc.rpc.request({
            'context': this,
            'method': 'Playlist.GetPlaylists',
            'timeout': 3000,
            'success': function (data) {
                if (data && data.result && data.result.length > 0) {
                    $.each($(data.result), jQuery.proxy(function (i, item) {
                        this.playlists[item.type] = item.playlistid;
                    }, this));
                }
            },
            'error': function (data, error) {
                xbmc.core.displayCommunicationError();
                setTimeout(jQuery.proxy(this.updateState, this), 2000);
            }
        });
    },
    remoteControlOpen: function (event) {
        this.resetPage();
        this.textBuffer = '';
        $('#remoteControl').addClass('selected');
        $('.contentContainer').hide();
        var libraryContainer = $('#remoteContainer');
        if (!libraryContainer || libraryContainer.length === 0) {
            $('#spinner').show();
            libraryContainer = $('<div>');
            libraryContainer.attr('id', 'remoteContainer')
                .addClass('contentContainer');
            $('#content').append(libraryContainer);
            var keys = [{
                    name: 'up',
                    width: '40px',
                    height: '30px',
                    top: '28px',
                    left: '58px'
                },
                {
                    name: 'down',
                    width: '40px',
                    height: '30px',
                    top: '122px',
                    left: '58px'
                },
                {
                    name: 'left',
                    width: '40px',
                    height: '30px',
                    top: '74px',
                    left: '15px'
                },
                {
                    name: 'right',
                    width: '40px',
                    height: '30px',
                    top: '74px',
                    left: '104px'
                },
                {
                    name: 'ok',
                    width: '40px',
                    height: '30px',
                    top: '74px',
                    left: '58px'
                },
                {
                    name: 'back',
                    width: '40px',
                    height: '30px',
                    top: '13px',
                    left: '161px'
                },
                {
                    name: 'home',
                    width: '40px',
                    height: '30px',
                    top: '154px',
                    left: '8px'
                },
                {
                    name: 'mute',
                    width: '40px',
                    height: '30px',
                    top: '107px',
                    left: '391px'
                },
                {
                    name: 'power',
                    width: '30px',
                    height: '30px',
                    top: '-3px',
                    left: '13px'
                },
                {
                    name: 'volumeup',
                    width: '30px',
                    height: '30px',
                    top: '49px',
                    left: '422px'
                },
                {
                    name: 'volumedown',
                    width: '30px',
                    height: '30px',
                    top: '49px',
                    left: '367px'
                },
                {
                    name: 'playpause',
                    width: '32px',
                    height: '23px',
                    top: '62px',
                    left: '260px'
                },
                {
                    name: 'stop',
                    width: '32px',
                    height: '23px',
                    top: '62px',
                    left: '211px'
                },
                {
                    name: 'next',
                    width: '38px',
                    height: '25px',
                    top: '102px',
                    left: '304px'
                },
                {
                    name: 'previous',
                    width: '38px',
                    height: '25px',
                    top: '101px',
                    left: '160px'
                },
                {
                    name: 'forward',
                    width: '32px',
                    height: '23px',
                    top: '102px',
                    left: '259px'
                },
                {
                    name: 'rewind',
                    width: '32px',
                    height: '23px',
                    top: '101px',
                    left: '211px'
                },
                {
                    name: 'cleanlib_a',
                    width: '46px',
                    height: '26px',
                    top: '47px',
                    left: '553px'
                },
                {
                    name: 'updatelib_a',
                    width: '46px',
                    height: '26px',
                    top: '47px',
                    left: '492px'
                },
                {
                    name: 'cleanlib_v',
                    width: '46px',
                    height: '26px',
                    top: '111px',
                    left: '553px'
                },
                {
                    name: 'updatelib_v',
                    width: '46px',
                    height: '26px',
                    top: '111px',
                    left: '492px'
                }
            ];
            for (var akey in keys) {
                var aremotekey = $('<p>').attr('id', keys[akey]['name']);
                aremotekey.addClass('remote_key')
                    .css('height', keys[akey]['height'])
                    .css('width', keys[akey]['width'])
                    .css('top', keys[akey]['top'])
                    .css('left', keys[akey]['left'])
                    .bind('click', {
                        key: keys[akey]['name']
                    }, jQuery.proxy(this.pressRemoteKey, this));
                libraryContainer.append(aremotekey);
            }
        } else {
            libraryContainer.show();
            libraryContainer.trigger('scroll');
        }

        $('#spinner').hide();
    },
    shouldHandleEvent: function (event) {
        var inRemoteControl = $('#remoteControl').hasClass('selected');
        return (!event.ctrlKey && !event.altKey && inRemoteControl);
    },
    handleKeyPress: function (event) {
        if (!this.shouldHandleEvent(event)) {
            return true;
        }

        var keys = {
            8: 'back', // Back space
            13: 'ok', // Enter
            27: 'home', // Escape
            32: 'playpause', // Space bar
            37: 'left', // Left
            38: 'up', // Up
            39: 'right', // Right
            40: 'down', // Down
            93: 'contextmenu', // "Right Click"
            107: 'volumeup', // + (num keypad)
            109: 'volumedown', // - (num keypad)
            187: 'volumeup', // + (alnum keypad)
            189: 'volumedown' // - (alnum keypad)
        };
        var which = event.which;
        var key = keys[which];

        event.data = {
            key: key
        };

        if (!key) {
            event.data.key = 'text';

            if (event.key && event.key.length === 1) {
                event.data.text = event.key;
            } else {
                // Letters
                if (which >= 65 && which <= 90) {
                    var offset = event.shiftKey ? 0 : 32;
                    event.data.text = String.fromCharCode(which + offset);
                }

                // Digits
                if (which >= 96 && which <= 105) {
                    event.data.text = (which - 96) + "";
                }
            }
        }

        if (event.data.key) {
            this.pressRemoteKey(event);
            return false;
        }
    },
    handleContextMenu: function (event) {
        if (!this.shouldHandleEvent(event)) {
            return true;
        }
        if (
            (event.target == document) || //Chrome/Opera
            (event.clientX === event.clientY && event.clientX === 0) //FF/IE
        ) {
            return false;
        } //keyboard event. cancel it.
        return true;
    },
    rpcCall: function (method, params) {
        var callObj = {
            'method': method
        };
        if (params) {
            callObj.params = params;
        }
        return xbmc.rpc.request(callObj);
    },
    typeRemoteText: function (event) {
        if (event.data.key === 'text' || ((event.data.key === 'playpause' || event.data.key === 'back') && this
                .textBuffer.length)) {
            if (event.data.key === 'back') {
                this.textBuffer = this.textBuffer.substring(0, this.textBuffer.length - 1);
            } else if (event.data.key === 'playpause') {
                this.textBuffer += ' ';
            } else if (event.data.text && event.data.text.length) {
                this.textBuffer += event.data.text;
            }
            console.log(this.textBuffer);
            return this.rpcCall('Input.SendText', {
                'text': this.textBuffer,
                'done': false
            });
        } else {
            this.textBuffer = '';
        }
    },
    pressRemoteKey: function (event) {
        var player = -1,
            keyPressed = event.data.key;
        $('#spinner').show();
        if (this.typeRemoteText(event)) {
            return true;
        }

        switch (keyPressed) {
        case 'up':
            return this.rpcCall('Input.Up');
        case 'down':
            return this.rpcCall('Input.Down');
        case 'left':
            return this.rpcCall('Input.Left');
        case 'right':
            return this.rpcCall('Input.Right');
        case 'ok':
            return this.rpcCall('Input.Select');
        case 'cleanlib_a':
            return this.rpcCall('AudioLibrary.Clean');
        case 'updatelib_a':
            return this.rpcCall('AudioLibrary.Scan');
        case 'cleanlib_v':
            return this.rpcCall('VideoLibrary.Clean');
        case 'updatelib_v':
            return this.rpcCall('VideoLibrary.Scan');
        case 'back':
            return this.rpcCall('Input.Back');
        case 'home':
            return this.rpcCall('Input.Home');
        case 'power':
            return this.rpcCall('System.Shutdown');
        case 'contextmenu':
            return this.rpcCall('Input.ContextMenu');
        case 'mute':
            return this.rpcCall('Application.SetMute', {
                'mute': 'toggle'
            });
        case 'volumeup':
            return this.rpcCall('Application.SetVolume', {
                'volume': 'increment'
            });
        case 'volumedown':
            return this.rpcCall('Application.SetVolume', {
                'volume': 'decrement'
            });
        }

        // TODO: Get active player
        if ($('#videoDescription').is(':visible')) {
            player = this.playlists["video"];
        } else if ($('#audioDescription').is(':visible')) {
            player = this.playlists["audio"];
        }

        if (player >= 0) {
            switch (keyPressed) {
            case 'playpause':
                return this.rpcCall('Player.PlayPause', {
                    'playerid': player
                });
            case 'stop':
                return this.rpcCall('Player.Stop', {
                    'playerid': player
                });
            case 'next':
                return this.rpcCall('Player.GoTo', {
                    'playerid': player,
                    'to': 'next'
                });
            case 'previous':
                return this.rpcCall('Player.GoTo', {
                    'playerid': player,
                    'to': 'previous'
                });
            case 'forward':
                return this.rpcCall('Player.SetSpeed', {
                    'playerid': player,
                    'speed': 'increment'
                });
            case 'rewind':
                return this.rpcCall('Player.SetSpeed', {
                    'playerid': player,
                    'speed': 'decrement'
                });
            }
        }
    },
    musicLibraryOpen: function (event) {
        this.resetPage();
        $('#musicLibrary').addClass('selected');
        $('.contentContainer').hide();
        var libraryContainer = $('#libraryContainer');
        if (!libraryContainer || libraryContainer.length === 0) {
            $('#spinner').show();
            libraryContainer = $('<div>');
            libraryContainer.attr('id', 'libraryContainer')
                .addClass('contentContainer');
            $('#content').append(libraryContainer);
            xbmc.rpc.request({
                'context': this,
                'method': 'AudioLibrary.GetAlbums',
                'params': {
                    'limits': {
                        'start': 0
                    },
                    'properties': [
                        'description',
                        'theme',
                        'mood',
                        'style',
                        'type',
                        'albumlabel',
                        'artist',
                        'genre',
                        'rating',
                        'title',
                        'year',
                        'thumbnail'
                    ],
                    'sort': {
                        'method': 'artist'
                    }
                },
                'success': function (data) {
                    if (data && data.result && data.result.albums) {
                        this.albumList = data.result.albums;
                        $.each($(this.albumList), jQuery.proxy(function (i, item) {
                            var floatableAlbum = this.generateThumb('album', item
                                .thumbnail, item.title, item.artist);
                            floatableAlbum.bind('click', {
                                album: item
                            }, jQuery.proxy(this.displayAlbumDetails, this));
                            libraryContainer.append(floatableAlbum);
                        }, this));
                        libraryContainer.append($('<div>').addClass('footerPadding'));
                        $('#spinner').hide();
                        libraryContainer.bind('scroll', {
                            activeLibrary: libraryContainer
                        }, jQuery.proxy(this.updateScrollEffects, this));
                        libraryContainer.trigger('scroll');
                        myScroll = new iScroll('libraryContainer');
                    } else {
                        libraryContainer.html('');
                    }
                }
            });
        } else {
            libraryContainer.show();
            libraryContainer.trigger('scroll');
        }
    },
    getThumbnailPath: function (thumbnail) {
        return thumbnail ? ('image/' + encodeURI(thumbnail)) : xbmc.core.DEFAULT_ALBUM_COVER;
    },
    generateThumb: function (type, thumbnail, title, artist) {
        title = title || '';
        artist = artist || '';

        var showTitle = title,
            showArtist = artist;
        var floatableAlbum = $('<div>');
        var path = this.getThumbnailPath(thumbnail);
        if (title.length > 21) {
            showTitle = $.trim(title.substr(0, 18)) + '...';
        }
        if (artist.length > 22) {
            showArtist = $.trim(artist.substr(0, 20)) + '...';
        }
        var className = '';
        var code = '';
        switch (type) {
        case 'album':
            className = 'floatableAlbum';
            code = '<p class="album" title="' + title + '">' + showTitle + '</p><p class="artist" title="' +
                artist + '">' + artist + '</p>';
            break;
        case 'movie':
            className = 'floatableMovieCover';
            code = '<p class="album" title="' + title + '">' + showTitle + '</p>';
            break;
        case 'tvshow':
            className = 'floatableTVShowCover';
            break;
        case 'tvshowseason':
            className = 'floatableTVShowCoverSeason';
            break;
        case 'image':
        case 'directory':
            className = 'floatableAlbum';
            code = '<p class="album" title="' + title + '">' + showTitle + '</p>';
            break;
        case 'profile':
            className = 'floatableProfileThumb';
            code = '<p class="album" title="' + title + '">' + showTitle + '</p>';
            break;
        }
        return floatableAlbum.addClass(className).html('<div class="imgWrapper"><div class="inner"><img src="' +
            path + '" alt="' + title + '" /></div></div>' + code);
    },
    showAlbumSelectorBlock: function (album) {
        if (album) {
            var prevAlbum = null,
                nextAlbum = null;
            $.each($(this.albumList), jQuery.proxy(function (i, item) {
                if (item.albumid == album.albumid) {
                    if (this.albumList.length > 1) {
                        prevAlbum = this.albumList[i <= 0 ? this.albumList.length - 1 : i - 1];
                        nextAlbum = this.albumList[i >= this.albumList.length ? 0 : i + 1];
                    }
                    return false; /* .each break */
                }
            }, this));
            var albumSelectorBlock = $('#albumSelector');
            if (!albumSelectorBlock || albumSelectorBlock.length === 0) {
                albumSelectorBlock = $('<div>');
                albumSelectorBlock.attr('id', 'albumSelector')
                    .html(
                        '<table><tr><td class="allAlbums">All Albums</td><td class="activeAlbumTitle"></td>' +
                           '<td class="prevAlbum">&nbsp;</td><td class="nextAlbum">&nbsp;</td></tr></table>'
                        );
                $('#content').prepend(albumSelectorBlock);
                $('#albumSelector .allAlbums').bind('click', jQuery.proxy(this.hideAlbumDetails, this));
            }
            $('#albumSelector .prevAlbum').unbind();
            $('#albumSelector .nextAlbum').unbind();
            if (prevAlbum) {
                $('#albumSelector .prevAlbum').bind('click', {
                    album: prevAlbum
                }, jQuery.proxy(this.displayAlbumDetails, this));
            }
            if (nextAlbum) {
                $('#albumSelector .nextAlbum').bind('click', {
                    album: nextAlbum
                }, jQuery.proxy(this.displayAlbumDetails, this));
            }
            $('#albumSelector .activeAlbumTitle').html(album.title || 'Unknown Album');
            albumSelectorBlock.show();
        }
    },
    hideAlbumDetails: function () {
        $('.contentContainer').hide();
        this.musicLibraryOpen();
    },
    displayAlbumDetails: function (event) {
        this.showAlbumSelectorBlock(event.data.album);
        var albumDetailsContainer = $('#albumDetails' + event.data.album.albumid);
        $('#topScrollFade').hide();
        if (!albumDetailsContainer || albumDetailsContainer.length === 0) {
            $('#spinner').show();
            xbmc.rpc.request({
                'context': this,
                'method': 'AudioLibrary.GetSongs',
                'params': {
                    'properties': [
                        'title',
                        'artist',
                        'genre',
                        'track',
                        'duration',
                        'year',
                        'rating',
                        'playcount'
                    ],
                    'sort': {
                        'method': 'track'
                    },
                    'filter': {
                        'albumid': event.data.album.albumid
                    }
                },
                'success': function (data) {
                    albumDetailsContainer = $('<div>');
                    albumDetailsContainer.attr('id', 'albumDetails' + event.data.album.albumid)
                        .addClass('contentContainer')
                        .addClass('albumContainer')
                        .html(
                            '<table class="albumView"><thead><tr class="headerRow"><th>Artwork</th><th>&nbsp;</th>' +
                            '<th>Name</th><th class="time">Time</th><th>Artist</th><th>Genre</th></tr></thead>' +
                            '<tbody class="resultSet"></tbody></table>'
                            );
                    $('.contentContainer').hide();
                    $('#content').append(albumDetailsContainer);
                    var albumThumbnail = event.data.album.thumbnail;
                    var albumTitle = event.data.album.title || 'Unknown Album';
                    var albumArtist = event.data.album.artist.join(', ') || 'Unknown Artist';
                    var trackCount = data.result.limits.total;
                    $.each($(data.result.songs), jQuery.proxy(function (i, item) {
                        var trackRow, trackNumberTD;
                        if (i === 0) {
                            trackRow = $('<tr>').addClass('trackRow').addClass('tr' +
                                i % 2);
                            trackRow.append($('<td>').attr('rowspan', ++trackCount + 1)
                                .addClass('albumThumb'));
                            for (var a = 0; a < 5; a++) {
                                trackRow.append($('<td>').html('&nbsp').attr('style',
                                    'display: none'));
                            }
                            $('#albumDetails' + event.data.album.albumid +
                                ' .resultSet').append(trackRow);
                        }
                        trackRow = $('<tr>').addClass('trackRow').addClass('tr' + i % 2)
                            .bind('click', {
                                album: event.data.album,
                                itmnbr: i
                            }, jQuery.proxy(this.playTrack, this));
                        trackNumberTD = $('<td>').html(item.track);

                        trackRow.append(trackNumberTD);
                        var trackTitleTD = $('<td>').html(item.title);

                        trackRow.append(trackTitleTD);
                        var trackDurationTD = $('<td>')
                            .addClass('time')
                            .html(xbmc.core.durationToString(item.duration));

                        trackRow.append(trackDurationTD);
                        var trackArtistTD = $('<td>').html(item.artist.join(', '));

                        trackRow.append(trackArtistTD);
                        var trackGenreTD = $('<td>').html(item.genre.join(', '));

                        trackRow.append(trackGenreTD);
                        $('#albumDetails' + event.data.album.albumid + ' .resultSet')
                            .append(trackRow);
                    }, this));
                    if (trackCount > 0) {
                        var trackRow = $('<tr>').addClass('fillerTrackRow'),
                            i;
                        for (i = 0; i < 5; i++) {
                            trackRow.append($('<td>').html('&nbsp'));
                        }
                        $('#albumDetails' + event.data.album.albumid + ' .resultSet').append(
                            trackRow);

                        var trackRow2 = $('<tr>').addClass('fillerTrackRow2');
                        trackRow2.append($('<td>').addClass('albumBG').html('&nbsp'));
                        for (i = 0; i < 5; i++) {
                            trackRow2.append($('<td>').html('&nbsp'));
                        }
                        $('#albumDetails' + event.data.album.albumid + ' .resultSet').append(
                            trackRow2);
                    }
                    $('#albumDetails' + event.data.album.albumid + ' .albumThumb')
                        .append(this.generateThumb('album', albumThumbnail, albumTitle,
                            albumArtist))
                        .append($('<div>').addClass('footerPadding'));
                    $('#spinner').hide();
                    myScroll = new iScroll('albumDetails' + event.data.album.albumid);
                }
            });
        } else {
            $('.contentContainer').hide();
            $('#albumDetails' + event.data.album.albumid).show();
        }
    },
    togglePosterView: function (event) {
        var view = event.data.mode;
        var wthumblist, hthumblist, hthumbdetails;
        $("#toggleBanner").removeClass('activeMode');
        $("#togglePoster").removeClass('activeMode');
        $("#toggleLandscape").removeClass('activeMode');
        switch (view) {
        case 'landscape':
            xbmc.core.setCookie('TVView', 'landscape');
            wthumblist = '210px';
            hthumblist = '118px';
            hthumbdetails = '213px';
            $("#toggleLandscape").addClass('activeMode');
            break;
        case 'banner':
            xbmc.core.setCookie('TVView', 'banner');
            wthumblist = '379px';
            hthumblist = '70px';
            hthumbdetails = '70px';
            $("#toggleBanner").addClass('activeMode');
            break;
        default:
            xbmc.core.setCookie('TVView', 'poster');
            wthumblist = '135px';
            hthumblist = '199px';
            hthumbdetails = '559px';
            $("#togglePoster").addClass('activeMode');
            break;
        }
        $(".floatableTVShowCover, .floatableTVShowCover div.imgWrapper, .floatableTVShowCover img, " +
          ".floatableTVShowCover div.imgWrapper div.inner")
            .css('width', wthumblist).css('height', hthumblist);
        $(".floatableTVShowCoverSeason div.imgWrapper, .floatableTVShowCoverSeason div.imgWrapper div.inner," +
          ".floatableTVShowCoverSeason img, .floatableTVShowCoverSeason")
            .css('height', hthumbdetails);
    },
    displayTVShowDetails: function (event) {
        var tvshowDetailsContainer = $('#tvShowDetails' + event.data.tvshow.tvshowid);
        $('#topScrollFade').hide();
        toggle = this.toggle.detach();
        if (!tvshowDetailsContainer || tvshowDetailsContainer.length === 0) {
            $('#spinner').show();
            xbmc.rpc.request({
                'context': this,
                'method': 'VideoLibrary.GetSeasons',
                'params': {
                    'properties': [
                        'season',
                        'showtitle',
                        'playcount',
                        'episode',
                        'thumbnail',
                        'fanart'
                    ],
                    'tvshowid': event.data.tvshow.tvshowid
                },
                'success': function (data) {
                    tvshowDetailsContainer = $('<div>');
                    tvshowDetailsContainer.attr('id', 'tvShowDetails' + event.data.tvshow.tvshowid)
                        .css('display', 'none')
                        .addClass('contentContainer')
                        .addClass('tvshowContainer');
                    var showThumb = this.generateThumb('tvshowseason', event.data.tvshow.thumbnail,
                        event.data.tvshow.title);
                    if (data && data.result && data.result.seasons && data.result.seasons.length >
                        0) {
                        var showDetails = $('<div>').addClass('showDetails');
                        showDetails.append(toggle);
                        showDetails.append($('<p>').html(data.result.seasons[0].showtitle).addClass(
                            'showTitle'));
                        var seasonSelectionSelect = $('<select>').addClass('seasonPicker');
                        this.tvActiveShowContainer = tvshowDetailsContainer;
                        $.each($(data.result.seasons), function (i, item) {
                            var season = $('<option>').attr('value', i);
                            season.text(item.label);
                            seasonSelectionSelect.append(season);
                        });
                        seasonSelectionSelect.bind('change', {
                            tvshow: event.data.tvshow.tvshowid,
                            seasons: data.result.seasons,
                            element: seasonSelectionSelect
                        }, jQuery.proxy(this.displaySeasonListings, this));
                        showDetails.append(seasonSelectionSelect);
                        tvshowDetailsContainer.append(showDetails);
                        tvshowDetailsContainer.append(showThumb);
                        seasonSelectionSelect.trigger('change');
                        $('#content').append(tvshowDetailsContainer);
                        if (xbmc.core.getCookie('TVView') !== null &&
                            xbmc.core.getCookie('TVView') !== 'banner'
                        ) {
                            var view = xbmc.core.getCookie('TVView');
                            switch (view) {
                            case 'poster':
                                togglePoster.trigger('click');
                                break;
                            case 'landscape':
                                toggleLandscape.trigger('click');
                                break;
                            }
                        }
                        tvshowDetailsContainer.fadeIn();
                    }
                    $('#spinner').hide();
                }
            });
        } else {
            $('.contentContainer').hide();
            $('#tvShowDetails' + event.data.tvshow.tvshowid).show();
            $('#tvShowDetails' + event.data.tvshow.tvshowid + ' select').trigger('change');
        }
    },
    displaySeasonListings: function (event) {
        var selectedVal = event.data.element.val();
        var seasons = event.data.seasons;
        $('#topScrollFade').hide();
        var oldListings = $('.episodeListingsContainer', this.tvActiveShowContainer).fadeOut();
        this.tvActiveSeason = selectedVal;
        xbmc.rpc.request({
            'context': this,
            'method': 'VideoLibrary.GetEpisodes',
            'params': {
                'properties': [
                    'title',
                    'thumbnail',
                    'episode',
                    'plot',
                    'season'
                ],
                'season': seasons[selectedVal].season,
                'tvshowid': event.data.tvshow
            },
            'success': function (data) {
                var episodeListingsContainer = $('<div>').addClass('episodeListingsContainer');
                var episodeTable = $('<table>').addClass('seasonView').html(
                    '<thead><tr class="headerRow"><th class="thumbHeader">N&deg;</th><th>Title</th>' +
                    '<th class="thumbHeader">Thumb</th><th class="thumbHeader">Details</th></tr></thead>' +
                    '<tbody class="resultSet"></tbody>'
                    );
                $.each($(data.result.episodes), jQuery.proxy(function (i, item) {
                    var episodeRow = $('<tr>').addClass('episodeRow').addClass('tr' +
                        i % 2);
                    var episodePictureImg = $('<img>').bind('click', {
                        episode: item
                    }, jQuery.proxy(this.playTVShow, this)).css('cursor', 'pointer');
                    episodePictureImg.attr('src', this.getThumbnailPath(item
                    .thumbnail));
                    var episodePicture = $('<td>').addClass('episodeThumb').append(
                        episodePictureImg).bind('click', {
                        episode: item
                    }, jQuery.proxy(this.playTVShow, this));
                    var episodeNumber = $('<td>').addClass('episodeNumber').html(item
                        .episode).bind('click', {
                        episode: item
                    }, jQuery.proxy(this.playTVShow, this));
                    var episodeTitle = $('<td>').html(item.title).bind('click', {
                        episode: item
                    }, jQuery.proxy(this.playTVShow, this));
                    var episodeDetails = $('<td class="info">').html('').bind('click', {
                        episode: item
                    }, jQuery.proxy(this.displayEpisodeDetails, this)).css('cursor',
                        'pointer');
                    episodeRow.append(episodeNumber).append(episodeTitle).append(
                        episodePicture).append(episodeDetails);
                    episodeTable.append(episodeRow);
                }, this));
                episodeListingsContainer.append(episodeTable);
                $(this.tvActiveShowContainer).append(episodeListingsContainer);
            }
        });
    },
    displayEpisodeDetails: function (event) {
        var episodeDetails = $('<div>').attr('id', 'episode-' + event.data.episode.episodeid).addClass(
            'episodePopoverContainer');
        episodeDetails.append($('<img>').attr('src', 'images/close-button.png').addClass('closeButton').bind(
            'click', jQuery.proxy(this.hideOverlay, this)));
        episodeDetails.append($('<img>').attr('src', this.getThumbnailPath(event.data.episode.thumbnail))
            .addClass('episodeCover'));
        episodeDetails.append($('<div>').addClass('playIcon').bind('click', {
            episode: event.data.episode
        }, jQuery.proxy(this.playTVShow, this)));
        var episodeTitle = $('<p>').addClass('episodeTitle');
        var yearText = event.data.episode.year ? ' <span class="year">(' + event.data.episode.year +
            ')</span>' : '';
        episodeTitle.html(event.data.episode.title + yearText);
        episodeDetails.append(episodeTitle);
        if (event.data.episode.runtime) {
            episodeDetails.append($('<p>').addClass('runtime').html('<strong>Runtime:</strong> ' + Math.ceil(
                event.data.episode.runtime / 60) + ' minutes'));
        }
        if (event.data.episode.season) {
            episodeDetails.append($('<p>').addClass('season').html('<strong>Season:</strong> ' + event.data
                .episode.season));
        }
        if (event.data.episode.episode) {
            episodeDetails.append($('<p>').addClass('episode').html('<strong>Episode:</strong> ' + event.data
                .episode.episode));
        }
        if (event.data.episode.plot) {
            episodeDetails.append($('<p>').addClass('plot').html('<strong>Plot:</strong> <br/><br/>' + event
                .data.episode.plot));
        }
        if (event.data.episode.genre) {
            episodeDetails.append($('<p>').addClass('genre').html('<strong>Genre:</strong> ' + event.data
                .episode.genre));
        }
        if (event.data.episode.director) {
            episodeDetails.append($('<p>').addClass('director').html('<strong>Directed By:</strong> ' + event
                .data.episode.director));
        }
        this.activeCover = episodeDetails;
        $('body').append(episodeDetails);
        $('#overlay').show();
        this.updatePlayButtonLocation();
    },
    playTVShow: function (event) {
        xbmc.rpc.request({
            'context': this,
            'method': 'Player.Open',
            'params': {
                'item': {
                    'episodeid': event.data.episode.episodeid
                }
            },
            'success': function (data) {
                this.hideOverlay();
            }
        });
    },
    hideOverlay: function (event) {
        if (this.activeCover) {
            $(this.activeCover).remove();
            this.activeCover = null;
        }
        $('#overlay').hide();
    },
    updatePlayButtonLocation: function (event) {
        var movieContainer = $('.movieCover'),
            playIcon;
        if (movieContainer.length > 0) {
            playIcon = $('.playIcon');
            if (playIcon.length > 0) {
                var heightpi = $(movieContainer[0]).height();
                playIcon.width(Math.floor(0.65 * heightpi));
                playIcon.height(heightpi);
            }
        }
        var episodeContainer = $('.episodeCover');
        if (episodeContainer.length > 0) {
            playIcon = $('.playIcon');
            if (playIcon.length > 0) {
                var widthpi = $(episodeContainer[0]).width();
                playIcon.width(widthpi);
                //assume 16/9 thumb
                playIcon.height(Math.floor(widthpi * 9 / 16));
            }
        }
    },
    playMovie: function (event) {
        xbmc.rpc.request({
            'context': this,
            'method': 'Player.Open',
            'params': {
                'item': {
                    'movieid': event.data.movie.movieid
                }
            },
            'success': function (data) {
                this.hideOverlay();
            }
        });
    },
    displayMovieDetails: function (event) {
        var movieDetails = $('<div>').attr('id', 'movie-' + event.data.movie.movieid).addClass(
            'moviePopoverContainer');
        movieDetails.append($('<img>').attr('src', 'images/close-button.png').addClass('closeButton').bind(
            'click', jQuery.proxy(this.hideOverlay, this)));
        movieDetails.append($('<img>').attr('src', this.getThumbnailPath(event.data.movie.thumbnail)).addClass(
            'movieCover'));
        movieDetails.append($('<div>').addClass('playIcon').bind('click', {
            movie: event.data.movie
        }, jQuery.proxy(this.playMovie, this)));
        var movieTitle = $('<p>').addClass('movieTitle');
        var yearText = event.data.movie.year ? ' <span class="year">(' + event.data.movie.year + ')</span>' :
        '';
        movieTitle.html(event.data.movie.title + yearText);
        movieDetails.append(movieTitle);
        if (event.data.movie.runtime) {
            movieDetails.append($('<p>').addClass('runtime').html('<strong>Runtime:</strong> ' + Math.ceil(event
                .data.movie.runtime / 60) + ' minutes'));
        }
        if (event.data.movie.plot) {
            movieDetails.append($('<p>').addClass('plot').html(event.data.movie.plot));
        }
        if (event.data.movie.genre) {
            movieDetails.append($('<p>').addClass('genre').html('<strong>Genre:</strong> ' + event.data.movie
                .genre));
        }
        if (event.data.movie.director) {
            movieDetails.append($('<p>').addClass('director').html('<strong>Directed By:</strong> ' + event.data
                .movie.director));
        }
        this.activeCover = movieDetails;
        $('body').append(movieDetails);
        $('#overlay').show();
        this.updatePlayButtonLocation();
    },
    playTrack: function (event) {
        xbmc.rpc.request({
            'context': this,
            'method': 'Playlist.Clear',
            'params': {
                'playlistid': this.playlists["audio"]
            },
            'success': function (data) {
                xbmc.rpc.request({
                    'context': this,
                    'method': 'Playlist.Add',
                    'params': {
                        'playlistid': this.playlists["audio"],
                        'item': {
                            'albumid': event.data.album.albumid
                        }
                    },
                    'success': function (data) {
                        xbmc.rpc.request({
                            'method': 'Player.Open',
                            'params': {
                                'item': {
                                    'playlistid': this.playlists["audio"],
                                    'position': event.data.itmnbr
                                }
                            },
                            'success': function () {}
                        });
                    }
                });
            }
        });
    },
    loadProfile: function (event) {
        return xbmc.rpc.request({
            'context': this,
            'method': 'Profiles.LoadProfile',
            'params': {
                'profile': event.data.profile.label
            }
        });
    },
    movieLibraryOpen: function () {
        this.resetPage();
        $('#movieLibrary').addClass('selected');
        $('.contentContainer').hide();
        var libraryContainer = $('#movieLibraryContainer');
        if (!libraryContainer || libraryContainer.length === 0) {
            $('#spinner').show();
            xbmc.rpc.request({
                'context': this,
                'method': 'VideoLibrary.GetMovies',
                'params': {
                    'limits': {
                        'start': 0
                    },
                    'properties': [
                        'genre',
                        'director',
                        'trailer',
                        'tagline',
                        'plot',
                        'plotoutline',
                        'title',
                        'originaltitle',
                        'lastplayed',
                        'runtime',
                        'year',
                        'playcount',
                        'rating',
                        'thumbnail',
                        'file'
                    ],
                    'sort': {
                        'method': 'sorttitle',
                        'ignorearticle': true
                    }
                },
                'success': function (data) {
                    if (data && data.result && data.result.movies) {
                        libraryContainer = $('<div>');
                        libraryContainer.attr('id', 'movieLibraryContainer')
                            .addClass('contentContainer');
                        $('#content').append(libraryContainer);
                    } else {
                        libraryContainer.html('');
                    }
                    $.each($(data.result.movies), jQuery.proxy(function (i, item) {
                        var floatableMovieCover = this.generateThumb('movie', item
                            .thumbnail, item.title);
                        floatableMovieCover.bind('click', {
                            movie: item
                        }, jQuery.proxy(this.displayMovieDetails, this));
                        libraryContainer.append(floatableMovieCover);
                    }, this));
                    libraryContainer.append($('<div>').addClass('footerPadding'));
                    $('#spinner').hide();
                    libraryContainer.bind('scroll', {
                        activeLibrary: libraryContainer
                    }, jQuery.proxy(this.updateScrollEffects, this));
                    libraryContainer.trigger('scroll');
                    myScroll = new iScroll('movieLibraryContainer');
                }
            });
        } else {
            libraryContainer.show();
            libraryContainer.trigger('scroll');
        }
    },
    tvshowLibraryOpen: function () {
        this.resetPage();
        $('#tvshowLibrary').addClass('selected');
        $('.contentContainer').hide();
        var libraryContainer = $('#tvshowLibraryContainer');
        if (!libraryContainer || libraryContainer.length === 0) {
            $('#spinner').show();
            toggle = $('<p>').addClass('toggle');
            togglePoster = $('<span>Poster</span>');
            togglePoster.attr('id', 'togglePoster')
                .css('cursor', 'pointer')
                .bind('click', {
                    mode: 'poster'
                }, jQuery.proxy(this.togglePosterView, this));
            toggleBanner = $('<span>Banner</span>');
            toggleBanner.attr('id', 'toggleBanner')
                .css('cursor', 'pointer')
                .addClass('activeMode')
                .bind('click', {
                    mode: 'banner'
                }, jQuery.proxy(this.togglePosterView, this));
            toggleLandscape = $('<span>Landscape</span>');
            toggleLandscape.attr('id', 'toggleLandscape')
                .css('cursor', 'pointer')
                .bind('click', {
                    mode: 'landscape'
                }, jQuery.proxy(this.togglePosterView, this));
            toggle.append(toggleBanner).append(' | ').append(togglePoster).append(' | ').append(
            toggleLandscape);
            this.toggle = toggle;
            xbmc.rpc.request({
                'context': this,
                'method': 'VideoLibrary.GetTVShows',
                'params': {
                    'properties': [
                        'genre',
                        'plot',
                        'title',
                        'lastplayed',
                        'episode',
                        'year',
                        'playcount',
                        'rating',
                        'thumbnail',
                        'studio',
                        'mpaa',
                        'premiered'
                    ],
                    'sort': {
                        'method': 'sorttitle',
                        'ignorearticle': true
                    }
                },
                'success': function (data) {
                    if (data && data.result && data.result.tvshows) {
                        libraryContainer = $('<div>');
                        libraryContainer.append(toggle);
                        libraryContainer.attr('id', 'tvshowLibraryContainer')
                            .addClass('contentContainer');
                        $('#content').append(libraryContainer);
                    } else {
                        libraryContainer.html('');
                    }
                    $.each($(data.result.tvshows), jQuery.proxy(function (i, item) {
                        var floatableTVShowCover = this.generateThumb('tvshow', item
                            .thumbnail, item.title);
                        floatableTVShowCover.bind('click', {
                            tvshow: item
                        }, jQuery.proxy(this.displayTVShowDetails, this));
                        libraryContainer.append(floatableTVShowCover);
                    }, this));
                    libraryContainer.append($('<div>').addClass('footerPadding'));
                    $('#spinner').hide();
                    libraryContainer.bind('scroll', {
                        activeLibrary: libraryContainer
                    }, jQuery.proxy(this.updateScrollEffects, this));
                    libraryContainer.trigger('scroll');
                    myScroll = new iScroll('tvshowLibraryContainer');
                    if (xbmc.core.getCookie('TVView') !== null &&
                        xbmc.core.getCookie('TVView') !== 'banner'
                    ) {
                        var view = xbmc.core.getCookie('TVView');
                        switch (view) {
                        case 'poster':
                            togglePoster.trigger('click');
                            break;
                        case 'landscape':
                            toggleLandscape.trigger('click');
                            break;
                        }
                    }
                }
            });
        } else {
            libraryContainer.prepend($(".toggle").detach()).show();
            libraryContainer.trigger('scroll');
        }
    },
    profilesOpen: function () {
        this.resetPage();
        $('#profiles').addClass('selected');
        $('.contentContainer').hide();
        var libraryContainer = $('#profilesContainer');
        if (!libraryContainer || libraryContainer.length == 0) {
            $('#spinner').show();
            var currentProfile = "";
            xbmc.rpc.request({
                'method': 'Profiles.GetCurrentProfile',
                'params': {
                    'properties': [
                        'lockmode'
                    ]
                },
                'success': function (data) {
                    if (data)
                        if (data.result)
                            currentProfile = data.result.label;
                }
            });
            xbmc.rpc.request({
                'context': this,
                'method': 'Profiles.GetProfiles',
                'params': {
                    'limits': {
                        'start': 0
                    },
                    'properties': [
                        'thumbnail'
                    ],
                    'sort': {
                        'method': 'sorttitle',
                        'ignorearticle': true
                    }
                },
                'success': function (data) {
                    if (data && data.result && data.result.profiles) {
                        libraryContainer = $('<div>');
                        libraryContainer.attr('id', 'profilesContainer')
                            .addClass('contentContainer');
                        $('#content').append(libraryContainer);
                    } else {
                        libraryContainer.html('');
                    }
                    $.each($(data.result.profiles), jQuery.proxy(function (i, item) {
                        var itemLabel = item.label;
                        if (currentProfile == itemLabel) {
                            itemLabel = itemLabel + "*";
                        }
                        var floatableProfileThumb = this.generateThumb('profile', item
                            .thumbnail, itemLabel);
                        floatableProfileThumb.bind('click', {
                            profile: item
                        }, jQuery.proxy(this.loadProfile, this));
                        libraryContainer.append(floatableProfileThumb);
                    }, this));
                    libraryContainer.append($('<div>').addClass('footerPadding'));
                    $('#spinner').hide();
                    libraryContainer.bind('scroll', {
                        activeLibrary: libraryContainer
                    }, jQuery.proxy(this.updateScrollEffects, this));
                    libraryContainer.trigger('scroll');
                    myScroll = new iScroll('profilesContainer');
                }
            });
        } else {
            libraryContainer.show();
            libraryContainer.trigger('scroll');
        }
    },
    updateScrollEffects: function (event) {
        if (event.data.activeLibrary && $(event.data.activeLibrary).scrollTop() > 0) {
            $('#topScrollFade').fadeIn();
        } else {
            $('#topScrollFade').fadeOut();
        }
    },
    startSlideshow: function (event) {
        xbmc.rpc.request({
            'method': 'Player.Open',
            'params': {
                'item': {
                    'recursive': 'true',
                    'random': 'true',
                    'path': this.replaceAll(event.data.directory.file, "\\", "\\\\")
                }
            },
            'success': function () {}
        });
    },
    showDirectory: function (event) {
        var directory = event.data.directory.file;
        var jsonDirectory = this.replaceAll(directory, "\\", "\\\\");
        this.resetPage();
        $('#pictureLibrary').addClass('selected');
        $('.contentContainer').hide();
        var libraryContainer = $('#pictureLibraryDirContainer' + directory);
        if (!libraryContainer || libraryContainer.length === 0) {
            $('#spinner').show();
            xbmc.rpc.request({
                'context': this,
                'method': 'Files.GetDirectory',
                'params': {
                    'media': 'pictures',
                    'directory': jsonDirectory
                },
                'success': function (data) {
                    if (data && data.result && (data.result.directories || data.result.files)) {
                        libraryContainer = $('<div>');
                        libraryContainer.attr('id', 'pictureLibraryDirContainer' + directory)
                            .addClass('contentContainer');
                        $('#content').append(libraryContainer);
                        var breadcrumb = $('<div>');
                        var seperator = '/';
                        var item = '';
                        var directoryArray = directory.split(seperator);
                        jQuery.each(directoryArray, function (i, v) {
                            if (v !== '') {
                                item += v + seperator;
                                breadcrumb.append($('<div>').text(' > ' + v).css('float',
                                    'left').addClass('breadcrumb'));
                            }
                        });
                        libraryContainer.append(breadcrumb);
                        libraryContainer.append($('<div>').css('clear', 'both'));
                        if (data.result.files) {
                            $.each($(data.result.files), jQuery.proxy(function (i, item) {
                                if (item.filetype == "file") {
                                    var floatableImage = this.generateThumb('image',
                                        item.file, item.label);
                                    libraryContainer.append(floatableImage);
                                } else if (item.filetype == "directory") {
                                    var floatableShare = this.generateThumb('directory',
                                        item.thumbnail, item.label);
                                    floatableShare.bind('click', {
                                        directory: item
                                    }, jQuery.proxy(this.showDirectory, this));
                                    libraryContainer.append(floatableShare);
                                }
                            }, this));
                        }
                        libraryContainer.append($('<div>').addClass('footerPadding'));
                    } else {
                        libraryContainer.html('');
                    }
                    $('#spinner').hide();
                    libraryContainer.bind('scroll', {
                        activeLibrary: libraryContainer
                    }, jQuery.proxy(this.updateScrollEffects, this));
                    libraryContainer.trigger('scroll');
                    myScroll = new iScroll('#pictureLibraryDirContainer' + directory);
                }
            });
        } else {
            libraryContainer.show();
            libraryContainer.trigger('scroll');
        }
    },
    pictureLibraryOpen: function () {
        this.resetPage();
        $('#pictureLibrary').addClass('selected');
        $('.contentContainer').hide();
        var libraryContainer = $('#pictureLibraryContainer');
        if (!libraryContainer || libraryContainer.length === 0) {
            $('#spinner').show();
            xbmc.rpc.request({
                'context': this,
                'method': 'Files.GetSources',
                'params': {
                    'media': 'pictures'
                },
                'success': function (data) {
                    if (data && data.result && data.result.shares) {
                        libraryContainer = $('<div>');
                        libraryContainer.attr('id', 'pictureLibraryContainer')
                            .addClass('contentContainer');
                        $('#content').append(libraryContainer);
                    } else {
                        libraryContainer.html('');
                    }
                    $.each($(data.result.shares), jQuery.proxy(function (i, item) {
                        var floatableShare = this.generateThumb('directory', item
                            .thumbnail, item.label);
                        floatableShare.bind('click', {
                            directory: item
                        }, jQuery.proxy(this.showDirectory, this));
                        libraryContainer.append(floatableShare);
                    }, this));
                    libraryContainer.append($('<div>').addClass('footerPadding'));
                    $('#spinner').hide();
                    libraryContainer.bind('scroll', {
                        activeLibrary: libraryContainer
                    }, jQuery.proxy(this.updateScrollEffects, this));
                    libraryContainer.trigger('scroll');
                    myScroll = new iScroll('#pictureLibraryContainer');
                }
            });
        } else {
            libraryContainer.show();
            libraryContainer.trigger('scroll');
        }
    }
};
