//  HULU CONFIDENTIAL MATERIAL. DO NOT DISTRIBUTE.
//  Copyright (C) 2009-2010 Hulu, LLC
//  All Rights Reserved
/**
 *
 * htvPlayerView.js
 *
 * Defines the view that contains the Player UI and interaction.
 */
/*jslint maxerr: 1000, nomen: false, evil: false, immed: true, plusplus: false */
/*global LOG, describe */
var $htv;

$htv.Views.PlayerView = function () {
    this.viewName = "PlayerView";

    this.seekState = {};
    this.seekTimer = null;
    this.playerState = {};
    this.progressBarVisible = false;
    this.captionsEnabled = false;
    this.initialized = false;
    this.progressBarButtons = [];
    
    this.SEEK_JUMP_TIME = 15000;
    
    this.updateBarButtons = function () { 
        var i, button, buttonIconPos = null, length = this.progressBarButtons.length, runningXPos = 0, spacer = 2 * 20 + 5; // this is based on brackets in ButtonControl
        
        for (i = 0; i < length; i++) {
            button = this.progressBarButtons[i];
            if (button !== null) {
                // initializing the position
                if (runningXPos === 0) {
                    runningXPos = 74; // the original Browse button x position.
                }
                button.position.x = runningXPos;
                if (button.position.x !== button.control.x || button.position.width !== button.control.width) {
                    button.control.move(button.position);
                }
                
                runningXPos += (button.position.width + spacer);
                buttonIconPos = button.control.iconImagePosition;
                if (buttonIconPos !== null) {
                    runningXPos += buttonIconPos.width + buttonIconPos.x;
                }
                
                // update nav info
                
                if (i !== 0) {
                    // to the left
                    button.nav_info.left = {type: "control", node: this.progressBarButtons[i - 1]};
                }
                if (i !== length - 1) {
                    button.nav_info.right = {type: "control", node: this.progressBarButtons[i + 1]};
                }
                
            }
        }
        // always make pausePlayButton nav_info together
        this.pausePlayButton.nav_info.down = {type: "control", node: this.progressBarButtons[0]};
        this.progressBarButtons[0].nav_info.up = {type: "control", node: this.pausePlayButton};
        this.progressBarButtons[0].nav_info.left = undefined;
        
    };
    
    this._initialize = function (options) {
        var captionsButtonText, captionsEnabled, autoPlayButtonText, autoPlayEnabled, stopButtonOptions, qualityButtonOptions, metadataObject;
        // todo: player canvas stuff for some platforms?
        this._instanceOptions = options; // options may change across initializes.
        $htv.Platform.disableSpotlight();
        
        if (this.initialized === false) {
            

            this.seekState = {
                seeking: false,
                speed: 0,
                seekTime: 0
            };
            this.playerState = {
                state: "INIT",
                timeProgress: 0,
                duration: 0
            };
            
            this.progressBarVisible = false;
            this.seekTimer = $htv.Platform.createTimer(0, null, null);
            this.pausePlayButton.control = $htv.ControlPool.getObject("ButtonControl");
            this.pausePlayButton.control.initialize(this.pausePlayButton.position, this.pausePlayButton, null, {
                focused_image: "images/player-pause-focused.png",
                unfocused_image: "images/player-pause-unfocused.png"
            });
            this.pausePlayButton.control.focus();
            this.pausePlayButton.control.hide();
            this._activeNode = this.pausePlayButton;
            this.progressBar.control = $htv.ControlPool.getObject("PlayerProgressBar");
            this.progressBar.control.initialize(this.progressBar.position, this.progressBar, null, {});
            this.infoBar.control = $htv.ControlPool.getObject("PlayerInfoBar");
            this.infoBar.control.initialize(this.infoBar.position, this.infoBar, null, {});
            this.seekControl.control = $htv.ControlPool.getObject("PlayerSeekControl");
            this.seekControl.control.initialize(this.seekControl.position, this.seekControl, null, {});
            this.closedCaptions.control = $htv.ControlPool.getObject("PlayerClosedCaptions");
            this.closedCaptions.control.initialize(this.closedCaptions.position, this.closedCaptions, null, {});
            this.qualityPopup.control = $htv.ControlPool.getObject("PlayerQualityPopup");
            this.qualityPopup.control.initialize(this.qualityPopup.position, this.qualityPopup, null, {autoswitch: $htv.Platform.properties.livestreaming_autoswitch});
            this.infoBar.control.hide();
            this.progressBar.control.hide();
            this.seekControl.control.hide();
            this.closedCaptions.control.hide();
            this.closedCaptions.control.disable();
            this.hideQualityPopup();
            
            this.browseButton.control = $htv.ControlPool.getObject("ButtonControl");
            this.browseButton.control.initialize(this.browseButton.position, this.browseButton, null, {
                text: "Browse",
                focused_style: $htv.Styles.PlayerControlButtonFocused,
                unfocused_style: $htv.Styles.PlayerControlButtonUnfocused,
                icon_image: "images/icon-toggle.png",
                icon_image_position: {
                    x: -5,
                    y: 3,
                    z: 2,
                    width: 19,
                    height: 19
                }
            });
            this.browseButton.control.hide();
            
            // Special case the UI a bit, depending on whether there is a dedicated stop button
            stopButtonOptions = {
                text: "Stop",
                focused_style: $htv.Styles.PlayerControlButtonFocused,
                unfocused_style: $htv.Styles.PlayerControlButtonUnfocused
            };
            if ($htv.Platform.properties.has_stop_button === true) {
                stopButtonOptions.icon_image = "images/icon-stop.png";
                stopButtonOptions.icon_image_position = {
                    x: -5,
                    y: 3,
                    z: 2,
                    width: 19,
                    height: 19
                };
            }
            
            this.stopButton.control = $htv.ControlPool.getObject("ButtonControl");
            this.stopButton.control.initialize(this.stopButton.position, this.stopButton, null, stopButtonOptions);
            this.stopButton.control.hide();
            
            // more specialcasing based on platform
            this.qualityButton.control = $htv.ControlPool.getObject("ButtonControl");
            qualityButtonOptions = {
                text: "Video Quality: HD",
                focused_style: $htv.Styles.PlayerControlButtonFocused,
                unfocused_style: $htv.Styles.PlayerControlButtonUnfocused
            };
            
            if ($htv.Platform.properties.has_quality_button === true) {
                qualityButtonOptions.icon_image = "images/icon-qualitypopup.png";
                qualityButtonOptions.icon_image_position = {
                    x: -5,
                    y: 3,
                    z: 2,
                    width: 30,
                    height: 19
                };
            }
            this.qualityButton.control.initialize(this.qualityButton.position, this.qualityButton, null, qualityButtonOptions);
            this.qualityButton.control.hide();
            this.updateQualityButtonText();
            
            this.captionsButton.control = $htv.ControlPool.getObject("ButtonControl");
            this.captionsButton.control.initialize(this.captionsButton.position, this.captionsButton, null, {
                text: captionsButtonText,
                focused_style: $htv.Styles.PlayerControlButtonFocused,
                unfocused_style: $htv.Styles.PlayerControlButtonUnfocused
            });
            this.captionsButton.control.hide();
            
            this.autoPlayButton.control = $htv.ControlPool.getObject("ButtonControl");
            this.autoPlayButton.control.initialize(this.autoPlayButton.position, this.autoPlayButton, null, {
                text: autoPlayButtonText,
                focused_style: $htv.Styles.PlayerControlButtonFocused,
                unfocused_style: $htv.Styles.PlayerControlButtonUnfocused
            });
            this.autoPlayButton.control.hide();
            
            this.initialized = true;
        } else {
            
            if (options.hasOwnProperty("start_with_quality") && options.start_with_quality === true) {
                this.showQualityPopup();
                this._navigateToControl(this.qualityPopup);
            } else {
                this.hideQualityPopup();
                this.pausePlayButton.control.focus();
                this.pausePlayButton.control.hide();
                // restore activenode.
                this._navigateToControl(this.pausePlayButton);
            }
        }
        
        if ($htv.Platform.properties.has_browse_while_playing === false) {
            this.progressBarButtons = [this.stopButton, this.qualityButton];
        } else {
            this.progressBarButtons = [this.browseButton, this.stopButton, this.qualityButton];
        }
        
        $htv.Controller.addEventListener("PLAYER_PLAYBACK_REQUESTED", this.infoBar.control);
        $htv.Controller.addEventListener("PLAYER_METADATA_RECEIVED", this.infoBar.control);
        $htv.Controller.addEventListener("PLAYER_METADATA_RECEIVED", this.progressBar.control);
        $htv.Controller.addEventListener("PLAYER_METADATA_RECEIVED", this.seekControl.control);
        $htv.Controller.addEventListener("PLAYER_TIME_PROGRESS", this.closedCaptions.control);
        $htv.Controller.addEventListener("PLAYER_TIME_PROGRESS", this.progressBar.control);
        $htv.Controller.addEventListener("PLAYER_PLAYLIST_RECEIVED", this.closedCaptions.control);
        $htv.Controller.addEventListener("PLAYER_PLAYLIST_RECEIVED", this.progressBar.control);
        $htv.Controller.addEventListener("PLAYER_PLAYLIST_RECEIVED", this.seekControl.control);
        $htv.Controller.addEventListener("PLAYER_PLAYLIST_RECEIVED", this);
        $htv.Controller.addEventListener("PLAYER_ADBREAK_PLAYING", this.closedCaptions.control);
        $htv.Controller.addEventListener("PLAYER_ADBREAK_PLAYING", this.progressBar.control);
        $htv.Controller.addEventListener("PLAYER_RESUMING", this.progressBar.control);
        $htv.Controller.addEventListener("PLAYER_SEEKING", this.progressBar.control);
        $htv.Controller.addEventListener("PLAYER_SEEKING_TO_AD", this.progressBar.control);
        $htv.Controller.addEventListener("PLAYER_SEEK_COMPLETED", this.progressBar.control);
        $htv.Controller.addEventListener("PLAYER_TIME_PROGRESS", this);
        $htv.Controller.addEventListener("PLAYER_STATE_CHANGED", this);
        $htv.Controller.addEventListener("PLAYER_PAUSED", this);
        $htv.Controller.addEventListener("PLAYER_PLAYING", this);
        $htv.Controller.addEventListener("PLAYER_METADATA_RECEIVED", this);
        $htv.Controller.addEventListener("PLAYER_PLAYBACK_FINISHED", this);
        $htv.Controller.addEventListener("PLAYER_PLAYBACK_FINISHED", this.closedCaptions.control);
        $htv.Controller.addEventListener("PLAYER_QUALITY_CHANGED", this.progressBar.control);
        
        // clean up
        this.closedCaptions.control.clearCaptionText();
        this.progressBar.control.handleEvent("PLAYER_TIME_PROGRESS", {milliseconds: 0});
        // call explicitly since event only updates when the bar is visible
        this.progressBar.control.updateProgress();
        
        // todo: fix state based on player state
        if ($htv.Player.isActive()) {
            
            this.playerState.state = $htv.Player.getState();
            // sending metadata
            metadataObject = {metadata: $htv.Player.getMetadata()};
            this.infoBar.control.handleEvent("PLAYER_METADATA_RECEIVED", metadataObject);
            this.progressBar.control.handleEvent("PLAYER_METADATA_RECEIVED", metadataObject);
            this.seekControl.control.handleEvent("PLAYER_METADATA_RECEIVED", metadataObject);
            this.closedCaptions.control.handleEvent("PLAYER_PLAYLIST_RECEIVED", {playlist: $htv.Player.getPlaylistData()});
        }
        
        captionsEnabled = $htv.Profile.getPreference("captions_enabled");

        captionsButtonText = "CC is: OFF";
        if (captionsEnabled === true) {
            this.closedCaptions.control.enable();
            captionsButtonText = "CC is: ON";
            this.captionsEnabled = true;
        }
        this.captionsButton.control.setText(captionsButtonText);
        
        if (this.playerState.has_captions === true) {
            
            if (this.progressBarButtons.indexOf(this.captionsButton) === -1) {
                
                if (this.progressBarButtons.length > 3) {
                    this.progressBarButtons.splice(3, 0, this.captionsButton);
                }
                else {
                    this.progressBarButtons.push(this.captionsButton);    
                }
            }
        } else {
            if (this.progressBarButtons.indexOf(this.captionsButton) !== -1) {
                this.progressBarButtons.splice(this.progressBarButtons.indexOf(this.captionsButton), 1);
            }
        }
        
        if (options && !options.disable_autoplay) {
            this.progressBarButtons.push(this.autoPlayButton);
        }
                
        autoPlayEnabled = $htv.Profile.getPreference("autoplay_enabled");
        autoPlayButtonText = "Autoplay is: OFF";
        if (autoPlayEnabled === true) {
            autoPlayButtonText = "Autoplay is: ON";
        }
        this.autoPlayButton.control.setText(autoPlayButtonText);
        
        this.updateBarButtons();
        
        if (options && options.maximize === true) {
            this.closedCaptions.control.show();
            if ($htv.Player.isPaused()) {
                this.peekAtControls($htv.Constants.CONTROLS_PEEK_DURATION);
            }
        }
    };

    // lazily loads other controls.  I think this is the right approach still..
    this._selectionChanged = function (eventData) {

    };

    this._activatedItem = function (eventData) {

    };
    
    if ($htv.Platform.properties.press_and_hold === false) {
        // PNH : FALSE
        this._seekTick = function () {
            this.seekState.seekTime = this.seekState.seekTime + this.seekState.speed * 10000;
            this.seekControl.control.updateSeekLabels(this.seekState.seekTime);
            this.progressBar.control.updateSeekAdBreaks(
                Math.min(this.playerState.timeProgress, this.seekState.seekTime),
                Math.max(this.playerState.timeProgress, this.seekState.seekTime));
            
        };
        
        // PNH : FALSE
        this._enterSeekMode = function (startTimer) {
            this.seekState.speed = 0;
            this.seekState.seeking = true;
            $htv.Player.pauseVideo();
            this.seekState.seekTime = this.playerState.timeProgress;
            this.seekTimer.setCallback(this, this._seekTick);
            this.seekTimer.setInterval(1000);
            if (startTimer) {
                this.seekTimer.start();
            }
            this.seekControl.control.updateSeekLabels(this.seekState.seekTime, true);
            this.progressBar.control.updateSeekAdBreaks(
                Math.min(this.playerState.timeProgress, this.seekState.seekTime),
                Math.max(this.playerState.timeProgress, this.seekState.seekTime));
            this.seekControl.control.show();
            this.infoBar.control.hide();
            this.progressBar.control.show();
        };
        
        // PNH : FALSE
        this._exitSeekMode = function (resumeVideo) {
            this.seekState.seeking = false;
            $htv.Player.resumeVideo(resumeVideo);
            this.seekControl.control.hide();
            this.progressBar.control.hide();
            this.progressBar.control.resetAdDotsColors();
            this.seekTimer.stop();
            this.progressBar.control.peek();
        };
        
        // PNH : FALSE
        this._handleMoveLeft = function (eventData) {
            if (eventData.is_down) {
                if (this.playerState.state === "VIDEO") {
                    if (this.seekState.seeking === false) {
                        this._enterSeekMode(true);
                    }
                    if (this.seekState.speed > 0) {
                        this.seekState.speed = -1;
                        this._seekTick();
                    }
                    else {
                        this.seekState.speed--;
                        if (this.seekState.speed < -10) {
                            this.seekState.speed = -10;
                        }
                    }
                }
            }
        };
        
        // PNH : FALSE
        this._handleMoveRight = function (eventData) {
            if (eventData.is_down) {
                if (this.playerState.state === "VIDEO") {
                    if (this.seekState.seeking === false) {
                        this._enterSeekMode(true);
                    }
                    if (this.seekState.speed < 0) {
                        this.seekState.speed = 1;
                        this._seekTick();
                    }
                    else {
                        this.seekState.speed++;
                        if (this.seekState.speed > 10) {
                            this.seekState.speed = 10;
                        }
                    }
                }
            }
        };
        
        // PNH : FALSE
        this._handleSeekOK = function () {
            $htv.Player.seekTo(this.seekState.seekTime);
            this._exitSeekMode(false);
        };
        
    } else { // press and hold is enabled
    
        // PNH : TRUE
        this._handleMoveLeft = function (eventData) {
            if (this.playerState.state === "VIDEO") {
                if (eventData.is_hold === true) {
                    if (eventData.is_down === true) {
                        // start the seek
                        this._enterSeekMode(true);
                        this.seekState.speed = -1;
                    } else {
                        // stop seeking that direction..
                        this.seekState.speed = 0;
                        this.seekTimer.stop();
                        this.seekControl.control.updateSeekLabels(this.seekState.seekTime, true);
                        this.progressBar.control.updateSeekAdBreaks(
                            Math.min(this.playerState.timeProgress, this.seekState.seekTime),
                            Math.max(this.playerState.timeProgress, this.seekState.seekTime));
                    }
                }
                else { // flags.repeat = false
                    if (eventData.is_down === false) {
                        // First enter seek mode
                        if (this.seekState.seeking !== true) {
                            this._enterSeekMode(false);
                            this.seekState.speed = 0;
                        }
                        // Then jump left
                        this.seekState.seekTime = Math.max(this.seekState.seekTime - this.SEEK_JUMP_TIME, 0);
                        this.seekControl.control.updateSeekLabels(this.seekState.seekTime, true);
                        this.progressBar.control.updateSeekAdBreaks(
                            Math.min(this.playerState.timeProgress, this.seekState.seekTime),
                            Math.max(this.playerState.timeProgress, this.seekState.seekTime));
                    } // else do nothing
                }
            }
        };
        
        // PNH : TRUE
        this._handleMoveRight = function (eventData) {
            if (this.playerState.state === "VIDEO") {
                if (eventData.is_hold === true) {
                    if (eventData.is_down === true) {
                        this._enterSeekMode(true);
                        this.seekState.speed = 1;
                    } else {
                        // stop seeking that direction..
                        this.seekState.speed = 0;
                        this.seekTimer.stop();
                        this.seekControl.control.updateSeekLabels(this.seekState.seekTime, true);
                        this.progressBar.control.updateSeekAdBreaks(
                            Math.min(this.playerState.timeProgress, this.seekState.seekTime),
                            Math.max(this.playerState.timeProgress, this.seekState.seekTime));
                    }
                }
                else { // flags.repeat = false
                    if (eventData.is_down === false) {
                        // First enter seek mode
                        if (this.seekState.seeking !== true) {
                            this._enterSeekMode(false);
                            this.seekState.speed = 0;
                        }
                        // Then jump right
                        this.seekState.seekTime = Math.min(this.seekState.seekTime + this.SEEK_JUMP_TIME, this.playerState.duration * 1000);
                        this.seekControl.control.updateSeekLabels(this.seekState.seekTime, true);
                        this.progressBar.control.updateSeekAdBreaks(
                            Math.min(this.playerState.timeProgress, this.seekState.seekTime),
                            Math.max(this.playerState.timeProgress, this.seekState.seekTime));
                    } // else do nothing
                }
            }
        };
        
        // PNH : TRUE
        this._enterSeekMode = function (startTimer) {
            if (this.seekState.seeking === false) {
                this.seekState.speed = 0;
                this.seekState.seeking = true;
                $htv.Player.pauseVideo();
                this.seekState.seekTime = this.playerState.timeProgress;
                this.seekControl.control.updateSeekLabels(this.seekState.seekTime, true);
                this.seekTimer.setCallback(this, this._seekTick);
                // SORTA HACK: reduce the seek preview animation frequency
                this.seekTimer.setInterval($htv.Platform.properties.has_animations ? 30 : 100);
                this.seekControl.control.show();
                this.progressBar.control.show();
            }
            if (startTimer) {
                this.seekTimer.start();
            }
        };
        
        // PNH : TRUE
        this._exitSeekMode = function (resumeVideo) {
            this.seekState.seeking = false;
            this.seekControl.control.hide();
            this.seekTimer.stop();
            this.progressBar.control.hide();
            this.progressBar.control.resetAdDotsColors();
            $htv.Player.resumeVideo(resumeVideo);
            this.progressBar.control.peek();
            this.seekState.seekTime = this.playerState.timeProgress;
        };
        
        // PNH : TRUE
        this._seekTick = function () {
            this.seekState.seekTime = this.seekState.seekTime + this.seekState.speed * (this.playerState.duration * 1000 / 100);
            if (this.seekState.seekTime > this.playerState.duration * 1000) {
                this.seekState.seekTime = this.playerState.duration * 1000;
            }
            if (this.seekState.seekTime < 0) {
                this.seekState.seekTime = 0;
            }
            this.seekControl.control.updateSeekLabels(this.seekState.seekTime);
            this.progressBar.control.updateSeekAdBreaks(
                Math.min(this.playerState.timeProgress, this.seekState.seekTime),
                Math.max(this.playerState.timeProgress, this.seekState.seekTime));
        };
        
        // PNH : TRUE
        this._handleSeekOK = function () {
            $htv.Player.seekTo(this.seekState.seekTime);
            // TODO: review this change on PS3. The seek works (i.e. it does resume), but
            // I have a feeling the seek times may be slower on PRESS_OK due to extra pause/plays
            this._exitSeekMode(false);
        };
    }
    
    this.peekAtControls = function (duration) {
        this.progressBar.control.peek(duration);
        this.infoBar.control.peek(duration);
    };
    
    this.updateQualityButtonText = function () {
        var bitrateText = "HD", buttonWidth = 130;
        if (this.playerState.currentBitrate) {
            if (this.playerState.currentBitrate === -1) {
                bitrateText = "Auto";
                buttonWidth = 144;
            } else if (this.playerState.currentBitrate <= 1000) {
                bitrateText = "SD";
                buttonWidth = 130;
            }
            this.qualityButton.position.width = buttonWidth;
            this.updateBarButtons();
            this.qualityButton.control.setText("Video Quality: " + bitrateText);
        }
    };
    
    this._handleEvent = function (eventName, eventData) {
        switch (eventName) {
        case "USER_INPUT":
            this._handleUserInput(eventData);
            break;
        case "LOSING_FOCUS": 
            this._navigateBetweenControls(eventData);
            break;
        case "PLAYER_END_CREDITS_HIT":
            $htv.Controller.resizePlayer($htv.Player.STATE_END_CREDITS);
            break;
        case "PLAYER_STATE_CHANGED":
            this.playerState.state = eventData.state;
            break;
        case "PLAYER_TIME_PROGRESS":
            this.playerState.timeProgress = eventData.milliseconds;
            break;
        case "PLAYER_PAUSED":
            this.peekAtControls($htv.Constants.PAUSED_PEEK_DURATION);
            this.pausePlayButton.control.setImages({
                focused_image: "images/player-play-focused.png",
                unfocused_image: "images/player-play-unfocused.png"
            });
            break;
        case "PLAYER_PLAYING": 
            this.pausePlayButton.control.setImages({
                focused_image: "images/player-pause-focused.png",
                unfocused_image: "images/player-pause-unfocused.png"
            });
            this.peekAtControls();
            break;
        case "PLAYER_PLAYLIST_RECEIVED":
            this.playerState.bitrates = eventData.playlist.bitrates;
            if (eventData.currentBitrate) {
                this.playerState.currentBitrate = eventData.currentBitrate; 
            }
            if (this._activeNode === this.qualityPopup) {
                this._navigateToControl(this.pausePlayButton);
                this.qualityPopup.control.hide();
            }
            this.qualityPopup.control.setButtons(this.playerState.bitrates, this.playerState.currentBitrate);
            this.updateQualityButtonText();
            break;
        case "PLAYER_METADATA_RECEIVED":
            this.playerState.duration = eventData.metadata.duration;
            this.playerState.has_captions = eventData.metadata.has_captions;
            if (eventData.metadata.has_captions === true) {
                
                if (this.progressBarButtons.indexOf(this.captionsButton) === -1) {
                    
                    if (this.progressBarButtons.length > 3) {
                        this.progressBarButtons.splice(3, 0, this.captionsButton);
                    }
                    else {
                        this.progressBarButtons.push(this.captionsButton);    
                    }
                }
            } else {
                if (this.progressBarButtons.indexOf(this.captionsButton) !== -1) {
                    this.progressBarButtons.splice(this.progressBarButtons.indexOf(this.captionsButton), 1);
                }
            }
            this.updateBarButtons();
            break;
        case "PLAYER_PLAYBACK_FINISHED":
            $htv.Controller.popView();
            
            break;
        case "CAPTIONS_INITIALIZED":
            this.closedCaptions.control.show();
            break;
        case "QUALITY_CHANGE_REQUESTED":
            this.hideQualityPopup();
            this._navigateToControl(this.qualityButton);
            if (eventData.quality !== this.playerState.currentBitrate) {
                $htv.Player.switchStream(eventData.quality);
                this.playerState.currentBitrate = eventData.quality; 
                $htv.Profile.setPreference("default_bitrate", this.playerState.currentBitrate);
                this.updateQualityButtonText();
            }
            $htv.Player.resumeVideo();
            break;
        case "CONTROL_SHOWN":
            if (eventData.target === this.progressBar) {
                if (this.pausePlayButton.control !== null) {
                    this.pausePlayButton.control.show();
                }
                if (this.stopButton.control !== null) {
                    this.stopButton.control.show();
                }
                if (this.browseButton.control !== null) {
                    if ($htv.Platform.properties.has_browse_while_playing === false) {
                    
                    } else {
                        this.browseButton.control.show();
                    }
                }
                if (this.qualityButton.control !== null) {
                    this.qualityButton.control.show();
                }
                if (this.captionsButton.control !== null) {
                    if (this.playerState.has_captions === true) {
                        this.captionsButton.control.show();
                        this.closedCaptions.control.setVerticalOffset(-80);
                    } else {
                        this.captionsButton.control.hide();
                    }
                }
                if (this.autoPlayButton.control !== null) {
                    if (this._instanceOptions && this._instanceOptions.disable_autoplay === true) {
                        this.autoPlayButton.control.hide();
                    }
                    else {
                        this.autoPlayButton.control.show();
                    }
                }
                this.progressBarVisible = true;
            }
            break;
        case "RETURN_KEY_PRESSED":
            if (eventData.target === this.qualityPopup) {
                this.hideQualityPopup();
                this._navigateToControl(this.qualityButton);
                if (this.playerWasPaused === true) {
                    $htv.Player.pauseVideo(); 
                } else {
                    $htv.Player.resumeVideo();
                }
            }
            else if (this.seekState.seeking === true) {
                this._exitSeekMode(true);
            }
            else if (this._instanceOptions && this._instanceOptions.disable_minimize === true) {
                $htv.Player.stopVideo({force_stop: true});
            }
            else if ($htv.Platform.properties.has_browse_while_playing === false) {
                $htv.Player.stopVideo({force_stop: true});
            }
            else {
                $htv.Controller.resizePlayer($htv.Player.STATE_MINIMIZED);
            }
            break;
        case "CONTROL_HIDDEN":
            if (eventData.target === this.progressBar) {
                if (this.pausePlayButton.control !== null) {
                    this.pausePlayButton.control.hide();
                }
                if (this.stopButton.control !== null) {
                    this.stopButton.control.hide();
                }
                if (this.browseButton.control !== null) {
                    this.browseButton.control.hide();
                }
                if (this.qualityButton.control !== null) {
                    this.qualityButton.control.hide();
                }
                if (this.captionsButton.control !== null) {
                    this.captionsButton.control.hide();
                }
                if (this.autoPlayButton.control !== null) {
                    this.autoPlayButton.control.hide();
                }
                this.closedCaptions.control.clearVerticalOffset();
                this.progressBarVisible = false;
                
                // Reset pause button to activated, unless in quality popup
                if (this._activeNode !== this.qualityPopup && $htv.Player.currentSize() === $htv.Player.STATE_MAXIMIZED) {
                    this._navigateToControl(this.pausePlayButton);
                }
            }
            break;
        case "BUTTON_ACTIVATED":
            if (eventData.target === this.pausePlayButton) {
                if ($htv.Player.isPaused()) {
                    $htv.Player.resumeVideo();
                } else {
                    $htv.Player.pauseVideo(); 
                }
            } else if (eventData.target === this.browseButton) {
                this._handleUserInput({ action: "PLAYER_TOGGLE", is_down: true });
            } else if (eventData.target === this.stopButton) {
                this._handleUserInput({ action: "STOP", is_down: true });
            } else if (eventData.target === this.qualityButton) {
                // TODO: some livestreaming platforms may not be able to choose quality.
                // so we can intercept the popup here with a platform property. (2 places)
                this.showQualityPopup();
                if ($htv.Player.isPaused()) {
                    this.playerWasPaused = true;
                } else {
                    this.playerWasPaused = false;
                }
                this._navigateToControl(this.qualityPopup);
                $htv.Player.pauseVideo();
            } else if (eventData.target === this.captionsButton) {
                this._toggleCaptionsEnabled();
            } else if (eventData.target === this.autoPlayButton) {
                this._toggleAutoPlayEnabled();
            }
            break;
        default: 
            
            break;
        }
    };
    
    this._toggleCaptionsEnabled = function () {
        if (this.captionsEnabled === false) { // todo: CCbutton setText based on events.
            this.closedCaptions.control.enable();
            this.closedCaptions.control.show();
            this.captionsButton.control.setText("CC is: ON");
        } else {
            this.closedCaptions.control.disable();
            this.closedCaptions.control.hide();
            this.captionsButton.control.setText("CC is: OFF");
        }
        this.captionsEnabled = !this.captionsEnabled;
        $htv.Profile.setPreference("captions_enabled", this.captionsEnabled);
    };
    
    this._toggleAutoPlayEnabled = function () {
        if ($htv.Profile.getPreference("autoplay_enabled") === true) {
            this.autoPlayButton.control.setText("Autoplay is: OFF");
            $htv.Profile.setPreference("autoplay_enabled", false);
        } else {
            this.autoPlayButton.control.setText("Autoplay is: ON");
            $htv.Profile.setPreference("autoplay_enabled", true);
        }
    };
    
    this._handleUserInput = function (eventData) {
        var handled = false;
        switch (eventData.action) {
        case "INSTANT_REPLAY":
            if (this.playerState.state === "VIDEO") {
                $htv.Player.instantReplay();
            }
            handled = true;
            break;
        case "PLAY":
            if (eventData.is_down === true) {
                if (this.seekState.seeking === true) {
                    this._handleSeekOK();
                    handled = true;
                }
                else {
                    // todo: check if we need to hide?
                    this.hideQualityPopup();
                    this._navigateToControl(this.pausePlayButton);
                    $htv.Player.resumeVideo();
                    handled = true;
                }
            }
            break;
        case "STOP":
            if (eventData.is_down === true) {
                if (this.seekState.seeking === true) {
                    this._exitSeekMode(false);
                }
                $htv.Player.stopVideo({force_stop: true});
                handled = true;
            }
            break;
        case "PAUSE":
            if (eventData.is_down === true) {
                $htv.Player.pauseVideo();
                this.peekAtControls($htv.Constants.PAUSED_PEEK_DURATION);
                handled = true;
            }
            break;
        case "PLAY_PAUSE":
            if (eventData.is_down === true) {
                if ($htv.Player.isPaused()) {
                    if (this.seekState.seeking === true) {
                        this._handleSeekOK();
                        handled = true;
                    }
                    else {
                        // todo: check if we need to hide?
                        this.hideQualityPopup();
                        this._navigateToControl(this.pausePlayButton);
                        $htv.Player.resumeVideo();
                        handled = true;
                    }
                }
                else {
                    $htv.Player.pauseVideo();
                    this.peekAtControls($htv.Constants.PAUSED_PEEK_DURATION);
                    handled = true;
                }
            }
            break;
        case "PRESS_OK":
            if (this.seekState.seeking === true) {
                handled = true;
                
                if (eventData.is_down === false) {
                    this._handleSeekOK();
                }
            }
            break;
        case "KEY_SUBTITLE":
            if (eventData.is_down === true) {
                if (this.seekState.seeking === true) {
                    this._exitSeekMode(true);
                }
                this._toggleCaptionsEnabled();
                handled = true;
            }
            break;
        case "KEY_INFO":
            this.peekAtControls();
            handled = true;
            break;
        case "ADVANCE_FORWARD":
            if (eventData.is_down === true) {
                if ($htv.Platform.properties.livestreaming === true) {
                    // TODO: some livestreaming platforms may not be able to choose quality.
                    // so we can intercept the popup here with a platform property. (2 places)
                    if (this.seekState.seeking === true) {
                        this._exitSeekMode(false);
                    }
                    this.showQualityPopup();
                    if ($htv.Player.isPaused()) {
                        this.playerWasPaused = true;
                    } else {
                        this.playerWasPaused = false;
                    }
                    
                    this._navigateToControl(this.qualityPopup);
                    $htv.Player.pauseVideo();
                    handled = true;
                }
            }
            break;
        case "ADVANCE_FORWARD_2":
        case "KEY_FF":
        case "KEY_FF_JUMP":
            this.hideQualityPopup();
            this._navigateToControl(this.pausePlayButton);
            this._handleMoveRight(eventData);
            handled = true;
            break;
        case "ADVANCE_BACKWARD_2":
        case "KEY_RW":
        case "KEY_RW_JUMP":
            this.hideQualityPopup();
            this._navigateToControl(this.pausePlayButton);
            this._handleMoveLeft(eventData);
            handled = true;
            break;
        case "MOVE_RIGHT":
            if (this.seekState.seeking === true || this._activeNode === this.pausePlayButton) {
                this._handleMoveRight(eventData);
            } else {
                this._activeNode.control.handleEvent("USER_INPUT", eventData);
                
                if (this._activeNode === this.browseButton || this._activeNode === this.stopButton || this._activeNode === this.qualityButton || this._activeNode === this.captionsButton || this._activeNode === this.autoPlayButton) {
                    this.peekAtControls($htv.Constants.ACTIVE_PEEK_DURATION);
                }
                else {
                    this.peekAtControls();
                }
            }
            handled = true;
            break;
        case "MOVE_LEFT":
            if (this.seekState.seeking === true || this._activeNode === this.pausePlayButton) {
                this._handleMoveLeft(eventData);
            } else {
                this._activeNode.control.handleEvent("USER_INPUT", eventData);
                
                if (this._activeNode === this.browseButton || this._activeNode === this.stopButton || this._activeNode === this.qualityButton || this._activeNode === this.captionsButton || this._activeNode === this.autoPlayButton) {
                    this.peekAtControls($htv.Constants.ACTIVE_PEEK_DURATION);
                }
                else {
                    this.peekAtControls();
                }
            }
            handled = true;
            break;
        case "MOVE_DOWN":
            if (this.seekState.seeking === true) {
                this._exitSeekMode(true);
            }
            else {
                if (eventData.is_down === true) {
                    if (this.progressBarVisible === true) {
                        this._activeNode.control.handleEvent("USER_INPUT", eventData);
                    }
                    if (this._activeNode === this.browseButton || this._activeNode === this.stopButton || this._activeNode === this.qualityButton || this._activeNode === this.captionsButton) {
                        this.peekAtControls($htv.Constants.ACTIVE_PEEK_DURATION);
                    }
                    else {
                        this.peekAtControls();
                    }
                }
            }
            handled = true;
            break;
        case "MOVE_UP":
            if (eventData.is_down === true) {
                if (this.seekState.seeking === false) {
                    if (this.progressBarVisible === true) {
                        this._activeNode.control.handleEvent("USER_INPUT", eventData);
                    }

                    if (this._activeNode === this.browseButton || this._activeNode === this.stopButton || this._activeNode === this.qualityButton || this._activeNode === this.captionsButton) {
                        this.peekAtControls($htv.Constants.ACTIVE_PEEK_DURATION);
                    }
                    else {
                        this.peekAtControls();
                    }
                } else {
                    this._exitSeekMode(true);
                }
            }
            handled = true;
            break;
        case "INFO":
            if (eventData.is_down === true && this.seekState.seeking === false) {
                this.peekAtControls();
            }
            handled = true;
            break;
        case "VOLUME_UP":
            $htv.Platform.increaseVolume();
            handled = true;
            break;
        case "VOLUME_DOWN":
            $htv.Platform.decreaseVolume();
            break;
        case "PLAYER_TOGGLE":
            if (eventData.is_down === true) {
                if (this.seekState.seeking === true) {
                    this._exitSeekMode(true);
                }
                if (this._instanceOptions.disable_minimize === true) {
                    $htv.Player.stopVideo({force_stop: true});
                }
                else if ($htv.Platform.properties.has_browse_while_playing === false) {
                    $htv.Player.stopVideo({force_stop: true});
                }
                else {
                    $htv.Controller.resizePlayer($htv.Player.STATE_MINIMIZED);
                }
            }
            handled = true;
            break;
        default:
            
            break;
        }
        // forward to active node, maybe?
        if (!handled) {
            this._activeNode.control.handleEvent("USER_INPUT", eventData);
        }
    };
    
    
    this.showQualityPopup = function () {
        if (this.qualityPopup.control !== null) {
            this.qualityPopup.control.show();
            this.qualityPopup.control.updateActiveIndex(this.playerState.currentBitrate);
        }
    };
    
    this.hideQualityPopup = function () {
        if (this.qualityPopup.control !== null) {
            this.qualityPopup.control.hide();
        }
    };
    
    var view = {
        view: this,
        callback: this._handleEvent,
        fireEvent: function (eventName, eventData) {
            this.callback.call(this.view, eventName, eventData);
        }
    };
    
    this.seekControl = {
        view: view,
        type: "PlayerSeekControl",
        position: {// todo: update position
            x: 0,
            y: 0,
            z: 11,
            width: 960,
            height: 540
        },
        control: null 
    };
    
    this.progressBar = {
        view: view,
        type: "PlayerProgressBar",
        position: {
            x: 37,
            y: 440,
            z: 12,
            width: 601,
            height: 91
        },
        control: null
    };
    
    this.infoBar = {
        view: view,
        type: "PlayerInfoBar",
        position: {
            x: 37,
            y: 37,
            z: 12,
            width: 601,
            height: 91
        },
        control: null
    };
    
    this.closedCaptions = {
        view: view,
        type: "PlayerClosedCaptions",
        position: {
            x: 40,
            y: 447,
            z: 10,
            width: 880,
            height: 66
        },
        control: null
    };
    
    this.qualityPopup = {
        view: view,
        type: "PlayerQualityPopup",
        position: {
            x: 0,
            y: 0,
            z: 24,
            width: 960,
            height: 540
        },
        control: null
    };
    
    this.pausePlayButton = {
        view: view,
        type: "ButtonControl",
        position: {
            x: 48,
            y: this.progressBar.position.y,
            z: 16,
            width: 53,
            height: 39
        },
        control: null
    };
    
    this.browseButton = {
        view: view,
        type: "ButtonControl",
        position: {
            x: 74,
            y: this.progressBar.position.y + 43,
            z: 20,
            width: 54,
            height: 23
        },
        control: null
    };
    
    this.stopButton = {
        view: view,
        type: "ButtonControl",
        position: {
            x: 186,
            y: this.progressBar.position.y + 43,
            z: 20,
            width: 34,
            height: 23
        },
        control: null
    };
    
    this.qualityButton = {
        view: view,
        type: "ButtonControl",
        position: {
            x: 266,
            y: this.progressBar.position.y + 43,
            z: 20,
            width: 145,
            height: 23
        },
        control: null
    };
    
    this.autoPlayButton = {
        view: view,
        type: "ButtonControl",
        position: {
            x: 465,
            y: this.progressBar.position.y + 43,
            z: 20,
            width: 122,
            height: 23
        },
        control: null
    };
    
    this.captionsButton = {
        view: view,
        type: "ButtonControl",
        position: {
            x: 570,
            y: this.progressBar.position.y + 43,
            z: 20,
            width: 84,
            height: 23
        },
        control: null
    };
    
    this.pausePlayButton.nav_info = {
        down: {
            type: "control",
            node: this.browseButton
        }
    };
    
    this.browseButton.nav_info = {
        up: {
            type: "control",
            node: this.pausePlayButton
        },
        right: {
            type: "control",
            node: this.stopButton
        }
    };
    
    this.stopButton.nav_info = {
        up: {
            type: "control",
            node: this.pausePlayButton
        },
        left: {
            type: "control",
            node: this.browseButton
        },
        right: {
            type: "control",
            node: this.qualityButton
        }
    };
    
    this.qualityButton.nav_info = {
        up: {
            type: "control",
            node: this.pausePlayButton
        },
        left: {
            type: "control",
            node: this.stopButton
        },
        right: {
            type: "control",
            node: this.autoPlayButton
        }
    };
    
    this.autoPlayButton.nav_info = {
        up: {
            type: "control",
            node: this.pausePlayButton
        },
        left: {
            type: "control",
            node: this.qualityButton
        }
    };
    
    this.captionsButton.nav_info = {
        up: {
            type: "control",
            node: this.pausePlayButton
        },
        left: {
            type: "control",
            node: this.autoPlayButton
        }
    };
    
    // attach nav_info
  
    this._controls.push(this.autoPlayButton);
  
    this._controls.push(this.captionsButton);
    this._controls.push(this.closedCaptions);
    this._controls.push(this.infoBar);
    
    this._controls.push(this.pausePlayButton);
    this._controls.push(this.progressBar);
    this._controls.push(this.browseButton);
    this._controls.push(this.stopButton);
    this._controls.push(this.qualityButton);
    this._controls.push(this.qualityPopup);
    this._controls.push(this.seekControl);
    
    this._activeNode = null;
    this.initialize = this._initialize;
    this.handleEvent = this._handleEvent;
    this.saveState = function () {
        return {
            viewName: "PlayerView"
        };
    
    };
    this.restoreState = function () {
        
    };
    
    this.discard = function () {
        
        this._activeNode.control.unfocus();
        if (this.seekState.seeking === true) {
            this._exitSeekMode(true);
        }
        for (var i = 0; i < this._controls.length; i++) {
            if (this._controls[i].control !== null) {
                this._controls[i].control.hide();
            }
        }
        $htv.Controller.removeEventListener("PLAYER_PLAYBACK_REQUESTED", this.infoBar.control);
        $htv.Controller.removeEventListener("PLAYER_METADATA_RECEIVED", this.infoBar.control);
        $htv.Controller.removeEventListener("PLAYER_METADATA_RECEIVED", this.progressBar.control);
        $htv.Controller.removeEventListener("PLAYER_METADATA_RECEIVED", this.seekControl.control);
        $htv.Controller.removeEventListener("PLAYER_TIME_PROGRESS", this.closedCaptions.control);
        $htv.Controller.removeEventListener("PLAYER_TIME_PROGRESS", this.progressBar.control);
        $htv.Controller.removeEventListener("PLAYER_PLAYLIST_RECEIVED", this.closedCaptions.control);
        $htv.Controller.removeEventListener("PLAYER_PLAYLIST_RECEIVED", this.progressBar.control);
        $htv.Controller.removeEventListener("PLAYER_PLAYLIST_RECEIVED", this.seekControl.control);
        $htv.Controller.removeEventListener("PLAYER_PLAYLIST_RECEIVED", this);
        $htv.Controller.removeEventListener("PLAYER_ADBREAK_PLAYING", this.closedCaptions.control);
        $htv.Controller.removeEventListener("PLAYER_ADBREAK_PLAYING", this.progressBar.control);
        $htv.Controller.removeEventListener("PLAYER_TIME_PROGRESS", this);
        $htv.Controller.removeEventListener("PLAYER_STATE_CHANGED", this);
        $htv.Controller.removeEventListener("PLAYER_PAUSED", this);
        $htv.Controller.removeEventListener("PLAYER_PLAYING", this);
        $htv.Controller.removeEventListener("PLAYER_RESUMING", this.progressBar.control);
        $htv.Controller.removeEventListener("PLAYER_SEEKING", this.progressBar.control);
        $htv.Controller.removeEventListener("PLAYER_SEEKING_TO_AD", this.progressBar.control);
        $htv.Controller.removeEventListener("PLAYER_SEEK_COMPLETED", this.progressBar.control);
        $htv.Controller.removeEventListener("PLAYER_METADATA_RECEIVED", this);
        $htv.Controller.removeEventListener("PLAYER_PLAYBACK_FINISHED", this);
        $htv.Controller.removeEventListener("PLAYER_PLAYBACK_FINISHED", this.closedCaptions.control);
        $htv.Controller.removeEventListener("PLAYER_QUALITY_CHANGED", this.progressBar.control);
        
        $htv.Platform.enableSpotlight();
        this._activeNode = null;
    };  
};

$htv.Views.PlayerView.prototype = new $htv.Views.BaseView();

$htv.Views.NamedViews.PlayerView = new $htv.Views.PlayerView();
