/*
 *      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 NowPlayingManager = function () {
    this.init();
    return true;
}

NowPlayingManager.prototype = {
    updateCounter: 0,
    activePlayer: "",
    activePlayerId: -1,
    currentItem: -1,
    playing: false,
    paused: false,
    playlistid: -1,

    init: function () {
        $('#pbPause').hide(); /* Assume we are not playing something */
        this.bindPlaybackControls();
        this.updateState();
        $('#nextTrack').bind('click', jQuery.proxy(this.showPlaylist, this));
        $('#nowPlayingPlaylist').bind('click', function () {
            return false;
        });
        $(window).bind('click', jQuery.proxy(this.hidePlaylist, this));
    },
    updateState: function () {
        xbmc.rpc.request({
            'context': this,
            'method': 'Player.GetActivePlayers',
            'timeout': 3000,
            'success': function (data) {
                if (data && data.result && data.result.length > 0) {
                    if (data.result[0].playerid != this.activePlayerId) {
                        this.activePlayerId = data.result[0].playerid;
                        this.activePlayer = data.result[0].type;
                        if (this.activePlayer == "audio") {
                            this.stopVideoPlaylistUpdate();
                            this.displayAudioNowPlaying();
                        } else if (this.activePlayer == "video") {
                            this.stopAudioPlaylistUpdate();
                            this.displayVideoNowPlaying();
                        } else {
                            this.stopVideoPlaylistUpdate();
                            this.stopAudioPlaylistUpdate();
                            this.activePlayer = "";
                            this.activePlayerId = -1;
                        }

                        this.stopRefreshTime();
                        this.updatePlayer();
                    }
                } else if (!data || !data.result || data.result.length <= 0) {
                    this.stopVideoPlaylistUpdate();
                    this.stopAudioPlaylistUpdate();
                    this.activePlayer = "";
                    this.activePlayerId = -1;
                }

                if (this.activePlayerId >= 0) {
                    this.showFooter();
                } else {
                    this.stopRefreshTime();
                    this.hideFooter();
                }

                setTimeout(jQuery.proxy(this.updateState, this), 1000);
            },
            'error': function (data, error) {
                xbmc.core.displayCommunicationError();
                setTimeout(jQuery.proxy(this.updateState, this), 2000);
            }
        });
    },
    updatePlayer: function () {
        xbmc.rpc.request({
            'context': this,
            'method': 'Player.GetProperties',
            'params': {
                'playerid': this.activePlayerId,
                'properties': [
                    'playlistid',
                    'speed',
                    'position',
                    'totaltime',
                    'time'
                ]
            },
            'success': function (data) {
                if (data && data.result) {
                    this.playlistid = data.result.playlistid;
                    this.playing = data.result.speed != 0;
                    this.paused = data.result.speed == 0;
                    this.currentItem = data.result.position;
                    this.trackBaseTime = xbmc.core.timeToDuration(data.result.time);
                    this.trackDurationTime = xbmc.core.timeToDuration(data.result.totaltime);
                    if (!this.autoRefreshAudioData && !this.autoRefreshVideoData && this.playing) {
                        if (this.activePlayer == 'audio') {
                            this.autoRefreshAudioData = true;
                            this.refreshAudioData();
                        } else if (this.activePlayer == 'video') {
                            this.autoRefreshVideoData = true;
                            this.refreshVideoData();
                        }
                    }
                }
                if ((this.autoRefreshAudioData || this.autoRefreshVideoData) && !this
                    .activeItemTimer) {
                    this.activeItemTimer = 1;
                    setTimeout(jQuery.proxy(this.updateActiveItemDurationLoop, this), 1000);
                }
            }
        });
    },
    bindPlaybackControls: function () {
        $('#pbNext').bind('click', jQuery.proxy(this.nextTrack, this));
        $('#pbPrev').bind('click', jQuery.proxy(this.prevTrack, this));
        $('#pbStop').bind('click', jQuery.proxy(this.stopTrack, this));
        $('#pbPlay').bind('click', jQuery.proxy(this.playPauseTrack, this));
        $('#pbPause').bind('click', jQuery.proxy(this.playPauseTrack, this));
        that = this
        $(document).keypress(function (event) {
            switch (event.which) {
            case 32: //spacebar
                event.preventDefault()
                jQuery.proxy(that.playPauseTrack, that)();
                break;
            case 120: //x key
                event.preventDefault()
                jQuery.proxy(that.stopTrack, that)();
                break;
            case 44: //period key
                event.preventDefault()
                jQuery.proxy(that.nextTrack, that)();
                break;
            case 46: //comma key
                event.preventDefault()
                jQuery.proxy(that.prevTrack, that)();
                break;
            }
        });
    },
    showPlaylist: function () {
        $('#nextText').html('Playlist: ');
        $('#nowPlayingPlaylist').show();
        return false;
    },
    hidePlaylist: function () {
        $('#nextText').html('Next: ');
        $('#nowPlayingPlaylist').hide();
        return false;
    },
    hideFooter: function () {
        $('#footerPopover').hide();
        $('#overlay').css('bottom', '0px');
    },
    showFooter: function () {
        $('#footerPopover').show();
        $('#overlay').css('bottom', '150px');
    },
    nextTrack: function () {
        if (this.activePlayer) {
            xbmc.rpc.request({
                'method': 'Player.GoTo',
                'params': {
                    'playerid': this.activePlayerId,
                    'to': 'next'
                },
                'success': function () {}
            });
        }
    },
    prevTrack: function () {
        if (this.activePlayer) {
            xbmc.rpc.request({
                'method': 'Player.GoTo',
                'params': {
                    'playerid': this.activePlayerId,
                    'to': 'previous'
                },
                'success': function () {}
            });
        }
    },
    stopTrack: function () {
        if (this.activePlayer) {
            xbmc.rpc.request({
                'context': this,
                'method': 'Player.Stop',
                'params': {
                    'playerid': this.activePlayerId
                },
                'success': function (data) {
                    if (data && data.result == 'OK') {
                        this.playing = false;
                        this.paused = false;
                        this.trackBaseTime = 0;
                        this.trackDurationTime = 0;
                        this.showPlayButton();
                    }
                }
            });
        }
    },
    playPauseTrack: function () {
        if (this.activePlayer) {
            var method = ((this.playing || this.paused) ? 'Player.PlayPause' : 'Playlist.Play');
            xbmc.rpc.request({
                'context': this,
                'method': method,
                'params': {
                    'playerid': this.activePlayerId
                },
                'success': function (data) {
                    if (data && data.result) {
                        this.playing = data.result.speed != 0;
                        this.paused = data.result.speed == 0;
                        if (this.playing) {
                            this.showPauseButton();
                        } else {
                            this.showPlayButton();
                        }
                    }
                }
            });
        }
    },
    showPauseButton: function () {
        $('#pbPause').show();
        $('#pbPlay').hide();
    },
    showPlayButton: function () {
        $('#pbPause').hide();
        $('#pbPlay').show();
    },
    displayAudioNowPlaying: function () {
        if (!this.autoRefreshAudioPlaylist) {
            this.autoRefreshAudioPlaylist = true;
            this.updateAudioPlaylist();
        }
    },
    displayVideoNowPlaying: function () {
        if (!this.autoRefreshVideoPlaylist) {
            this.autoRefreshVideoPlaylist = true;
            this.updateVideoPlaylist();
        }
    },
    playPlaylistItem: function (sender) {
        var sequenceId = $(sender.currentTarget).attr('seq');
        if (!this.activePlaylistItem || (this.activePlaylistItem !== undefined && sequenceId != this
                .activePlaylistItem.seq)) {
            xbmc.rpc.request({
                'method': 'Player.GoTo',
                'params': {
                    'playerid': this.activePlayerId,
                    'to': sequenceId
                },
                'success': function () {}
            });
        }
        this.hidePlaylist();
    },
    playlistChanged: function (newPlaylist) {
        if (this.activePlaylist && !newPlaylist || !this.activePlaylist && newPlaylist) {
            return true;
        }
        if (!this.activePlaylist && !newPlaylist) {
            return false;
        }
        if (this.activePlaylist.length != newPlaylist.length) {
            return true;
        }
        for (var i = 0; i < newPlaylist.length; i++) {
            if (!this.comparePlaylistItems(this.activePlaylist[i], newPlaylist[i])) {
                return true;
            }
        }
        return false;
    },
    updateAudioPlaylist: function () {
        xbmc.rpc.request({
            'context': this,
            'method': 'Playlist.GetItems',
            'params': {
                'playlistid': this.playlistid,
                'properties': [
                    'title',
                    'album',
                    'artist',
                    'duration',
                    'thumbnail'
                ]
            },
            'success': function (data) {
                if (data && data.result && data.result.items && data.result.items.length > 0 && data
                    .result.limits.total > 0) {
                    if (!this.activePlaylistItem || this.playlistChanged(data.result.items) || (this
                            .activePlaylistItem && (this.activePlaylistItem.seq != this.currentItem)
                            )) {
                        var ul = $('<ul>');
                        var activeItem;
                        $.each($(data.result.items), jQuery.proxy(function (i, item) {
                            var li = $('<li>');
                            var code = '<span class="duration">' + xbmc.core
                                .durationToString(item.duration) +
                                '</span><div class="trackInfo" title="' + item.title +
                                ' - ' + item.artist + '"><span class="trackTitle">' +
                                item.title + '</span> - <span class="trackArtist">' +
                                item.artist + '</span></div>';
                            if (i == this.currentItem) {
                                activeItem = item;
                                activeItem.seq = i;
                                li.addClass('activeItem');
                            }
                            if (i == (this.currentItem + 1)) {
                                $('#nextTrack').html(code).show();
                            }
                            li.bind('click', jQuery.proxy(this.playPlaylistItem, this));
                            ul.append(li.attr('seq', i).html(code));
                        }, this));
                        if (data.result.limits.total > 1) {
                            if (activeItem && data.result.limits.total - 1 == activeItem.seq) {
                                $('#nextTrack').html(
                                    '<div class="trackInfo">Last track in playlist</div>')
                                .show();
                            }
                            $('#nextText').show();
                            $('#nowPlayingPlaylist').html('').append(ul);
                        } else {
                            $('#nextText').hide();
                            $('#nowPlayingPlaylist').hide();
                            $('#nextTrack').hide();
                        }
                        if (!this.comparePlaylistItems(activeItem, this.activePlaylistItem)) {
                            this.activePlaylistItem = activeItem;
                            if (!this.updateActiveItemDurationRunOnce) {
                                this.updateActiveItemDurationRunOnce = true;
                                this.updatePlayer();
                            }
                        } else if (!activeItem) {
                            this.stopRefreshTime();
                        }
                        this.activePlaylist = data.result.items;
                        $('#videoDescription').hide();
                        $('#audioDescription').show();
                        $('#nowPlayingPanel').show();
                    }
                } else {
                    this.activePlaylist = null;
                    $('#audioDescription').hide();
                    $('#nowPlayingPanel').hide();
                }
                if (this.autoRefreshAudioPlaylist) {
                    setTimeout(jQuery.proxy(this.updateAudioPlaylist, this), 1000);
                }
            },
            'error': function (data) {
                xbmc.core.displayCommunicationError();
                if (this.autoRefreshAudioPlaylist) {
                    setTimeout(jQuery.proxy(this.updateAudioPlaylist, this),
                    2000); /* Slow down request period */
                }
            }
        });
    },
    stopAudioPlaylistUpdate: function () {
        this.autoRefreshAudioPlaylist = false;
        this.updateActiveItemDurationRunOnce = false;
    },
    stopVideoPlaylistUpdate: function () {
        this.autoRefreshVideoPlaylist = false;
        this.updateActiveItemDurationRunOnce = false;
    },
    updateActiveItemDurationLoop: function () {
        this.activeItemTimer = 0;
        this.updatePlayer();
    },
    refreshAudioDataLoop: function () {
        this.audioRefreshTimer = 0;
        this.refreshAudioData();
    },
    refreshAudioData: function () {
        if (this.autoRefreshAudioData && !this.audioRefreshTimer) {
            this.audioRefreshTimer = 1;
            setTimeout(jQuery.proxy(this.refreshAudioDataLoop, this), 1000);
        }
        if (this.playing && !this.paused) {
            this.trackBaseTime++;
        }
        if (this.paused) {
            this.showPlayButton();
        } else if (this.playing) {
            this.showPauseButton();
        }
        if (this.activePlaylistItem) {
            if (this.activePlaylistItem != this.lastPlaylistItem) {
                this.lastPlaylistItem = this.activePlaylistItem;
                var imgPath = xbmc.core.DEFAULT_ALBUM_COVER;
                if (this.activePlaylistItem.thumbnail) {
                    imgPath = 'image/' + encodeURI(this.activePlaylistItem.thumbnail);
                }
                $('#audioCoverArt').html('<img src="' + imgPath + '" alt="' + this.activePlaylistItem.album +
                    ' cover art">');
                $('#audioTrackTitle').html('<span title="' + this.activePlaylistItem.title + '">' + this
                    .activePlaylistItem.title + '</span>');
                if (this.activePlaylistItem.album) {
                    $('#audioAlbumTitle').html('<span title="' + this.activePlaylistItem.album + '">' + this
                            .activePlaylistItem.album + '</span>')
                        .show();
                } else {
                    $('#audioAlbumTitle').hide();
                }
                $('#audioArtistTitle').html(this.activePlaylistItem.artist);
                $('#progressBar').attr('style', '');
            }
            $('#audioDuration').html(xbmc.core.durationToString(this.trackBaseTime) + ' / ' + xbmc.core
                .durationToString(this.trackDurationTime));
            var buttonWidth = $('#progressBar .progressIndicator').width();
            var progressBarWidth = (this.trackBaseTime / this.trackDurationTime) * 100;
            var progressSliderPosition = Math.ceil(($('#progressBar').width() / 100) * progressBarWidth) -
                buttonWidth;
            if (progressSliderPosition < 0) {
                progressSliderPosition = 0;
            }
            if (progressBarWidth <= 100) {
                $('#progressBar .elapsedTime').width(progressBarWidth + '%');
                $('#progressBar .progressIndicator').css('left', progressSliderPosition);
            }
        }
    },
    refreshVideoDataLoop: function () {
        this.videoRefreshTimer = 0;
        this.refreshVideoData();
    },
    refreshVideoData: function () {
        if (this.autoRefreshVideoData && !this.videoRefreshTimer) {
            this.videoRefreshTimer = 1;
            setTimeout(jQuery.proxy(this.refreshVideoDataLoop, this), 1500);
        }
        if (this.playing && !this.paused) {
            this.trackBaseTime++;
        }
        if (this.paused) {
            this.showPlayButton();
        } else if (this.playing) {
            this.showPauseButton();
        }
        if (this.activePlaylistItem) {
            if (this.activePlaylistItem != this.lastPlaylistItem) {
                this.lastPlaylistItem = this.activePlaylistItem;
                var imgPath = xbmc.core.DEFAULT_VIDEO_COVER;
                if (this.activePlaylistItem.thumbnail) {
                    imgPath = 'image/' + encodeURI(this.activePlaylistItem.thumbnail);
                }
                $('#videoCoverArt').html('<img src="' + imgPath + '" alt="' + this.activePlaylistItem.title +
                    ' cover art">');
                $('#videoShowTitle').html(this.activePlaylistItem.showtitle || '&nbsp;');
                var extra = '';
                if (this.activePlaylistItem.season >= 0 && this.activePlaylistItem.episode >= 0) {
                    extra = this.activePlaylistItem.season + 'x' + this.activePlaylistItem.episode + ' ';
                }
                $('#videoTitle').html(extra + this.activePlaylistItem.title);
            }
            $('#videoDuration').html(xbmc.core.durationToString(this.trackBaseTime) + ' / ' + xbmc.core
                .durationToString(this.trackDurationTime));
            var buttonWidth = $('#progressBar .progressIndicator').width();
            var progressBarWidth = (this.trackBaseTime / this.trackDurationTime) * 100;
            var progressSliderPosition = Math.ceil(($('#progressBar').width() / 100) * progressBarWidth) -
                buttonWidth;
            if (progressSliderPosition < 0) {
                progressSliderPosition = 0;
            }
            if (progressBarWidth <= 100) {
                $('#progressBar .elapsedTime').width(progressBarWidth + '%');
                $('#progressBar .progressIndicator').css('left', progressSliderPosition);
            }
        }
    },
    stopRefreshTime: function () {
        this.autoRefreshAudioData = false;
        this.autoRefreshVideoData = false;
    },
    comparePlaylistItems: function (item1, item2) {
        if (!item1 || !item2) {
            if (!item1 && !item2) {
                return true;
            }
            return false;
        }
        if (item1.title != item2.title) {
            return false;
        }
        if (item1.album != item2.album) {
            return false;
        }
        if (item1.artist != item2.artist) {
            return false;
        }
        if (item1.duration != item2.duration) {
            return false;
        }
        if (item1.label != item2.label) {
            return false;
        }
        if (item1.season != item2.season) {
            return false;
        }
        if (item1.episode != item2.episode) {
            return false;
        }
        return true;
    },
    updateVideoPlaylist: function () {
        xbmc.rpc.request({
            'context': this,
            'method': 'Playlist.GetItems',
            'params': {
                'playlistid': this.playlistid,
                'properties': [
                    'title',
                    'season',
                    'episode',
                    'plot',
                    'runtime',
                    'showtitle',
                    'thumbnail'
                ]
            },
            'success': function (data) {
                if (data && data.result && data.result.items && data.result.items.length > 0 && data
                    .result.limits.total > 0) {
                    if (this.playlistChanged(data.result.items)) {
                        var ul = $('<ul>');
                        var activeItem;
                        $.each($(data.result.items), jQuery.proxy(function (i, item) {
                            var li = $('<li>');
                            var extra = '';
                            if (item.season >= 0 && item.episode >= 0) {
                                extra = item.season + 'x' + item.episode + ' ';
                            }
                            var code = '<span class="duration">' + xbmc.core
                                .durationToString(item.runtime) +
                                '</span><div class="trackInfo" title="' + extra + item
                                .title + '"><span class="trackTitle">' + extra + item
                                .title + '</span></div>';
                            if (i == this.currentItem) {
                                activeItem = item;
                                activeItem.seq = i;
                                li.addClass('activeItem');
                            }
                            if (i == (this.currentItem + 1)) {
                                $('#nextTrack').html(code).show();
                            }
                            li.bind('click', jQuery.proxy(this.playPlaylistItem, this));
                            ul.append(li.attr('seq', i).html(code));
                        }, this));
                        if (data.result.limits.total > 1) {
                            $('#nextText').show();
                            if (activeItem && data.result.limits.total == activeItem.seq) {
                                $('#nextTrack').html(
                                    '<div class="trackInfo">Last track in playlist</div>')
                                .show();
                            }
                            $('#nowPlayingPlaylist').html('').append(ul);
                        } else {
                            $('#nextText').hide();
                            $('#nowPlayingPlaylist').hide();
                            $('#nextTrack').hide();
                        }
                        if (!this.comparePlaylistItems(activeItem, this.activePlaylistItem)) {
                            this.activePlaylistItem = activeItem;
                            if (!this.updateActiveItemDurationRunOnce) {
                                this.updateActiveItemDurationRunOnce = true;
                                this.updatePlayer();
                            }
                        } else if (!activeItem) {
                            this.stopRefreshTime();
                        }
                        this.activePlaylist = data.result.items;
                        $('#videoDescription').show();
                        $('#audioDescription').hide();
                        $('#nowPlayingPanel').show();
                    }
                } else {
                    xbmc.rpc.request({
                        'context': this,
                        'method': 'Player.GetItem',
                        'params': {
                            'playerid': this.activePlayerId,
                            'properties': [
                                'title',
                                'season',
                                'episode',
                                'plot',
                                'runtime',
                                'showtitle',
                                'thumbnail'
                            ]
                        },
                        'success': function (data) {
                            if (data && data.result && data.result.item) {
                                this.activePlaylistItem = data.result.item;
                                if (!this.updateActiveItemDurationRunOnce) {
                                    this.updateActiveItemDurationRunOnce = true;
                                    this.updatePlayer();
                                }

                                $('#nextText').hide();
                                $('#nowPlayingPlaylist').hide();
                                $('#nextTrack').hide();

                                $('#videoDescription').show();
                                $('#audioDescription').hide();
                                $('#nowPlayingPanel').show();
                            } else {
                                this.activePlaylist = null;
                                $('#videoDescription').hide();
                                $('#nowPlayingPanel').hide();
                            }
                        },
                        'error': function (data) {
                            xbmc.core.displayCommunicationError();
                            if (this.autoRefreshVideoPlaylist) {
                                setTimeout(jQuery.proxy(this.updateVideoPlaylist, this),
                                    2000); /* Slow down request period */
                            }
                        }
                    });
                }
                if (this.autoRefreshVideoPlaylist) {
                    setTimeout(jQuery.proxy(this.updateVideoPlaylist, this), 1000);
                }
            },
            'error': function (data) {
                xbmc.core.displayCommunicationError();
                if (this.autoRefreshVideoPlaylist) {
                    setTimeout(jQuery.proxy(this.updateVideoPlaylist, this),
                    2000); /* Slow down request period */
                }
            }
        });
    }
}