//  HULU CONFIDENTIAL MATERIAL. DO NOT DISTRIBUTE.
//  Copyright (C) 2009-2010 Hulu, LLC
//  All Rights Reserved
/**
*
* htvControls.js
*
* This class defines controls for the app.  The controls render UI by
* making calls to the Platform API calls ($htv.Platform.create*)
*
* These are mapped in the layout tree defined by each view (refer to htvViews).
* The mapping can be one to one between cmtypes or specialized in the tree. 
* i.e. the tree can specify that menus are rendered differently at a specific
* level (i.e. under the show page) but we can also specialize this within twinkie.
*/
/*jslint maxerr: 1000, nomen: false, evil: false, immed: true, plusplus: false */
/*global LOG, describe */
var $htv;

$htv.Controls = {  
    // Sliding menu: 5 buttons that slide around.
    SlidingMenu: function () {
        this.height = 0;
        this.width = 0;
        this.x = 0;
        this.y = 0;
        this.z = 0;
        this.node = null;
        this.className = "SlidingMenu";
        this.items = null;
        this.displayItems = [];
        this.activeIndex = 0;
        this.visible = true;
        this.canvas = null;
        this.menu_title = null;
        this.leftBracket = null;
        this.rightBracket = null;
        this.itemSpacing = 60;
        this.visibleCount = 5;
        this.menuItemsContainer = null;
        this.menuSpacers = null;
        this.initialized = false;
        this.showDownArrow = false;
        this.leftArrow = null;
        this.rightArrow = null;
        this.downArrow = null;
        
        // make request to twinkie for info
        this.initialize = function (position, target, url, options) {
            this.height = position.height;
            this.width = position.width;
            this.x = position.x;
            this.y = position.y;
            this.z = position.z;
            this.node = target;
            this.activeIndex = 0;
            this.initialized = false;
            if (options.hasOwnProperty("canvas")) {
                this.canvas = options.canvas;
            }

            if (options.hasOwnProperty("visible_item_count")) {
                this.visibleCount = options.visible_item_count;
            }
            if (options.hasOwnProperty("show_down_arrow")) {
                this.showDownArrow = options.show_down_arrow;
            }
            // data source
            if (options.items) {
                this.items = options.items;
            }
            else {
                this.items = $htv.Utils.createTwinkieCollection(['items_url', 'login_required', 'cmtype', 'title', 'start_at_end', 'view_name']);
                
                // the data source requires a login token (recommendations, queue)
                if (options.hasOwnProperty("login_required") && (options.login_required === 1)) {
                    this.login_required = true;
                    if (url.indexOf("user_id=") === url.length - 8) {
                        url = url + $htv.Profile.getUserToken();
                    }
                }
                
                url = $htv.Utils.applyGlobalContext(url);
            }
            // populate the collection
            this.items.initialize(url, this, this.initializeResult);
            
            if (options.hasOwnProperty("view_title")) {
                this.menu_title = options.view_title;
            }
            
            if (options.hasOwnProperty("indexHint")) {
                this.activeIndex = options.indexHint;
            }
        };
        
        // twinkie result handler
        this.initializeResult = function () {
            if (this.activeIndex >= this.items.getLength()) {
                this.activeIndex = 0;
            }
            this.render();
            this.initialized = true;
            this.node.view.fireEvent("INITIALIZE_COMPLETE", {
                target: this.node
            });
            this.node.view.fireEvent("MENU_SELECTION_CHANGED", {
                items_url: this.items.getItemAt(this.activeIndex).item.items_url,
                cmtype: this.items.getItemAt(this.activeIndex).item.cmtype,
                options: {
                    login_required: this.items.getItemAt(this.activeIndex).item.login_required
                },
                target: this.node
            });
            
        };
        
        
        this.render = function () {
            var startIndex, i, index;
            this.displayItems = new Array(this.visibleCount);
            this.rightArrow = $htv.Platform.createImage({
                x: this.x + this.width - 8,
                y: this.y + 2,
                z: this.z,
                width: 8,
                height: 21
            }, "images/arrow-right.png", this.canvas);
            this.rightArrow.hide();
            this.leftArrow = $htv.Platform.createImage({
                x: this.x,
                y: this.y + 2,
                z: this.z,
                width: 8,
                height: 21
            }, "images/arrow-left.png", this.canvas);
            this.leftArrow.hide();
            this.downArrow = $htv.Platform.createImage({
                x: this.x + (this.width / 2) - 11,
                y: this.y + this.height + 2,
                z: this.z,
                width: 21,
                height: 8
            }, "images/down-arrow.png", this.canvas);
            this.downArrow.hide();
            this.leftBracket = $htv.Platform.createImage({
                x: -100,
                y: -100,
                z: this.z,
                width: 6,
                height: 27
            }, "images/bracket_small_left.png", this.canvas);
            this.leftBracket.hide();
            this.rightBracket = $htv.Platform.createImage({
                x: -100,
                y: -100,
                z: this.z,
                width: 6,
                height: 27
            }, "images/bracket_small_right.png", this.canvas);
            this.rightBracket.hide();
            
            // First just create the visible items (position doesn't matter)
            startIndex = this.activeIndex - Math.floor((this.visibleCount - 1) / 2);
            for (i = 0; i < this.visibleCount; i++) {
                index = startIndex + i;
                if (index >= 0 && index < this.items.getLength()) {
                    this.displayItems[i] = $htv.Platform.createLabel({
                        x: this.width / 2,
                        y: this.y,
                        z: this.z,
                        width: this.width,
                        height: this.height
                    }, this.items.getItemAt(index).item.title, this.canvas, { styleName: $htv.Styles.SlidingMenuItemUnfocused });
                    this.displayItems[i].show();
                }
            }
            this.activeDisplayItemIndex = Math.floor(this.visibleCount / 2); // will never change.
            // Center the active item, then call layout
            
            this.layoutWithFixedItem(this.activeDisplayItemIndex);
            
        };
        
        this.layoutWithFixedItem = function (fixedIndex) {
            var i;
            
            this.displayItems[fixedIndex].move({
                x: this.x + this.width / 2 - this.displayItems[fixedIndex].getTextDimensions().textWidth / 2,
                y: this.y,
                z: this.z,
                width: this.width,
                height: this.height
            }, 250);
            
            // Adjust to the left
            for (i = fixedIndex - 1; i >= 0; i--) {
                
                this.displayItems[i].move({
                    x: this.displayItems[i + 1].getPosition().x - this.itemSpacing - this.displayItems[i].getTextDimensions().textWidth,
                    y: this.y,
                    z: this.z,
                    width: this.width,
                    height: this.height
                }, 250);
            }
            
            // Adjust to the right
            for (i = fixedIndex + 1; i < this.displayItems.length; i++) {
                this.displayItems[i].move({
                    x: this.displayItems[i - 1].getPosition().x + this.displayItems[i - 1].getTextDimensions().textWidth + this.itemSpacing,
                    y: this.y,
                    z: this.z,
                    width: this.width,
                    height: this.height
                }, 250);
            }
        };
        
        this.layoutBrackets = function () {
            if (!$htv.Platform.properties.has_animations) {
                this.leftBracket.hide();
                this.rightBracket.hide();
            }
            
            this.leftBracket.move({
                x: this.displayItems[this.activeDisplayItemIndex].getPosition().x - 14,
                y: this.y - 3,
                z: this.z,
                width: 6,
                height: 27
            }, 250);
            this.rightBracket.move({
                x: this.displayItems[this.activeDisplayItemIndex].getPosition().x + this.displayItems[this.activeDisplayItemIndex].getTextDimensions().textWidth + 7,
                y: this.y - 3,
                z: this.z,
                width: 6,
                height: 27
            }, 250);
            this.leftBracket.show(250);
            this.rightBracket.show(250);
            
            // check for arrow state
            if ((this.activeIndex + Math.floor(this.visibleCount / 2)) < (this.items.getLength() - 1)) {
                this.rightArrow.show();
            } else {
                this.rightArrow.hide();
            }
            if (this.activeIndex - Math.floor(this.visibleCount / 2) > 0) {
                this.leftArrow.show();
            } else {
                this.leftArrow.hide();
            }
            
        };    
        
        this.dispose = function () {
            this.activeIndex = 0;
            while (this.displayItems.length > 0) {
                $htv.Platform.deleteItem(this.displayItems.pop());
            }
            $htv.Platform.deleteItem(this.leftBracket);
            $htv.Platform.deleteItem(this.rightBracket);
            $htv.Platform.deleteItem(this.leftArrow);
            $htv.Platform.deleteItem(this.rightArrow);
            if (this.downArrow !== null) {
                $htv.Platform.deleteItem(this.downArrow);
            }
            $htv.Platform.deleteItem(this.menuItemsContainer);
            this.items = null;
            this.node = null;
            this.height = 0;
            this.width = 0;
            this.x = 0;
            this.y = 0;
            this.z = 0;
            this.leftArrow = null;
            this.rightArrow = null;
            this.downArrow = null;
        };
        
        // called whenever navigation gives control of userinput to this control
        this.focus = function () {
            var i;
            if (this.initialized === false) {
                return;
            }
            
            // Move the brackets immediately so the first focus doesn't move them in from offscreen
            this.leftBracket.move({
                x: this.displayItems[this.activeDisplayItemIndex].getPosition().x - 14,
                y: this.y - 3,
                z: this.z,
                width: 6,
                height: 27
            });
            this.rightBracket.move({
                x: this.displayItems[this.activeDisplayItemIndex].getPosition().x + this.displayItems[this.activeDisplayItemIndex].getTextDimensions().textWidth + 7,
                y: this.y - 3,
                z: this.z,
                width: 6,
                height: 27
            });
            
            if (this.downArrow !== null) {
                this.downArrow.show();
            }
            
            for (i = 0; i < this.items.getLength(); i++) {
                if (this.displayItems[i] && this.displayItems[i] !== null) {
                    if (i === this.activeDisplayItemIndex) {
                        this.displayItems[this.activeDisplayItemIndex].setStyle($htv.Styles.SlidingMenuItemSelectedFocused);
                    } else {
                        this.displayItems[i].setStyle($htv.Styles.SlidingMenuItemFocused);
                    }
                }
            }
            this.layoutBrackets();
            $htv.Platform.updateSpotlight(this.x + this.width / 2, this.y + this.height / 2 - 10, 1);
        };
        
        // called whenever navigation takes control of userinput from this control
        this.unfocus = function () {
            var i;
            for (i = 0; i < this.displayItems.length; i++) {
                if (this.displayItems[i] !== null) {
                    this.displayItems[i].setStyle($htv.Styles.SlidingMenuItemUnfocused);
                }
            }
            this.leftArrow.hide();
            this.rightArrow.hide();
            this.leftBracket.hide(250);
            this.rightBracket.hide(250);
            
            if (this.downArrow !== null) {
                this.downArrow.hide();
            }
        };
        
        this.hide = function () {
            var i;
            this.visible = false;
            for (i = 0; i < this.displayItems.length; i++) {
                if (this.displayItems[i] !== null) {
                    this.displayItems[i].hide();
                }
            }
            this.leftArrow.hide();
            this.rightArrow.hide();
            this.leftBracket.hide();
            this.rightBracket.hide();
            
            if (this.downArrow !== null) {
                this.downArrow.hide();
            }
        };
        
        this.show = function () {
            var i;
            this.visible = true;
            for (i = 0; i < this.displayItems.length; i++) {
                if (this.displayItems[i] !== null) {
                    this.displayItems[i].show();
                }
            }
        };
        
        this.handleEvent = function (eventName, eventData) {
            if (eventName === "USER_INPUT") {
                this.handleInput(eventData);
            } else {
                
            }
        };
        
        this.handleInput = function (eventData) {

            
            // TODO: disposal of ones that fall off?
            var i, index, label, title = "";
            switch (eventData.action) {
            case "MOVE_RIGHT":
                if (eventData.is_down === false) {
                    this.rightArrow.setURL("images/arrow-right.png");
                }
                else {
                    this.rightArrow.setURL("images/arrow-right-hover.png");
                    if (this.activeIndex < (this.items.getLength() - 1)) {
                        this.activeIndex++;
                        label = this.displayItems.shift();
                        $htv.Platform.deleteItem(label);
                        
                        index = this.activeIndex + Math.floor(this.visibleCount / 2);
                        if (index < this.items.getLength()) {
                            title = this.items.getItemAt(index).item.title;
                        }
                        this.displayItems.push($htv.Platform.createLabel({
                            x: this.width + 100,
                            y: this.y,
                            z: this.z,
                            width: this.width,
                            height: this.height
                        }, title, this.canvas, {
                            styleName: $htv.Styles.SlidingMenuItemSelectedUnfocused
                        }));
                        // Then layout the rest
                        this.layoutWithFixedItem(this.activeDisplayItemIndex);
                        this.displayItems[this.activeDisplayItemIndex - 1].setStyle($htv.Styles.SlidingMenuItemFocused);
                        this.displayItems[this.activeDisplayItemIndex].setStyle($htv.Styles.SlidingMenuItemSelectedFocused);
                        this.layoutBrackets();
                        
                        this.node.view.fireEvent("MENU_SELECTION_CHANGED", {
                            items_url: this.items.getItemAt(this.activeIndex).item.items_url,
                            cmtype: this.items.getItemAt(this.activeIndex).item.cmtype,
                            options: {
                                login_required: this.items.getItemAt(this.activeIndex).item.login_required
                            },
                            target: this.node
                        });
                    }
                }
                break;
            case "MOVE_LEFT":
                if (eventData.is_down === false) {
                    this.leftArrow.setURL("images/arrow-left.png");
                }
                else {
                    this.leftArrow.setURL("images/arrow-left-hover.png");
                    if (this.activeIndex > 0) {
                        this.activeIndex--;
                        label = this.displayItems.pop();
                        $htv.Platform.deleteItem(label);
                        
                        index = this.activeIndex - Math.floor(this.visibleCount / 2);
                        if (index >= 0) {
                            title = this.items.getItemAt(index).item.title;
                        }
                        
                        this.displayItems.unshift($htv.Platform.createLabel({
                            x: -100,
                            y: this.y,
                            z: this.z,
                            width: this.width,
                            height: this.height
                        }, title, this.canvas, {
                            styleName: $htv.Styles.SlidingMenuItemSelectedUnfocused
                        }));
                        
                        // Then layout the rest
                        this.layoutWithFixedItem(this.activeDisplayItemIndex);
                        this.displayItems[this.activeDisplayItemIndex + 1].setStyle($htv.Styles.SlidingMenuItemFocused);
                        this.displayItems[this.activeDisplayItemIndex].setStyle($htv.Styles.SlidingMenuItemSelectedFocused);
                        this.layoutBrackets();
                        
                        this.node.view.fireEvent("MENU_SELECTION_CHANGED", {
                            items_url: this.items.getItemAt(this.activeIndex).item.items_url,
                            cmtype: this.items.getItemAt(this.activeIndex).item.cmtype,
                            options: {
                                login_required: this.items.getItemAt(this.activeIndex).item.login_required
                            },
                            target: this.node
                        });
                    }
                    
                }
                break;
            case "MOVE_DOWN":
                if (eventData.is_down) {
                    this.downArrow.setURL("images/down-arrow-hover.png");
                } else {
                    this.downArrow.setURL("images/down-arrow.png");
                    this.node.view.fireEvent("LOSING_FOCUS", {
                        nav_dir: "down",
                        item: this.items.getItemAt(this.activeIndex).item,
                        target: this.node
                    });
                }
                break;
            case "KEY_RETURN":
            case "MOVE_UP":
                if (!eventData.is_down || eventData.is_hold) {
                    return;
                }
                this.node.view.fireEvent("LOSING_FOCUS", {
                    nav_dir: "up",
                    item: this.items.getItemAt(this.activeIndex).item,
                    target: this.node
                });
                break;
            case "PRESS_OK":
                if (!eventData.is_down || eventData.is_hold) {
                    return;
                }
                this.node.view.fireEvent("MENU_ITEM_ACTIVATED", {
                    item: this.items.getItemAt(this.activeIndex).item,
                    target: this.node
                });
                break;
            default:
                
                break;
            }
        };
    }
    
    
};

$htv.Controls.singletons = {};

$htv.Controls.VideoProgress = function () {
    this.height = 0;
    this.width = 0;
    this.x = 0;
    this.y = 0;
    this.z = 0;
    this.node = null;
    this.activeIndex = 0;
    this.className = "VideoProgress";
    this.visible = true;
    this.items = null;
    this.canvas = null;
    this.backgroundBox = null;
    this.filledBox = null;
    this.emptyBox = null;
    this.titleLabel = null;
    this.progressLabel = null;
    this.durationLabel = null;
    this.cursor = null;
    
    this.initialize = function (position, target, url, options) {
        this.height = position.height;
        this.width = position.width;
        this.x = position.x;
        this.y = position.y;
        this.z = position.z;
        if (options.hasOwnProperty("canvas")) {
            this.canvas = options.canvas;
        }

        this.render(options);
    };
    
    this.render = function (options) {
        var titleWidth, timeWidth, progressBarWidth, viewed, duration, percentage;
        viewed = 0;
        duration = 1;
        percentage = 0;
        titleWidth = 45;
        timeWidth = 45;
        progressBarWidth = this.width - titleWidth - 2 * timeWidth;
        if (options.hasOwnProperty("viewed")) {
            
            viewed = parseFloat(options.viewed);
        }
        if (options.hasOwnProperty("duration")) {
            
            duration = parseFloat(options.duration);
        }
        
        percentage = (viewed <= duration) ? viewed / duration : 1;

        this.backgroundBox = $htv.Platform.createBox({
                x: this.x,
                y: this.y,
                z: this.z,
                width: this.width,
                height: this.height
            }, "VideoProgressBackground", this.canvas);
        this.emptyBox = $htv.Platform.createBox({
                x: this.x + titleWidth + timeWidth,
                y: this.y + (this.height - 10) / 2,
                z: this.z + 1,
                width: progressBarWidth,
                height: 10
            }, "VideoProgressEmpty", this.canvas);
        this.filledBox = $htv.Platform.createBox({
                x: this.x + titleWidth + timeWidth,
                y: this.y + (this.height - 10) / 2,
                z: this.z + 2,
                width: progressBarWidth * percentage,
                height: 10
            }, "VideoProgressFilled", this.canvas);
        this.titleLabel = $htv.Platform.createLabel({
                x: this.x + 3,
                y: this.y + (this.height - 13) / 2,
                z: this.z + 3,
                width: titleWidth,
                height: this.height
            }, "Viewed:", this.canvas, {styleName: $htv.Styles.VideoProgressTitle});
        this.progressLabel = $htv.Platform.createLabel({
                x: this.x + titleWidth - 3,
                y: this.y + (this.height - 13) / 2,
                z: this.z + 3,
                width: timeWidth,
                height: this.height
            }, $htv.Utils.formatSecondsAsTimeCode(viewed, false), this.canvas, {styleName: $htv.Styles.VideoProgressViewed});
        this.durationLabel = $htv.Platform.createLabel({
                x: this.x + this.width - timeWidth + 3,
                y: this.y + (this.height - 13) / 2,
                z: this.z + 3,
                width: timeWidth,
                height: this.height
            }, $htv.Utils.formatSecondsAsTimeCode(duration, false), this.canvas, {styleName: $htv.Styles.VideoProgressDuration});
        this.cursor = $htv.Platform.createImage({
                x: this.x + titleWidth + timeWidth + (progressBarWidth * percentage),
                y: this.y + (this.height - 13) / 2,
                z: this.z + 4,
                width: 2,
                height: 13
            }, "images/video_progress_cursor.png", this.canvas);
    };
    
    this.dispose = function () {
        $htv.Platform.deleteItem(this.backgroundBox);
        $htv.Platform.deleteItem(this.filledBox);
        $htv.Platform.deleteItem(this.emptyBox);
        $htv.Platform.deleteItem(this.titleLabel);
        $htv.Platform.deleteItem(this.progressLabel);
        $htv.Platform.deleteItem(this.durationLabel);
        $htv.Platform.deleteItem(this.cursor);
        this.backgroundBox = null;
        this.filledBox = null;
        this.emptyBox = null;
        this.titleLabel = null;
        this.progressLabel = null;
        this.durationLabel = null;
        this.cursor = null;
    
    };
    
    this.focus = function () {
    };
    
    this.unfocus = function () {
    };
    
    this.hide = function () {
        this.backgroundBox.hide();
        this.filledBox.hide();
        this.emptyBox.hide();
        this.titleLabel.hide();
        this.progressLabel.hide();
        this.durationLabel.hide();
        this.cursor.hide();
    };
    
    this.show = function () {
        this.backgroundBox.show();
        this.filledBox.show();
        this.emptyBox.show();
        this.titleLabel.show();
        this.progressLabel.show();
        this.durationLabel.show();
        this.cursor.show();
    };
    
    this.handleEvent = function (eventName, eventData) {
        if (eventName === "USER_INPUT") {
            this.handleInput(eventData);
        } else {
            
        }
    };
    
    this.handleInput = function (eventData) {
        if (!eventData.is_down || eventData.is_hold) {
            return;
        }
        
    };
};

$htv.Controls.SeriesDetails = function () {
    this.height = 0;
    this.width = 0;
    this.x = 0;
    this.y = 0;
    this.z = 0;
    this.node = null;
    this.activeIndex = 0;
    this.className = "SeriesDetails";
    this.canvas = null;
    this.seriesData = null;
    this.errorLabel = null;
    
    this.initialize = function (position, target, url, options) {
        this.height = position.height;
        this.width = position.width;
        this.x = position.x;
        this.y = position.y;
        this.z = position.z;
        this.seriesData = null;
        
        /* TODO: make metadata request
        if (options.show_id) {
            
            $htv.Utils.makeMetadataRequest(options.content_id, this, this.initializeResult);
        }
        */
        
        this.errorLabel = $htv.Platform.createLabel({
            x: this.x,
            y: this.y + 85,
            z: this.z,
            width: this.width,
            height: 30
        }, "Press [OK] to view the series details", this.canvas, {styleName: $htv.Styles.VideoDetailsError});
    };
    
    this.initializeResult = function (metadata) {
        if (metadata.show_id === undefined) {
            this.errorLabel = $htv.Platform.createLabel({
                x: this.x,
                y: this.y + 85,
                z: this.z,
                width: this.width,
                height: 30
            }, "Error loading series details. Please try again later.", this.canvas, {styleName: $htv.Styles.VideoDetailsError});
        }
        else {
            this.seriesData = metadata;
            this.render();
        }
    };
    
    this.getSeriesMetadata = function () {
        return this.seriesData;
    };
    
    this.render = function () {
    };
    
    this.dispose = function () {
        if (this.errorLabel !== null) {
            $htv.Platform.deleteItem(this.errorLabel);
            this.errorLabel = null;
        }
    };
    
    this.focus = function () {

    };
    
    this.unfocus = function () {
        
    };
    
    this.hide = function () {
        if (this.errorLabel !== null) {
            this.errorLabel.hide();
        }
    };
    
    this.show = function () {
        if (this.errorLabel !== null) {
            this.errorLabel.show();
        }
    };
    
    this.handleEvent = function (eventName, eventData) {
        if (eventName === "USER_INPUT") {
            this.handleInput(eventData);
        } else {
            
        }
    };
    
    this.handleInput = function (eventData) {
        if (!eventData.is_down || eventData.is_hold) {
            return;
        }
        
    };
};

$htv.Controls.VideoDetails = function () {
    this.height = 0;
    this.width = 0;
    this.x = 0;
    this.y = 0;
    this.z = 0;
    this.node = null;
    this.activeIndex = 0;
    this.className = "VideoDetails";
    this.visible = false;
    this.showTitleLabel = null;
    this.videoTitleLabel = null;
    this.typeDurationLabel = null;
    this.descriptionTitle = null;
    this.networkLabel = null;
    this.channelLabel = null;
    this.tuneInLabel = null;
    this.copyrightLabel = null;
    this.videoThumbnail = null;
    this.videoThumbnailBug = null;
    this.metaDataContainer = null;
    this.items = null;
    this.canvas = null;
    this.videoData = null;
    this.errorLabel = null;
    this.stars = null;
    this.ccIcon = null;
    this.typeDurationContainer = null;
    this.typeDurationPipe = null;
    this.spacers = [];
    
    this.initialize = function (position, target, url, options) {
        this.height = position.height;
        this.width = position.width;
        this.x = position.x;
        this.y = position.y;
        this.z = position.z;
        this.visible = true;
        this.videoData = null;
        this.ccIcon = null;
        if (options.content_id) {
            
            $htv.Utils.makeMetadataRequestWithContentID(options.content_id, this, this.initializeResult);
        }
    };
    
    this.initializeResult = function (metadata) {
        if (this.visible === true) { // ghost protection
            if (metadata.video_id === undefined) {
                this.errorLabel = $htv.Platform.createLabel({
                    x: this.x,
                    y: this.y + this.height / 2,
                    z: this.z,
                    width: this.width,
                    height: 30
                }, "Error loading video details. Please try again later.", this.canvas, {
                    styleName: $htv.Styles.VideoDetailsError
                });
            } else {
                this.videoData = metadata;
                this.render();
            }
        }
    };
    
    this.getVideoMetadata = function () {
        return this.videoData;
    };
    
    this.render = function () {
        var companyBugUrl, metadataX, metadataWidth, typeDurationText, thumbUrl;
        
        companyBugUrl = null;
        metadataX = this.x + 512 + 15;
        metadataWidth = this.width - metadataX + 30;
        typeDurationText = $htv.Utils.formatVideoSubtitle(this.videoData); 
        thumbUrl = $htv.Utils.getURLForVideoThumb(this.videoData.content_id, {
                width: 512,
                height: 288
            });
        this.videoThumbnail = $htv.Platform.createImage({
            x: this.x,
            y: this.y,
            z: this.z,
            width: 512,
            height: 288
        }, thumbUrl, this.canvas, {styleName: $htv.Styles.VideoDetailsThumbnail});
        
        if (this.videoData.company_name.toLowerCase().indexOf("abc") === 0) {
            companyBugUrl = "images/company-bug-abc.png";
        }
        else if (this.videoData.company_name.toLowerCase().indexOf("nbc") === 0) {
            companyBugUrl = "images/company-bug-nbc.png";
        }
        else if (this.videoData.company_name.toLowerCase().indexOf("fox") === 0) {
            companyBugUrl = "images/company-bug-fox.png";
        }
        this.videoThumbnailBug = $htv.Platform.createImage({
            x: this.x + 512 - 15 - 50,
            y: this.y + 288 - 12 - 50,
            z: this.z + 1,
            width: 50,
            height: 50
        // TEMPORARY: use real company bug
        }, companyBugUrl, this.canvas);
        if (companyBugUrl === null) {
            this.videoThumbnailBug.hide();
        }
        
        
        this.metaDataContainer = $htv.Platform.createContainer({
                x: metadataX,
                y: this.y - 10,
                z: this.z,
                width: metadataWidth,
                height: this.height
            }, this.canvas, {vertical: true, spacing: 0});
        
        this.showTitleLabel = $htv.Platform.createLabel({
                x: metadataX,
                y: 0,
                z: this.z,
                width: metadataWidth,
                height: this.height
            }, this.videoData.show_name, this.canvas, {styleName: $htv.Styles.VideoDetailsShow});
        
        this.videoTitleLabel = $htv.Platform.createLabel({
                x: metadataX,
                y: 0,
                z: this.z,
                width: metadataWidth,
                height: this.height
            }, this.videoData.title, this.canvas, {styleName: $htv.Styles.VideoDetailsTitle});
        
        this.typeDurationContainer = $htv.Platform.createContainer({
                x: metadataX,
                y: 30,
                z: this.z,
                width: metadataWidth,
                height: 22
            }, this.canvas, {vertical: false, spacing: 13, edgePadding: 0});
        this.typeDurationLabel = $htv.Platform.createLabel({
            x: 0,
            y: 0,
            z: this.z,
            width: metadataWidth,
            height: 22
        }, typeDurationText, this.canvas, {styleName: $htv.Styles.VideoDetailsTypeDuration});
        this.typeDurationPipe = $htv.Platform.createImage({
            x: 0, 
            y: 0, 
            z: this.z, 
            width: 1, 
            height: 14
        }, "images/small_pipe.png", this.canvas);
        this.stars = $htv.ControlPool.getObject("RatingStarsControl");
        this.stars.initialize({
                x: 0,
                y: 0,
                z: this.z,
                width: 92,
                height: 16
            }, null, null, { rating: this.videoData.rating });
        if (this.videoData.has_captions) {
            this.ccIcon = $htv.Platform.createImage({
                    x: 0,
                    y: 0,
                    z: this.z,
                    width: 20,
                    height: 14
                }, "images/cc-icon.png", this.canvas);
        }
        
        this.descriptionTextArea = $htv.Platform.createLabel({
                x: metadataX,
                y: 0,
                z: this.z,
                width: metadataWidth - 30,
                height: this.height
            }, this.videoData.description, this.canvas, {styleName: $htv.Styles.VideoDetailsDescription});
        
        this.networkLabel = $htv.Platform.createLabel({
                x: metadataX,
                y: 0,
                z: this.z,
                width: metadataWidth,
                height: 15
            }, "Network: " + this.videoData.company_name, this.canvas, {styleName: $htv.Styles.VideoDetailsNetworkChannel});
        
        this.channelLabel = $htv.Platform.createLabel({
                x: metadataX,
                y: 0,
                z: this.z,
                width: metadataWidth,
                height: 15
            }, "Channel: " + this.videoData.parent_channel_name, this.canvas, {styleName: $htv.Styles.VideoDetailsNetworkChannel});
        
        this.tuneInLabel = $htv.Platform.createLabel({
                x: metadataX,
                y: 0,
                z: this.z,
                width: metadataWidth,
                height: this.height
            }, this.videoData.tune_in_information, this.canvas, {styleName: $htv.Styles.VideoDetailsTuneIn});
        this.copyrightLabel = $htv.Platform.createLabel({
                x: metadataX,
                y: 0,
                z: this.z,
                width: metadataWidth,
                height: this.height
                // NOTE: passing the actual (c) unicode character barfs. replaced with html code in Plaform._convertLabelText
            }, $htv.Utils.stringIsNullOrEmpty(this.videoData.copyright) ? "" : "(c) " + this.videoData.copyright, this.canvas, {styleName: $htv.Styles.VideoDetailsCopyright});
            
        this.metaDataContainer.addItem(this.showTitleLabel);
        this.spacers.push($htv.Platform.createSpacer({width: metadataWidth, height: 2}, this.canvas, {}));
        this.metaDataContainer.addItem(this.spacers[this.spacers.length - 1]);
        this.metaDataContainer.addItem(this.videoTitleLabel);
        this.spacers.push($htv.Platform.createSpacer({width: metadataWidth, height: 2}, this.canvas, {}));
        this.metaDataContainer.addItem(this.spacers[this.spacers.length - 1]);
        this.typeDurationContainer.addItem(this.typeDurationLabel);
        this.typeDurationContainer.addItem(this.typeDurationPipe, {padding: {top: 3}, absolute_offset: {top: -1}});
        this.typeDurationContainer.addItem(this.stars.getContainer(), {padding: {top: 1}, absolute_offset: {top : -1}});
        if (this.ccIcon !== null) {
            this.typeDurationContainer.addItem(this.ccIcon, {padding: {top: 2}, absolute_offset: {top: -1}});
        }
        this.metaDataContainer.addItem(this.typeDurationContainer);
        this.spacers.push($htv.Platform.createSpacer({width: metadataWidth, height: 10}, this.canvas, {}));
        this.metaDataContainer.addItem(this.spacers[this.spacers.length - 1]);
        this.metaDataContainer.addItem(this.descriptionTextArea);
        this.spacers.push($htv.Platform.createSpacer({width: metadataWidth, height: 10}, this.canvas, {}));
        this.metaDataContainer.addItem(this.spacers[this.spacers.length - 1]);
        this.metaDataContainer.addItem(this.networkLabel);
        this.metaDataContainer.addItem(this.channelLabel);
        this.spacers.push($htv.Platform.createSpacer({width: metadataWidth, height: 10}, this.canvas, {}));
        this.metaDataContainer.addItem(this.spacers[this.spacers.length - 1]);
        this.metaDataContainer.addItem(this.tuneInLabel);
        this.metaDataContainer.addItem(this.copyrightLabel);
    };
    
    this.dispose = function () {
        if (this.videoData) {
            $htv.Platform.deleteItem(this.videoThumbnail);
            // TODO: concerned about the ordering here..  can we just remove the container?
            $htv.Platform.deleteItem(this.showTitleLabel);
            $htv.Platform.deleteItem(this.videoTitleLabel);
            $htv.Platform.deleteItem(this.typeDurationLabel);
            $htv.Platform.deleteItem(this.typeDurationPipe);
            $htv.Platform.deleteItem(this.descriptionTextArea);
            $htv.Platform.deleteItem(this.networkLabel);
            $htv.Platform.deleteItem(this.channelLabel);
            $htv.Platform.deleteItem(this.tuneInLabel);
            $htv.Platform.deleteItem(this.copyrightLabel);
            this.stars.dispose();
            if (this.ccIcon !== null) {
                $htv.Platform.deleteItem(this.ccIcon);
                this.ccIcon = null;
            }
            while (this.spacers.length > 0) {
                $htv.Platform.deleteItem(this.spacers.pop());
            }
            if (this.videoThumbnailBug !== null) {
                $htv.Platform.deleteItem(this.videoThumbnailBug);
                this.videoThumbnailBug = null;
            }
            
            $htv.Platform.deleteItem(this.typeDurationContainer);
            $htv.Platform.deleteItem(this.metaDataContainer);
        }
        if (this.errorLabel) {
            $htv.Platform.deleteItem(this.errorLabel);
            this.errorLabel = null;
        }
        this.visible = false;
    };
    
    this.focus = function () {

    };
    
    this.unfocus = function () {
        
    };
    
    this.hide = function () {
        this.visible = false;
        if (this.videoData) {
            this.showTitleLabel.hide();
            this.videoTitleLabel.hide();
            this.typeDurationPipe.hide();
            this.descriptionTextArea.hide();
            this.networkLabel.hide();
            this.channelLabel.hide();
            this.tuneInLabel.hide();
            this.copyrightLabel.hide();
            if (this.ccIcon !== null) {
                this.ccIcon.hide();
            }
            if (this.videoThumbnailBug !== null) {
                this.videoThumbnailBug.hide();
            }
            this.typeDurationContainer.hide();
            this.metaDataContainer.hide();
            this.videoThumbnail.hide();
        }
        if (this.errorLabel) {
            this.errorLabel.hide();
        }
        if (this.videoThumbnailBug !== null) {
            this.videoThumbnailBug.hide();
        }
    };
    
    this.show = function () {
        this.visible = true;
        if (this.videoData) {
            this.showTitleLabel.show();
            this.videoTitleLabel.show();
            this.typeDurationPipe.show();
            this.descriptionTextArea.show();
            this.networkLabel.show();
            this.channelLabel.show();
            this.tuneInLabel.show();
            this.copyrightLabel.show();
            if (this.ccIcon !== null) {
                this.ccIcon.show();
            }
            this.typeDurationContainer.show();
            this.metaDataContainer.show();
            this.videoThumbnail.show();
        }
        if (this.errorLabel) {
            this.errorLabel.show();
        }
        if (this.videoThumbnailBug !== null) {
            this.videoThumbnailBug.show();
        }
    };
    
    this.handleEvent = function (eventName, eventData) {
        if (eventName === "USER_INPUT") {
            this.handleInput(eventData);
        } else {
            
        }
    };
    
    this.handleInput = function (eventData) {
        if (!eventData.is_down || eventData.is_hold) {
            return;
        }
        
    };
};

$htv.Controls.ResumeDetails = function () {
    this.height = 0;
    this.width = 0;
    this.x = 0;
    this.y = 0;
    this.z = 0;
    this.node = null;
    this.activeIndex = 0;
    this.className = "ResumeDetails";
    this.visible = false;
    this.showTitleLabel = null;
    this.videoTitleLabel = null;
    this.typeDurationLabel = null;
    this.videoThumbnail = null;
    this.videoThumbnailBox = null;
    this.metaDataContainer = null;
    this.progressBarBox = null;
    this.progressBarEmptyBox = null;
    this.progressBarFilledBox = null;    
    this.canvas = null;
    this.content_id = 0;
    this.videoData = null;
    this.errorLabel = null;
    
    this.initialize = function (position, target, url, options) {
        this.height = position.height;
        this.width = position.width;
        this.x = position.x;
        this.y = position.y;
        this.z = position.z;
        this.visible = true;
        this.videoData = null;
        if (options.content_id) {
            
            this.content_id = options.content_id;
            $htv.Utils.makeMetadataRequestWithContentID(this.content_id, this, this.initializeResult);
        }
    };
    
    this.initializeResult = function (metadata) {
        if (this.visible === true) { // ghost protection
            if (metadata.video_id === undefined) {
                this.errorLabel = $htv.Platform.createLabel({
                    x: this.x,
                    y: this.y + this.height / 2,
                    z: this.z,
                    width: this.width,
                    height: 30
                }, "Error loading video details. Please try again later.", this.canvas, {
                    styleName: $htv.Styles.VideoDetailsError
                });
            } else {
                this.videoData = metadata;
                this.render();
            }
        }
    };
    
    this.render = function () {
        var metadataX, metadataWidth, typeDurationText, progressInfo, percentage;
        
        metadataX = this.x + 160;
        metadataWidth = this.width - 160;
        typeDurationText = $htv.Utils.formatVideoSubtitle(this.videoData);
        
        progressInfo = $htv.Profile.getPlaybackProgress(this.content_id);
        percentage = Math.max(0, Math.min(1, progressInfo.viewed / progressInfo.duration)); 
        
        this.videoThumbnailBox = $htv.Platform.createBox({
            x: this.x,
            y: this.y - 1,
            z: this.z,
            width: 147,
            height: 82
        }, "ResumeBackgroundBorder", this.canvas);
        
        this.videoThumbnail = $htv.Platform.createImage({
            x: this.x + 1,
            y: this.y,
            z: this.z + 1,
            width: 145,
            height: 80
        }, $htv.Utils.getURLForVideoThumb(this.content_id, { width: 145, height: 80 }), this.canvas, {});
                
        this.progressBarBox = $htv.Platform.createBox({
            x: this.x,
            y: this.y + 85,
            z: this.z,
            width: 147,
            height: 8
        }, "ResumeBackgroundBorder", this.canvas);
        
        this.progressBarEmptyBox = $htv.Platform.createBox({
            x: this.x + 1,
            y: this.y + 86,
            z: this.z + 1,
            width: 145,
            height: 6
        }, "ResumeProgressEmpty", this.canvas);        
        
        this.progressBarFilledBox = $htv.Platform.createBox({
            x: this.x + 1,
            y: this.y + 86,
            z: this.z + 2,
            width: 145 * percentage,
            height: 6
        }, "ResumeProgressFilled", this.canvas);

        this.metaDataContainer = $htv.Platform.createContainer({
            x: metadataX,
            y: this.y - 14,
            z: this.z + 1,
            width: metadataWidth,
            height: this.height
        }, this.canvas, {vertical: true, spacing: 2});
        
        this.showTitleLabel = $htv.Platform.createLabel({
            x: metadataX,
            y: 0,
            z: this.z + 1,
            width: metadataWidth,
            height: 20
        }, this.videoData.show_name, this.canvas, {styleName: $htv.Styles.ResumeDetailsShow});
        
        this.videoTitleLabel = $htv.Platform.createLabel({
            x: metadataX,
            y: 0,
            z: this.z + 1,
            width: metadataWidth,
            height: 80 // hack height for 2linemaxstyle
        }, this.videoData.title, this.canvas, {styleName: $htv.Styles.ResumeDetailsTitle});

        this.typeDurationLabel = $htv.Platform.createLabel({
            x: metadataX,
            y: 0,
            z: this.z + 1,
            width: metadataWidth,
            height: 22
        }, typeDurationText, this.canvas, {styleName: $htv.Styles.VideoDetailsTypeDuration});
            
        this.metaDataContainer.addItem(this.showTitleLabel);
        this.metaDataContainer.addItem(this.videoTitleLabel);
        this.metaDataContainer.addItem(this.typeDurationLabel);
    };
    
    this.dispose = function () {
        if (this.videoData) {
            $htv.Platform.deleteItem(this.videoThumbnail);
            $htv.Platform.deleteItem(this.videoThumbnailBox);
            $htv.Platform.deleteItem(this.progressBarBox);
            $htv.Platform.deleteItem(this.progressBarEmptyBox);
            $htv.Platform.deleteItem(this.progressBarFilledBox);
            // TODO: concerned about the ordering here..  can we just remove the container?
            $htv.Platform.deleteItem(this.showTitleLabel);
            $htv.Platform.deleteItem(this.videoTitleLabel);
            $htv.Platform.deleteItem(this.typeDurationLabel);

            $htv.Platform.deleteItem(this.metaDataContainer);
        }
        if (this.errorLabel) {
            $htv.Platform.deleteItem(this.errorLabel);
            this.errorLabel = null;
        }
        this.visible = false;
    };
    
    this.focus = function () {
        
    };
    
    this.unfocus = function () {
        
    };
    
    this.hide = function () {
        this.visible = false;
        if (this.videoData) {
            this.showTitleLabel.hide();
            this.videoTitleLabel.hide();
            this.typeDurationLabel.hide();
            this.metaDataContainer.hide();
            this.videoThumbnail.hide();
            this.videoThumbnailBox.hide();
            this.progressBarBox.hide();
            this.progressBarEmptyBox.hide();
            this.progressBarFilledBox.hide();
        }
        if (this.errorLabel) {
            this.errorLabel.hide();
        }
    };
    
    this.show = function () {
        this.visible = true;
        if (this.videoData) {
            this.showTitleLabel.show();
            this.videoTitleLabel.show();
            this.typeDurationLabel.show();
            this.metaDataContainer.show();
            this.videoThumbnail.show();
            this.videoThumbnailBox.show();
            this.progressBarBox.show();
            this.progressBarEmptyBox.show();
            this.progressBarFilledBox.show();
        }
        if (this.errorLabel) {
            this.errorLabel.show();
        }
    };
};

$htv.Controls.Masthead = function () {
    this.height = 0;
    this.width = 0;
    this.x = 0;
    this.y = 0;
    this.z = 0;
    this.node = null;
    this.className = "Masthead";
    this.hasFocus = false;
    this.visible = true;
    this.canvas = null;
    this.items = null;
    this.descriptionImage = null;
    this.descriptionScreen = null;
    this.descriptionTextArea = null;
    this.descriptionTitle = null;
    this.displayItems = null;
    this.reflectionItems = null;
    this.activeIndex = 0;
    this.boxes = [];
    this.leftArrow = null;
    this.rightArrow = null;
    this.leftBracket = null;
    this.rightBracket = null;
    this.idleTimer = null;
    this.IDLE_INTERVAL = 15000;
    this.IMAGE_WIDTH = 599;
    this.IMAGE_HEIGHT = 262;
    this.REFLECTION_HEIGHT = 50;
    this.TWDUR_MOVE = 500;
    
    this.initialize = function (position, target, url, options) {
        this.height = position.height;
        this.width = position.width;
        this.x = position.x;
        this.y = position.y;
        this.z = position.z;
        this.node = target;
        this.hasFocus = false;
        if (options.hasOwnProperty("canvas")) {
            this.canvas = options.canvas;
        }
        
        this.centerDisplayPosition = {
            x: this.x + this.width / 2 - this.IMAGE_WIDTH / 2,
            y: this.y,
            z: this.z,
            width: this.IMAGE_WIDTH,
            height: this.IMAGE_HEIGHT
        };
        this.leftDisplayPosition = {
            x: -this.width,
            y: this.y,
            z: this.z,
            width: this.IMAGE_WIDTH,
            height: this.IMAGE_HEIGHT
        };
        this.rightDisplayPosition = {
            x: this.width + 100,
            y: this.y,
            z: this.z,
            width: this.IMAGE_WIDTH,
            height: this.IMAGE_HEIGHT
        };
        
        this.centerReflectionDisplayPosition = {
            x: this.x + this.width / 2 - this.IMAGE_WIDTH / 2,
            y: this.y + this.IMAGE_HEIGHT + 8,
            z: this.z,
            width: this.IMAGE_WIDTH,
            height: this.REFLECTION_HEIGHT
        };
        this.leftReflectionDisplayPosition = {
            x: -this.width,
            y: this.y + this.IMAGE_HEIGHT + 8,
            z: this.z,
            width: this.IMAGE_WIDTH,
            height: this.REFLECTION_HEIGHT
        };
        this.rightReflectionDisplayPosition = {
            x: this.width + 100,
            y: this.y + this.IMAGE_HEIGHT + 8,
            z: this.z,
            width: this.IMAGE_WIDTH,
            height: this.REFLECTION_HEIGHT
        };
        
        this.leftArrow = $htv.Platform.createImage({
            x: this.x + 48,
            y: this.y + 106,
            z: this.z,
            width: 18,
            height: 54
        }, 
        "images/left_arrow_lg.png", this.canvas);
        
        this.rightArrow = $htv.Platform.createImage({
            x: this.x + 895,
            y: this.y + 106,
            z: this.z,
            width: 18,
            height: 54
        }, 
        "images/right_arrow_lg.png", this.canvas);

        this.leftBracket = $htv.Platform.createImage({
            x: this.x + 149,
            y: this.y + 62,
            z: this.z,
            width: 16,
            height: 134
        }, 
        "images/masthead_bracket_left.png", this.canvas);
        
        this.rightBracket = $htv.Platform.createImage({
            x: this.x + 795,
            y: this.y + 62,
            z: this.z,
            width: 16,
            height: 134
        }, 
        "images/masthead_bracket_right.png", this.canvas);
        
        // Create the first image for loading ui
        this.displayItems = [];
        this.displayItems[0] = $htv.Platform.createImage(this.centerDisplayPosition, "images/masthead-loading.png", this.canvas, {});
        
        $htv.Platform.loadURL($htv.Constants.Endpoints.masthead, this, this.onResultsComplete, {
            xmlparse: true
        });
    };
    
    this.onResultsComplete = function (requestData, options) {
        // TODO: support show results, get Xinan to add to format=xml response
        var i, imageUrl, reflectionUrl, item, all, contentId, showId, filtered, mastheadItem;
        filtered = [];
        all = $htv.Platform.evaluateXPath(requestData, "features/feature");
        for (i = 0; i < all.length && filtered.length < 7; i++) {
            item = $htv.Platform.getXPathResultAt(all, i);
            contentId = $htv.Platform.evaluateXPathInt(item, "contentId");
            showId = $htv.Platform.evaluateXPathInt(item, "showId");
            if (contentId > 0 || showId > 0) {
                imageUrl = $htv.Platform.evaluateXPathString(item, "imageUrl");
                if (imageUrl.match("swf$") === "swf") { 
                    continue; // filter swf masthead items
                }
                imageUrl = $htv.Utils.getURLForAsset(imageUrl, {
                    format: "png",
                    width: this.IMAGE_WIDTH,
                    height: this.IMAGE_HEIGHT
                });
                reflectionUrl = $htv.Utils.getURLForAsset(imageUrl, {
                    reflection_height: this.REFLECTION_HEIGHT,
                    reflection_alpha_top: 0.3
                });
                
                if (contentId > 0) { 
                    mastheadItem = {
                        content_id: contentId,
                        description: $htv.Platform.evaluateXPathString(item, "description"),
                        image_url: imageUrl,
                        logo_url: $htv.Platform.evaluateXPathString(item, "logoUrl"),
                        reflection_url: reflectionUrl,
                        show_id: showId,
                        show_name: $htv.Platform.evaluateXPathString(item, "showName"),
                        title: $htv.Platform.evaluateXPathString(item, "title"),
                        video_title: $htv.Platform.evaluateXPathString(item, "videoTitle")
                    };
                }
                else {
                    mastheadItem = {
                        description: $htv.Platform.evaluateXPathString(item, "description"),
                        image_url: imageUrl,
                        logo_url: $htv.Platform.evaluateXPathString(item, "logoUrl"),
                        reflection_url: reflectionUrl,
                        series_identifier: $htv.Platform.evaluateXPathString(item, "seriesIdentifier"),
                        show_id: showId,
                        show_name: $htv.Platform.evaluateXPathString(item, "showName"),
                        title: $htv.Platform.evaluateXPathString(item, "title")
                    };
                }
                
                filtered.push(mastheadItem);
            }
        }
        this.items = $htv.Utils.createGenericCollection(filtered);

        this.render();
    };
    
    this.render = function () {
        var index, i, item, boxWidth, boxSpace, boxesWidth, boxesX;
        
        boxWidth = 14;
        boxSpace = 3;
        boxesWidth = boxWidth * this.items.getLength() + boxSpace * (this.items.getLength() - 1); 
        boxesX = this.x + this.width / 2 - boxesWidth / 2;
        
        // Create boxes under key art
        for (i = 0; i < this.items.getLength(); i++) {
            this.boxes[i] = $htv.Platform.createImage(
                {
                    x: boxesX + i * (boxWidth + boxSpace),
                    y: this.y + 278,
                    z: this.z + 1,
                    width: boxWidth,
                    height: 8
                }, 
                (i === 0 ? "images/masthead_box_sel_focused.png" : "images/masthead_box_unsel_focused.png"), 
                this.canvas);
        }
        
        this.descriptionScreen = $htv.Platform.createImage({
            x: this.centerDisplayPosition.x + this.centerDisplayPosition.width - 174,
            y: this.centerDisplayPosition.y,
            z: this.z + 1,
            width: 176,
            height: 263
        }, "images/masthead_screen.png", this.canvas);
        
        this.descriptionImage = $htv.Platform.createImage({
            x: 0,
            y: -1080,
            z: this.z + 2,
            width: 145,
            height: 40
        }, "", this.canvas, {autoHeight: true});
        
        this.descriptionTitle = $htv.Platform.createTextArea({
            x: -1920,
            y: -1080,
            z: this.z + 2,
            width: 145,
            height: 40 
        }, "", this.canvas, {styleName: $htv.Styles.MastheadTitle});
        
        this.descriptionTextArea = $htv.Platform.createTextArea({
            x: -1920,
            y: -1080,
            z: this.z + 2,
            width: 145,
            height: 120
        }, "", this.canvas, {styleName: $htv.Styles.MastheadDescription});

        this.descriptionContainer = $htv.Platform.createContainer({
            x: this.centerDisplayPosition.x + this.centerDisplayPosition.width - 175 + 15,
            y: this.centerDisplayPosition.y + 5,
            z: this.z + 2,
            width: 145,
            height: this.centerDisplayPosition.height - 30
        }, this.canvas, {vertical: true, center: true, spacing: 15});
        this.descriptionContainer.addItem(this.descriptionImage);
        this.descriptionContainer.addItem(this.descriptionTitle);
        this.descriptionContainer.addItem(this.descriptionTextArea);
        
        this.reflectionItems = new Array(this.items.getLength());
        for (i = 0; i < this.items.getLength(); i++) {
            item = this.items.getItemAt(i).item;
            
            // The 0th displayItem should already be created to show the loading asset
            if (i >= this.displayItems.length || !this.displayItems[i]) {
                this.displayItems[i] = $htv.Platform.createImage(this.rightDisplayPosition, "images/masthead-loading.png", this.canvas, {});
            }
            this.displayItems[i].setURL(item.image_url);
            
            if ($htv.Platform.properties.has_reflections === true) {
                this.reflectionItems[i] = $htv.Platform.createReflection(this.rightReflectionDisplayPosition, this.displayItems[i], this.canvas, {
                    source_height: this.IMAGE_HEIGHT,
                    alpha_top: 0.3
                });
            } else {
                this.reflectionItems[i] = $htv.Platform.createImage(this.rightReflectionDisplayPosition, item.reflection_url, this.canvas);
            }
        }
        this.jumpToIndex(0);
        this.node.view.fireEvent("INITIALIZE_COMPLETE", {
            target: this.node
        });
    };
 
    this.jumpToIndex = function (index) {
        var oldIndex, rightWrap, leftWrap, item;
        
        if (this.displayItems !== null && index >= this.displayItems.length) {
            return;
        }
        
        oldIndex = this.activeIndex;
        this.activeIndex = index;
        
        rightWrap = (oldIndex === this.items.getLength() - 1 && index === 0);
        leftWrap = (oldIndex === 0 && index === this.items.getLength() - 1);
        
        if ((oldIndex < index || rightWrap) && !leftWrap) {
            this.displayItems[oldIndex].move(this.leftDisplayPosition, this.TWDUR_MOVE);
            this.reflectionItems[oldIndex].move(this.leftReflectionDisplayPosition, this.TWDUR_MOVE);
            if ($htv.Platform.properties.has_animations) {
                this.displayItems[this.activeIndex].move(this.rightDisplayPosition, 0);
                this.reflectionItems[this.activeIndex].move(this.rightReflectionDisplayPosition, 0);
            }
        }
        else {
            this.displayItems[oldIndex].move(this.rightDisplayPosition, this.TWDUR_MOVE);
            this.reflectionItems[oldIndex].move(this.rightReflectionDisplayPosition, this.TWDUR_MOVE);
            if ($htv.Platform.properties.has_animations) {
                this.displayItems[this.activeIndex].move(this.leftDisplayPosition, 0);
                this.reflectionItems[this.activeIndex].move(this.leftReflectionDisplayPosition, 0);
            }
        }
        this.displayItems[this.activeIndex].move(this.centerDisplayPosition, this.TWDUR_MOVE);
        this.reflectionItems[this.activeIndex].move(this.centerReflectionDisplayPosition, this.TWDUR_MOVE);
        
        item = this.items.getItemAt(index).item;
        
        if ($htv.Utils.stringIsNullOrEmpty(item.logo_url)) {
            if (this.descriptionContainer.containsItem(this.descriptionImage)) {
                this.descriptionContainer.removeItem(this.descriptionImage);
            }
            if (this.visible === true) {
                this.descriptionImage.hide();
            }
        }
        else {
            if (!this.descriptionContainer.containsItem(this.descriptionImage)) {
                this.descriptionContainer.addItemAtIndex(this.descriptionImage, 0);
            }
            this.descriptionImage.setURL("");
            this.descriptionImage.setURL(item.logo_url);
            if (this.visible === true) {
                this.descriptionImage.show();
            }
        }
        
        this.descriptionTitle.setText(item.title);
        this.descriptionTextArea.setText(item.description);
        this.updateBoxes();
        
        // Reset idle timer
        if (this.idleTimer !== null) {
            this.idleTimer.stop();
            this.idleTimer = null;
        }
        this.idleTimer = $htv.Platform.createTimer(this.IDLE_INTERVAL, this, this.idleTimerTick);
        this.idleTimer.start();
    };
    
    this.idleTimerTick = function () {
        if (this.items !== null) {
            this.jumpToIndex((this.activeIndex + 1) % this.items.getLength());
        }
    };
    
    this.dispose = function () {
        var i;
        $htv.Platform.deleteItem(this.descriptionImage);
        $htv.Platform.deleteItem(this.descriptionScreen);
        $htv.Platform.deleteItem(this.descriptionTitle);
        $htv.Platform.deleteItem(this.descriptionTextArea);
        $htv.Platform.deleteItem(this.descriptionContainer);
        this.activeIndex = 0;
        for (i = 0; i < this.displayItems.length; i++) {
            $htv.Platform.deleteItem(this.displayItems[i]);
        }
        this.displayItems = null;
        for (i = 0; i < this.reflectionItems.length; i++) {
            $htv.Platform.deleteItem(this.reflectionItems[i]);
        }
        this.reflectionItems = null;
        while (this.boxes.length > 0) {
            $htv.Platform.deleteItem(this.boxes.pop());
        }
        $htv.Platform.deleteItem(this.leftArrow);
        $htv.Platform.deleteItem(this.rightArrow);
        $htv.Platform.deleteItem(this.leftBracket);
        $htv.Platform.deleteItem(this.rightBracket);
        
        // Stop idle timer
        if (this.idleTimer !== null) {
            this.idleTimer.stop();
            this.idleTimer = null;
        }
    };
    
    this.updateBoxes = function () {
        for (var i = 0; i < this.boxes.length; i++) {
            if (this.hasFocus) {
                this.boxes[i].setURL(i === this.activeIndex ? 
                    "images/masthead_box_sel_focused.png" : "images/masthead_box_unsel_focused.png");
            }
            else {
                this.boxes[i].setURL(i === this.activeIndex ? 
                    "images/masthead_box_sel_unfocused.png" : "images/masthead_box_unsel_unfocused.png");            
            }
        }
    };
    
    this.focus = function () {
        this.hasFocus = true;
        this.leftArrow.show(250);
        this.rightArrow.show(250);
        this.leftBracket.show(250);
        this.rightBracket.show(250);
        this.updateBoxes();
        $htv.Platform.updateSpotlight(this.x + this.width / 2, this.y + this.height / 2 - 80, 3);
    };
    
    this.unfocus = function () {
        this.hasFocus = false;
        this.leftArrow.hide(250);
        this.rightArrow.hide(250);
        this.leftBracket.hide(250);
        this.rightBracket.hide(250);
        this.updateBoxes();
    };
    
    this.hide = function () {
        var i;
        this.visible = false;
        for (i = 0; i < this.displayItems.length; i++) {
            if (this.displayItems[i] !== null) {
                this.displayItems[i].hide();
            }
        }
        for (i = 0; i < this.reflectionItems.length; i++) {
            if (this.reflectionItems[i] !== null) {
                this.reflectionItems[i].hide();
            }
        }
        this.descriptionImage.hide();
        this.descriptionScreen.hide();
        this.descriptionTitle.hide();
        this.descriptionTextArea.hide();
        this.leftArrow.hide();
        this.rightArrow.hide();
        this.leftBracket.hide();
        this.rightBracket.hide();
        for (i = 0; i < this.boxes.length; i++) {
            this.boxes[i].hide();
        }
        
        // Stop idle timer
        if (this.idleTimer !== null) {
            this.idleTimer.stop();
            this.idleTimer = null;
        }
    };
    
    this.show = function () {
        var i, item;
        this.visible = true;
        for (i = 0; i < this.displayItems.length; i++) {
            if (this.displayItems[i] !== null) {
                this.displayItems[i].show();
            }
        }
        for (i = 0; i < this.reflectionItems.length; i++) {
            if (this.reflectionItems[i] !== null) {
                this.reflectionItems[i].show();
            }
        }
        
        if (this.items !== null) {
            item = this.items.getItemAt(this.activeIndex).item;
            if (!$htv.Utils.stringIsNullOrEmpty(item.logo_url)) {
                this.descriptionImage.show();
            }
        }
        this.descriptionScreen.show();
        this.descriptionTitle.show();
        this.descriptionTextArea.show();
        for (i = 0; i < this.boxes.length; i++) {
            this.boxes[i].show();
        }

        // Stop/start idle timer
        if (this.idleTimer !== null) {
            this.idleTimer.stop();
            this.idleTimer = null;
        }
        this.idleTimer = $htv.Platform.createTimer(this.IDLE_INTERVAL, this, this.idleTimerTick);
        this.idleTimer.start();
    };
    
    this.handleEvent = function (eventName, eventData) {
        if (eventName === "USER_INPUT") {
            this.handleInput(eventData);
        } else {
            
        }
    };
    
    this.handleInput = function (eventData) {
        var item;
        switch (eventData.action) {
        // NOTE: PLAY and PLAY_PAUSE will be intercepted by Controller._handleInput
        // if player is active. So will only get here if video is not playing.
        case "PLAY":
        case "PLAY_PAUSE":
            if (this.items !== null) {
                item = this.items.getItemAt(this.activeIndex).item;
                if (item === null) {
                }
                else if (item.content_id > 0) {
                    $htv.Controller.playVideo(item.content_id, {});
                }
            }
            break;
        case "PRESS_OK":
            if (this.items !== null) {
                item = this.items.getItemAt(this.activeIndex).item;
                if (item === null) {
                }
                else if (item.content_id > 0) {
                    $htv.Controller.playVideo(item.content_id, {});
                }
                else if (item.show_id > 0) {
                    $htv.Controller.pushView("ContentView", {
                        menu_url: "/menu/" + $htv.Constants.MENU_PREFIX + "show_page?show_id=" + item.show_id,
                        view_title: $htv.Utils.stringIsNullOrEmpty(item.show_name) ? "Series Details" : item.show_name,
                        show_id: item.show_id,
                        show_name: item.show_name,
                        show_canonical_name: item.series_identifier,
                        previous_view_title: "Home"
                    });
                }
            }
            break;
        case "MOVE_RIGHT":
            if (eventData.is_down === true) {
                this.rightArrow.setURL("images/right-arrow-lg-hover.png");
                if (this.items !== null) {
                    this.jumpToIndex((this.activeIndex + 1) % this.items.getLength());
                }
            }
            else {
                this.rightArrow.setURL("images/right_arrow_lg.png");
            }
            break;
        case "MOVE_LEFT":
            if (eventData.is_down === true) {
                this.leftArrow.setURL("images/left-arrow-lg-hover.png");
                if (this.items !== null) {
                    this.jumpToIndex(this.activeIndex <= 0 ? this.items.getLength() - 1 : this.activeIndex - 1);
                }
            }
            else {
                this.leftArrow.setURL("images/left_arrow_lg.png");
            }
            break;
        case "MOVE_DOWN":
            if (eventData.is_down === true) {
                this.node.view.fireEvent("LOSING_FOCUS", {
                    nav_dir: "down"
                });
            }
            break;
        case "KEY_RETURN":
            if (eventData.is_down === true) {
                this.node.view.fireEvent("RETURN_KEY_PRESSED", {target: this.node});
            }
            break;
        case "KEY_EXIT":
            if (eventData.is_down === true) {
                this.node.view.fireEvent("EXIT_KEY_PRESSED", {target: this.node});
            }
            break;
        case "MOVE_UP":
            if (eventData.is_down === true) {
                this.node.view.fireEvent("LOSING_FOCUS", {
                    nav_dir: "up"
                });
            }
            break;
        default:
            
            break;
        }
    };
};

$htv.Controls.SingletonBreadCrumb = function () {
    this.height = 0;
    this.width = 0;
    this.x = 0;
    this.y = 0;
    this.z = 0;
    this.node = null;
    this.className = "SingletonBreadCrumb";
    this.viewNames = null;
    this.visible = true;
    this.titleLabel = null;
    this.backLabel = null;
    this.canvas = null;
    this.initialized = false;
    
    this.initialize = function (position, target, url, options) {
        var titleLabelPosition, backLabelPosition;

        this.height = position.height;
        this.width = position.width;
        this.x = position.x;
        this.y = position.y;
        this.z = position.z;
        this.node = target;
        
        titleLabelPosition = {
            x: this.x + 40,
            y: this.y + 29,
            z: this.z,
            width: this.width,
            height: 24
        };
        backLabelPosition = {
            x: this.x + 10,
            y: this.y + 10,
            z: this.z,
            width: this.width,
            height: 24
        };
        
        if (this.initialized === false) { //  there can only be one
            this.viewNames = [];
            if (options.hasOwnProperty("canvas")) {
                this.canvas = options.canvas;
            }
            this.backLabel = $htv.Platform.createLabel(backLabelPosition, "", this.canvas, {styleName: $htv.Styles.BreadCrumbBackLabel});
            this.titleLabel = $htv.Platform.createLabel(titleLabelPosition, this.viewNames[this.viewNames.length - 1] + "", this.canvas, {styleName: $htv.Styles.BreadCrumbFrontLabel});
            $htv.Controller.addEventListener("VIEW_PUSHED", this);
            $htv.Controller.addEventListener("VIEW_POPPED", this);
            $htv.Controller.addEventListener("CONTENTVIEW_CAROUSEL2_FOCUSED", this);
            $htv.Controller.addEventListener("CONTENTVIEW_NONCAROUSEL2_FOCUSED", this);
            this.initialized = true;
        }
        // allow repositioning on each view that uses it
        this.titleLabel.move(titleLabelPosition);
        this.backLabel.move(backLabelPosition);
        if (this.viewNames[this.viewNames.length - 1]) {
            this.titleLabel.setText(this.viewNames[this.viewNames.length - 1] + "");
        } else {
            this.titleLabel.setText("");
        }
    };
    
    this.dispose = function () { // probably shouldn't ever be called
        $htv.Platform.deleteItem(this.backLabel);
        $htv.Platform.deleteItem(this.titleLabel);
        this.backLabel = null;
        this.titleLabel = null;
        this.viewNames = null;
        this.initialized = false;
        
    };
    
    this.focus = function () {
    
    };
    
    this.unfocus = function () {
    
    };
    
    this.hide = function () {
        this.visible = false;
        this.titleLabel.hide();
        this.backLabel.hide();
    };
    
    this.show = function () {
        this.visible = true;
        this.titleLabel.show();
        this.backLabel.show();
    };
    
    this.handleInput = function (eventData) {
        
    };
    
    this.handleEvent = function (event, eventData) {
        var previous_title, orig_title;
        
        switch (event) {
        case "VIEW_PUSHED":
            
            
            previous_title = "Home";
            if (eventData.previous_view_title) {
                previous_title = eventData.previous_view_title;
            }
            this.backLabel.setText(previous_title);
            this.titleLabel.setText(eventData.view_title);
            orig_title = this.viewNames.pop();
            if (typeof orig_title === "object") {
                orig_title = orig_title.orig_title;
            }
            this.viewNames.push({
                orig_title: orig_title,
                pushed_title: previous_title
            });
            this.viewNames.push(eventData.view_title);
            break;
        case "VIEW_POPPED":
            
            this.viewNames.pop();
            if (this.viewNames.length > 1) {
                this.backLabel.setText(this.viewNames[this.viewNames.length - 2].pushed_title);
                this.titleLabel.setText(this.viewNames[this.viewNames.length - 1].orig_title);
            }
            break;
        case "CONTENTVIEW_CAROUSEL2_FOCUSED":
            this.backLabel.hide();
            break;
        case "CONTENTVIEW_NONCAROUSEL2_FOCUSED":
            if (this.visible === true) {
                this.backLabel.show();
            }
            break;
        default:
            
            break;
        }
    };
};

$htv.Controls.singletons.Breadcrumb = new $htv.Controls.SingletonBreadCrumb();
$htv.Controls.BreadCrumb = function () {
    this.height = 0;
    this.width = 0;
    this.x = 0;
    this.y = 0;
    this.z = 0;
    this.node = null;
    this.className = "Breadcrumb";
    this.initialize = function (position, target, url, options) {
        $htv.Controls.singletons.Breadcrumb.initialize(position, target, url, options);
    };
    
    this.dispose = function () {
        $htv.Controls.singletons.Breadcrumb.hide();
    };
    
    this.focus = function () {
    
    };
    
    this.unfocus = function () {
    
    };
    
    this.hide = function () {
        $htv.Controls.singletons.Breadcrumb.hide();
    };
    
    this.show = function () {
        $htv.Controls.singletons.Breadcrumb.show();
    };
    
    this.handleInput = function (eventData) {
        $htv.Controls.singletons.Breadcrumb.handleInput(eventData);
    };
    
    this.handleEvent = function (event, eventData) {
        $htv.Controls.singletons.Breadcrumb.handleEvent(event, eventData);
    };
};

$htv.Controls.TopBar = function () {
    this.height = 0;
    this.width = 0;
    this.x = 0;
    this.y = 0;
    this.z = 0;
    this.node = null;
    this.className = "TopBar";
    this.visible = true;
    this.topBarBackgroundImage = null;
    this.topBarPlayerOverlayImage = null;
    this.minimizedHintImage = null;
    this.minimizedHintText = null;
    this.canvas = null;
    
    this.initialize = function (position, target, url, options) {
        var topBarBackgroundPosition, topBarPlayerOverlayPosition;
        
        this.height = position.height;
        this.width = position.width;
        this.x = position.x;
        this.y = position.y;
        this.z = position.z;
        this.node = target;
        if (options.hasOwnProperty("canvas")) {
            this.canvas = options.canvas;
        }
        topBarBackgroundPosition = {
            x: this.x,
            y: this.y,
            z: this.z,
            width: 960,
            height: 101
        };
        
        topBarPlayerOverlayPosition = {
            x: this.x + this.width - 200,
            y: this.y,
            z: this.z,
            width: 200,
            height: 101
        };
        
        this.topBarBackgroundImage = $htv.Platform.createImage(topBarBackgroundPosition, "images/top_bar_background.png", this.canvas);
        this.topBarPlayerOverlayImage = $htv.Platform.createImage(topBarPlayerOverlayPosition, "images/top_bar_player_overlay.png", this.canvas);
        this.minimizedHintImage = $htv.Platform.createImage({
            x: this.x + this.width - 105,
            y: this.height + 2,
            z: this.z + 3,
            width: 17,
            height: 17
        }, "images/minimized-player-hint.png", this.canvas);
        this.minimizedHintText =  $htv.Platform.createLabel({
            x: this.x + this.width - 83,
            y: this.height + 3,
            z: this.z + 3,
            width: 100,
            height: 12
        }, "back to video", this.canvas, {styleName: $htv.Styles.VideoDetailsCopyright});
    };
    
    this.dispose = function () {
        $htv.Platform.deleteItem(this.topBarBackgroundImage);
        $htv.Platform.deleteItem(this.topBarPlayerOverlayImage);
        $htv.Platform.deleteItem(this.minimizedHintImage);
        $htv.Platform.deleteItem(this.minimizedHintText);
        this.topBarBackgroundImage = null;
        this.topBarPlayerOverlayImage = null;
        this.minimizedHintImage = null;
        this.minimizedHintText = null;
    };
    
    this.focus = function () {
    
    };
    
    this.unfocus = function () {
    
    };
    
    this.hide = function () {
        this.topBarPlayerOverlayImage.hide();
        this.topBarBackgroundImage.hide();
        this.minimizedHintImage.hide();
        this.minimizedHintText.hide();
    };
    
    this.show = function () {
        this.topBarBackgroundImage.show();
        if ($htv.Player.isActive()) {
            this.topBarPlayerOverlayImage.hide();
            this.minimizedHintImage.show();
            this.minimizedHintText.show();
        }
        else {
            this.topBarPlayerOverlayImage.show();
            this.minimizedHintImage.hide();
            this.minimizedHintText.hide();
        }
    };
    
    this.handleEvent = function (eventName, eventData) {
        if (eventName === "USER_INPUT") {
            this.handleInput(eventData);
        } else {
            
        }
    };
    
    this.handleInput = function (eventData) {
        if (!eventData.is_down || eventData.is_hold) {
            return;
        }
        
    };
};

$htv.Controls.NonSlidingMenu = function () {
    this.height = 0;
    this.width = 0;
    this.x = 0;
    this.y = 0;
    this.z = 0;
    this.node = null;
    this.activeIndex = 0;
    this.className = "NonSlidingMenu";
    this.visible = false;
    this.menuItemPositions = null;
    this.menuItems = null;
    this.menuItemsContainer = null;
    this.menu_title = null;
    this.canvas = null;
    this.items = null;
    this.leftBracket = null;
    this.rightBracket = null;
    this.leftVisibleIndex = 0;
    this.rightVisibleIndex = 0;
    this.spacerWidth = 20;
    this.itemPadding = 10; // combined = 40 px
    this.rightArrow = null;
    this.leftArrow = null;
    this.maxItemsVisible = -1;
    this.numItemsVisible = 0;
    
    this._initialize = function (position, target, url, options) {
        this.height = position.height;
        this.width = position.width;
        this.x = position.x;
        this.y = position.y;
        this.z = position.z;
        this.node = target;
        this.items = null;
        this.menuItems = null;
        this.visible = true;
        this.activeIndex = 0;
        this.maxItemsVisible = -1;
        this.numItemsVisible = 0;

        if (options && options.hasOwnProperty("max_items_visible")) {
            this.maxItemsVisible = options.max_items_visible;
        }
        
        if (options && options.hasOwnProperty("canvas")) {
            this.canvas = options.canvas;
        }
        
        // Position gets updated in layoutBrackets()
        this.leftBracket = $htv.Platform.createImage({
            x: -100,
            y: -100,
            z: this.z,
            width: 6,
            height: 27
        }, "images/bracket_small_left.png", this.canvas);
        this.leftBracket.hide();
        this.rightBracket = $htv.Platform.createImage({
            x: -100,
            y: -100,
            z: this.z,
            width: 6,
            height: 27
        }, "images/bracket_small_right.png", this.canvas);
        this.rightBracket.hide();
        this.rightArrow = $htv.Platform.createImage({
            x: this.x + this.width - 8,
            y: this.y + 22,
            z: this.z,
            width: 8,
            height: 21
        }, "images/arrow-right.png", this.canvas);
        this.rightArrow.hide();
        this.leftArrow = $htv.Platform.createImage({
            x: this.x,
            y: this.y + 22,
            z: this.z,
            width: 8,
            height: 21
        }, "images/arrow-left.png", this.canvas);
        this.leftArrow.hide();
            
        if (options.hasOwnProperty("view_title")) {
            this.menu_title = options.view_title;
        } else {
            this.menu_title = "";
        }
        
        // data source
        if (options.items) {
            this.items = options.items;
        }
        else {
            this.items = $htv.Utils.createTwinkieCollection(
                ['add_cb', 'items_url', 'login_required', 'recommended_required', 'cmtype', 'title', 'start_at_end', 'carousel_item_type', 'carousel_name', 'include_show_title', 'bug_br_field', 'child_text', 'use_related_title', 'is_queue_carousel'],
                // TODO: fix NonSlidingMenu to allow async retrieval from PagedTwinkieCollection.getItemAt
                1000
            );
            
            // the data source requires a login token (recommendations, queue)
            if (options.hasOwnProperty("login_required") && (options.login_required === 1)) {
                this.login_required = true;
                if (url.indexOf("user_id=") === url.length - 8) {
                    url = url + $htv.Profile.getUserToken();
                }
            }
            url = $htv.Utils.applyGlobalContext(url);
        }
        // populate the collection
        this.items.initialize(url, this, this.initializeResult);
    };
    
    this._initializeResult = function () {
        if (this.visible === true && this.items.getItemAt(this.activeIndex).item) {
            this.node.view.fireEvent("MENU_SELECTION_CHANGED", {
                title: this.items.getItemAt(this.activeIndex).item.title,
                items_url: this.items.getItemAt(this.activeIndex).item.items_url,
                cmtype: this.items.getItemAt(this.activeIndex).item.cmtype,
                options: {
                    start_at_end: this.items.getItemAt(this.activeIndex).item.start_at_end === "true",
                    add_cb: this.items.getItemAt(this.activeIndex).item.add_cb,
                    login_required: this.items.getItemAt(this.activeIndex).item.login_required,
                    recommended_required: this.items.getItemAt(this.activeIndex).item.recommended_required,
                    carousel_name: this.getChildCarouselName(),
                    is_queue_carousel: this.items.getItemAt(this.activeIndex).item.is_queue_carousel,
                    include_show_title: this.items.getItemAt(this.activeIndex).item.include_show_title,
                    carousel_item_type: this.items.getItemAt(this.activeIndex).item.carousel_item_type,
                    use_related_title: this.items.getItemAt(this.activeIndex).item.use_related_title,
                    view_title: this.menu_title,
                    delayed_initialize: false,
                    metadata_item: this.items.getMetadataItem(),
                    bug_br_field: this.items.getItemAt(this.activeIndex).item.bug_br_field,
                    child_text: this.items.getItemAt(this.activeIndex).item.child_text
                },
                target: this.node
            });
            
            this.render();
            this.node.view.fireEvent("INITIALIZE_COMPLETE", {});
        }
    };
    
    // Allow initializeResult to be overriden (see AlphaMenu)
    this.initializeResult = this._initializeResult;
    this.initialize = this._initialize;
    
    this.setDataSource = function (data) {
        var i;
        if (this.menuItems) {
            for (i = 0; i < this.menuItems.length; i++) {
                this.menuItems[i].hide();
                $htv.Platform.deleteItem(this.menuItems[i]);
                this.menuItems[i] = null;
            }
        }
        
        this.items = data;
        this._initializeResult(); 
    };
    

    this.getChildCarouselName = function () {
        if (this.items.getItemAt(this.activeIndex).item.hasOwnProperty("carousel_name") &&
            !$htv.Utils.stringIsNullOrEmpty(this.items.getItemAt(this.activeIndex).item.carousel_name)) {
            return this.items.getItemAt(this.activeIndex).item.carousel_name;
        }
        return this.menu_title + " " + this.items.getItemAt(this.activeIndex).item.title;
    };
    
    
    this.hasTooManyItems = function () {
        if (this.maxItemsVisible > -1) {
            return (this.numItemsVisible > this.maxItemsVisible);
        }
        return this.menuItemsContainer.contentsOverflowed();
    };
    
    this.render = function () {
        var i, item, overflowed, lastNonOverflowIndex, approximateWidth;
        this.numItemsVisible = 0;
        if (this.visible === true) {
            overflowed = false;
            lastNonOverflowIndex = -1;
            approximateWidth = 0;
            this.leftVisibleIndex = 0;
            this.rightVisibleIndex = this.items.getLength() - 1;
            this.menuItemPositions = new Array(this.items.getLength());
            this.menuItems = new Array(this.items.getLength());
            this.menuSpacers = new Array(this.items.getLength() + 1);
            this.menuItemsContainer = $htv.Platform.createContainer({
                x: this.x + 9,
                y: this.y + 20,
                z: this.z,
                width: this.width - 18,
                height: this.height
            }, this.canvas, {
                spacing: 0
            });
            this.menuSpacers[0] = $htv.Platform.createSpacer({
                width: this.spacerWidth,
                height: 27
            }, this.canvas, {});
            this.menuItemsContainer.addItem(this.menuSpacers[0]);
            for (i = 0; i < this.items.getLength(); i++) {
                item = this.items.getItemAt(i).item;
                if (item === null) {
                    continue;
                }
                
                this.menuItems[i] = $htv.Platform.createLabel({
                        x: 960,
                        y: this.y + 20,
                        z: this.z,
                        width: this.width,
                        height: 30
                    }, item.title, this.canvas, { styleName: $htv.Styles.NonSlidingMenuItemUnfocused});
                if (i === 0) {
                    this.menuItems[i].setStyle($htv.Styles.NonSlidingMenuItemSelectedUnfocused);
                }
                this.menuSpacers[i + 1] = $htv.Platform.createSpacer({width: this.spacerWidth, height: 27}, this.canvas, {});
                
                // If not already overflowed, add the item
                if (overflowed === false) {
                    this.menuItemsContainer.addItem(this.menuItems[i], {
                        padding: {
                            top: 2,
                            left: this.itemPadding,
                            right: this.itemPadding
                        }
                    });
                    this.menuItemsContainer.addItem(this.menuSpacers[i + 1]);
                    this.numItemsVisible++;
                    
                    // Add 9px per char and the spacer
                    approximateWidth += 9 * this.items.getItemAt(i).item.title.length + this.spacerWidth + 2 * this.itemPadding;
                    
                    // If approximation is over the container width, check for real
                    if (approximateWidth > this.menuItemsContainer.getPosition().width) {
                        // Don't waste an overflow result -- start by checking before this item
                        if (this.hasTooManyItems()) {
                            
                            overflowed = true;
                            this.menuItemsContainer.removeItem(this.menuItems[i]);
                            this.menuItemsContainer.removeItem(this.menuSpacers[i + 1]);
                            this.rightVisibleIndex = i - 1;
                            this.menuItems[i].hide();
                            this.numItemsVisible--;
                        }
                        // Don't waste a no overflow result -- avoid checking this item or anything before it
                        else {
                            lastNonOverflowIndex = i;
                        }
                    }
                }
                // If already overflowed, don't add and hide the item
                else {
                    this.menuItems[i].hide();
                }
            }
            // After exiting render, check for overflow up to the lastNonOverlowIndex
            for (i = this.rightVisibleIndex; i > lastNonOverflowIndex; i--) {
                if (this.hasTooManyItems()) {
                    
                    this.menuItemsContainer.removeItem(this.menuItems[i]);
                    this.menuItemsContainer.removeItem(this.menuSpacers[i + 1]);
                    this.rightVisibleIndex = i - 1;
                    this.menuItems[i].hide();
                    this.numItemsVisible--;
                }
                else {
                    // Once no overflow is detected, done checking
                    break;
                }
            }
        }
    };
    
    this.ensureItemsVisible = function () {
        this.menuItemsContainer.removeItem(this.menuSpacers[0]);
        if (this.activeIndex < this.leftVisibleIndex) { // shift right
            while (this.activeIndex < this.leftVisibleIndex) {
                this.menuItemsContainer.addItemAtIndex(this.menuSpacers[this.leftVisibleIndex], 0);
                this.menuItemsContainer.addItemAtIndex(this.menuItems[this.leftVisibleIndex - 1], 0, {padding: {top: 2, left: 6, right: 6}});
                this.numItemsVisible++;
                this.leftVisibleIndex--;
                this.menuItems[this.leftVisibleIndex].show();
                while (this.hasTooManyItems()) {
                    this.menuItemsContainer.removeItem(this.menuItems[this.rightVisibleIndex]);
                    this.menuItemsContainer.removeItem(this.menuSpacers[this.rightVisibleIndex + 1]);
                    this.menuItems[this.rightVisibleIndex].hide();
                    this.numItemsVisible--;
                    this.rightVisibleIndex--;
                }
            }
        } else if (this.activeIndex > this.rightVisibleIndex) { // add to end, shift left
            while (this.activeIndex > this.rightVisibleIndex) {
                this.menuItemsContainer.addItem(this.menuItems[this.rightVisibleIndex + 1], {padding: {top: 2, left: 6, right: 6}});
                this.menuItemsContainer.addItem(this.menuSpacers[this.rightVisibleIndex + 2]);
                this.numItemsVisible++;
                this.rightVisibleIndex++;
                this.menuItems[this.rightVisibleIndex].show();
                while (this.hasTooManyItems()) {
                    this.menuItemsContainer.removeItem(this.menuItems[this.leftVisibleIndex]);
                    this.menuItemsContainer.removeItem(this.menuSpacers[this.leftVisibleIndex + 1]);
                    this.menuItems[this.leftVisibleIndex].hide();
                    this.numItemsVisible--;
                    this.leftVisibleIndex++;
                }
            }
        }
        this.menuItemsContainer.addItemAtIndex(this.menuSpacers[0], 0);
    };
    
    this.layoutBrackets = function (direction) {
        var selectedDimensions, selectedPosition, targetItemIndex;
        
        this.leftBracket.hide();
        this.rightBracket.hide();
        
        this.menuItemsContainer.removeItem(this.leftBracket);
        this.menuItemsContainer.removeItem(this.rightBracket);
        
        if (direction) { // direction was used
            if (direction === 1) {
                if (this.activeIndex === 0) { // wrap
                    this.menuSpacers[this.menuSpacers.length - 1].resize({
                        width: this.spacerWidth,
                        height: 27
                    });
                    this.menuSpacers[this.menuSpacers.length - 2].resize({
                        width: this.spacerWidth,
                        height: 27
                    });
                } else {
                    this.menuSpacers[this.activeIndex - 1].resize({
                        width: this.spacerWidth,
                        height: 27
                    });
                }
            } else if (direction === -1) {
                if (this.activeIndex === (this.items.getLength() - 1)) { // wrap
                    this.menuSpacers[0].resize({
                        width: this.spacerWidth,
                        height: 27
                    });
                    this.menuSpacers[1].resize({
                        width: this.spacerWidth,
                        height: 27
                    });
                } else {
                    this.menuSpacers[this.activeIndex + 2].resize({
                        width: this.spacerWidth,
                        height: 27
                    });
                }
            }
        }
        
        this.menuSpacers[this.activeIndex].resize({
            width: this.spacerWidth - 6,
            height: 27
        });
        this.menuSpacers[this.activeIndex + 1].resize({
            width: this.spacerWidth - 6,
            height: 27
        });
        targetItemIndex = this.menuItemsContainer.getIndexOfItem(this.menuItems[this.activeIndex]);
        this.menuItemsContainer.addItemAtIndex(this.leftBracket, targetItemIndex);
        this.menuItemsContainer.addItemAtIndex(this.rightBracket, targetItemIndex + 2);
        
        if (this.leftVisibleIndex === 0) {
            this.leftArrow.hide();
        } else {
            this.leftArrow.show();
        }
        
        if (this.rightVisibleIndex === (this.items.getLength() - 1)) {
            this.rightArrow.hide();
        } else {
            this.rightArrow.show();
        }
        this.leftBracket.show();
        this.rightBracket.show();
        
        if ($htv.Platform.properties.has_spotlight === true) {
            selectedPosition = this.menuItems[this.activeIndex].getPosition();
            selectedDimensions = this.menuItems[this.activeIndex].getActualSize();
            $htv.Platform.updateSpotlight(selectedPosition.x + selectedDimensions.width / 2, selectedPosition.y + selectedDimensions.height / 2, 1);
        }
    };

    
    this.dispose = function () {
        var i;
        if (this.menuItems !== null) {
            for (i = 0; i < this.items.getLength(); i++) {
                $htv.Platform.deleteItem(this.menuItems[i]);
                $htv.Platform.deleteItem(this.menuSpacers[i]);
                this.menuSpacers[i] = null;
                this.menuItems[i] = null;
            }
            if (this.menuSpacers !== null) {
                $htv.Platform.deleteItem(this.menuSpacers[this.items.getLength()]);
                this.menuSpacers[this.items.getLength()] = null;
                this.menuSpacers = null;
            }
        }
        this.menuItemPositions = null;
        this.menuItems = null;
        $htv.Platform.deleteItem(this.leftBracket);
        $htv.Platform.deleteItem(this.rightBracket);
        $htv.Platform.deleteItem(this.leftArrow);
        $htv.Platform.deleteItem(this.rightArrow);
        this.leftBracket = null;
        this.rightBracket = null;
        this.leftArrow = null;
        this.rightArrow = null;
        this.height = 0;
        this.width = 0;
        this.x = 0;
        this.y = 0;
        this.z = 0;
        this.node = null;
        this.maxItemsVisible = -1;
        this.visible = false;
        this.items = null;
        this.menu_title = null;
    };
    
    this.focus = function () {
        if (this.menuItems) {
            for (var i = 0; i < this.menuItems.length; i++) {
                if (this.menuItems[i]) {
                    this.menuItems[i].setStyle($htv.Styles.NonSlidingMenuItemFocused);
                }
            }
            this.menuItems[this.activeIndex].setStyle($htv.Styles.NonSlidingMenuItemSelectedFocused);
            this.leftBracket.show();
            this.rightBracket.show();
            this.layoutBrackets();
            
        }
    };
    
    this.unfocus = function () {
        if (this.menuItems) {
            for (var i = 0; i < this.menuItems.length; i++) {
                if (this.menuItems[i]) {
                    this.menuItems[i].setStyle($htv.Styles.NonSlidingMenuItemUnfocused);
                }
            }
            this.menuItems[this.activeIndex].setStyle($htv.Styles.NonSlidingMenuItemSelectedUnfocused);
            this.leftArrow.hide();
            this.rightArrow.hide();
            this.leftBracket.hide();
            this.rightBracket.hide();
        }
    };
    
    this.hide = function () {
        this.visible = false;
        for (var i = 0; this.menuItems && i < this.menuItems.length; i++) {
            if (this.menuItems[i]) {
                this.menuItems[i].hide();
            }
        }
        this.leftArrow.hide();
        this.rightArrow.hide();
        this.leftBracket.hide();
        this.rightBracket.hide();
    };
    
    this.show = function () {
        this.visible = true;
        for (var i = this.leftVisibleIndex; this.menuItems && i <= this.rightVisibleIndex; i++) {
            if (this.menuItems[i]) {
                this.menuItems[i].show();
            }
        }
    };
    
    this.handleEvent = function (eventName, eventData) {
        if (eventName === "USER_INPUT") {
            this.handleInput(eventData);
        } else {
            
        }
    };
    
    this.handleInput = function (eventData) {
        var selectedDimensions, selectedPosition;
        
        switch (eventData.action) {
        case "KEY_RETURN":
        case "MOVE_UP":
            if (!eventData.is_down || eventData.is_hold) {
                return;
            }
            this.node.view.fireEvent("LOSING_FOCUS", {nav_dir: "up"});
            break;
        case "MOVE_LEFT":
            if (eventData.is_down) {
                this.leftArrow.setURL("images/arrow-left-hover.png");
            } else {
                this.leftArrow.setURL("images/arrow-left.png");
            }
            if (eventData.is_down && this.menuItems && this.activeIndex < this.menuItems.length) {
                this.menuItems[this.activeIndex].setStyle($htv.Styles.NonSlidingMenuItemFocused);
                if (this.activeIndex > 0) {
                    this.activeIndex--;
                } else {
                    this.activeIndex = this.items.getLength() - 1;
                    if (this.items.getLength() === 1) {
                        this.menuItems[this.activeIndex].setStyle($htv.Styles.NonSlidingMenuItemSelectedFocused);
                        return; // doesn't need to do anything.
                    }
                    
                    // Move spotlight so it comes in from the right
                    if ($htv.Platform.properties.has_spotlight === true) {
                        selectedPosition = this.menuItems[this.activeIndex].getPosition();
                        selectedDimensions = this.menuItems[this.activeIndex].getActualSize();
                        $htv.Platform.updateSpotlight(1200, selectedPosition.y + selectedDimensions.height / 2, 1, 0);
                    }
                }
                this.menuItems[this.activeIndex].setStyle($htv.Styles.NonSlidingMenuItemSelectedFocused);
                this.ensureItemsVisible();
                this.layoutBrackets(-1);
                this.node.view.fireEvent("MENU_SELECTION_CHANGED", {
                    title: this.items.getItemAt(this.activeIndex).item.title,
                    items_url: this.items.getItemAt(this.activeIndex).item.items_url,
                    cmtype: this.items.getItemAt(this.activeIndex).item.cmtype,
                    options: { // todo: considering just sending this.activeItem + properties.
                        start_at_end: this.items.getItemAt(this.activeIndex).item.start_at_end === "true",
                        add_cb: this.items.getItemAt(this.activeIndex).item.add_cb,
                        login_required: this.items.getItemAt(this.activeIndex).item.login_required,
                        recommended_required: this.items.getItemAt(this.activeIndex).item.recommended_required,
                        carousel_item_type: this.items.getItemAt(this.activeIndex).item.carousel_item_type,
                        carousel_name: this.getChildCarouselName(),
                        include_show_title: this.items.getItemAt(this.activeIndex).item.include_show_title,
                        view_title: this.menu_title,
                        use_related_title: this.items.getItemAt(this.activeIndex).item.use_related_title,
                        delayed_initialize: true,
                        metadata_item: this.items.getMetadataItem(),
                        bug_br_field: this.items.getItemAt(this.activeIndex).item.bug_br_field,
                        child_text: this.items.getItemAt(this.activeIndex).item.child_text
                    },
                    target: this.node
                });
            }
            break;
        case "MOVE_RIGHT":
            if (eventData.is_down) {
                this.rightArrow.setURL("images/arrow-right-hover.png");
            } else {
                this.rightArrow.setURL("images/arrow-right.png");
            }
            if (eventData.is_down && this.menuItems && this.activeIndex < this.menuItems.length) {
                this.menuItems[this.activeIndex].setStyle($htv.Styles.NonSlidingMenuItemFocused);
                if (this.activeIndex < this.items.getLength() - 1) {
                    this.activeIndex++;
                } else {
                    this.activeIndex = 0;
                    if (this.items.getLength() === 1) {
                        this.menuItems[this.activeIndex].setStyle($htv.Styles.NonSlidingMenuItemSelectedFocused);
                        return; // doesn't need to do anything.
                    }
                    
                    // Move spotlight so it comes in from the left
                    if ($htv.Platform.properties.has_spotlight === true) {
                        selectedPosition = this.menuItems[this.activeIndex].getPosition();
                        selectedDimensions = this.menuItems[this.activeIndex].getActualSize();
                        $htv.Platform.updateSpotlight(-200, selectedPosition.y + selectedDimensions.height / 2, 1, 0);
                    }
                }
                this.menuItems[this.activeIndex].setStyle($htv.Styles.NonSlidingMenuItemSelectedFocused);
                this.ensureItemsVisible();
                this.layoutBrackets(1);
                
                this.node.view.fireEvent("MENU_SELECTION_CHANGED", {
                    title: this.items.getItemAt(this.activeIndex).item.title,
                    items_url: this.items.getItemAt(this.activeIndex).item.items_url,
                    cmtype: this.items.getItemAt(this.activeIndex).item.cmtype,
                    options: {
                        start_at_end: this.items.getItemAt(this.activeIndex).item.start_at_end === "true",
                        add_cb: this.items.getItemAt(this.activeIndex).item.add_cb,
                        login_required: this.items.getItemAt(this.activeIndex).item.login_required,
                        recommended_required: this.items.getItemAt(this.activeIndex).item.recommended_required,
                        carousel_item_type: this.items.getItemAt(this.activeIndex).item.carousel_item_type,
                        carousel_name: this.getChildCarouselName(),
                        include_show_title: this.items.getItemAt(this.activeIndex).item.include_show_title,
                        view_title: this.menu_title,
                        use_related_title: this.items.getItemAt(this.activeIndex).item.use_related_title,
                        delayed_initialize: true,
                        metadata_item: this.items.getMetadataItem(),
                        bug_br_field: this.items.getItemAt(this.activeIndex).item.bug_br_field,
                        child_text: this.items.getItemAt(this.activeIndex).item.child_text
                    },
                    target: this.node
                });
            }
            break;
        case "MOVE_DOWN":
            if (!eventData.is_down || eventData.is_hold) {
                return;
            }
            this.node.view.fireEvent("LOSING_FOCUS", {nav_dir: "down"});
            break;
        case "PLAY":
            if (!eventData.is_down || eventData.is_hold) {
                return;
            }
            this.node.view.fireEvent("PLAY_BUTTON_PRESSED", {
                item: this.items.getItemAt(this.activeIndex).item,
                target: this.node
            });
            break;
        case "PRESS_OK":
            if (!eventData.is_down || eventData.is_hold) {
                return;
            }
            this.node.view.fireEvent("MENU_ITEM_ACTIVATED", {
                item: this.items.getItemAt(this.activeIndex).item,
                target: this.node
            });
            break;
        default:
            
            break;
        }
    };
};

$htv.Controls.AlphaMenu = function () {
    $htv.Controls.NonSlidingMenu.call(this);
    this.className = "AlphaMenu";
    
    this.initialize = function (position, target, url, options) {
        // TODO:  why does this seem like an extreme hack?
        if (!options) {
            options = {};
        }
        options.max_items_visible = 17;
        this._initialize(position, target, url, options);
    };
    
    this.initializeResult = function () {
        var i, indicesUrl, source, letters, letterObjects, letterObject;
        letters = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
        letterObjects = [];
        
        if (this.visible !== true) {
            return;
        }
        this.spacerWidth = 18;
        this.itemPadding = 6; // combined = 30 px
        
        // Use the Twinkie result as a template for the alpha menu items
        source = this.items.getItemAt(this.activeIndex).item;
        if (source === null) {
            return;
        }

        // Fetch the alpha indexes using the child carousel id
        indicesUrl = $htv.Utils.applyGlobalContext($htv.Constants.Endpoints.menu +
            "/alphabetindices?id=" + source.items_url.replace("/menu/", ""));
        $htv.Platform.loadURL(indicesUrl, this, this.onAlphaIndicesResponse, {
            xmlparse: false
        });
        
        // Swap in the alpha menu items
        
        for (i = 0; i < letters.length; i++) {
            letterObject = $htv.Utils.copyObject(source);
            letterObject.title = letters[i];
            letterObjects.push(letterObject);
        }
        this.setDataSource($htv.Utils.createGenericCollection(letterObjects));
    };
    
    // Given a letter, move the unselected alpha menu to select that letter if exists
    this.jumpToAlpha = function (letter) {
        var diff, newIndex;
        
        if (this.visible !== true) {
            return;
        }
        
        if (letter < "A" || letter > "Z") {
            letter = "#";
        }
        
        newIndex = this.activeIndex;
        while (newIndex >= 0 && newIndex < this.menuItems.length) {
            diff = letter.charCodeAt(0) - this.menuItems[newIndex].getText().charCodeAt(0);
            
            if (diff === 0) {
                if (newIndex !== this.activeIndex) {
                    this.menuItems[this.activeIndex].setStyle($htv.Styles.NonSlidingMenuItemUnfocused);
                    this.activeIndex = newIndex;
                    this.menuItems[this.activeIndex].setStyle($htv.Styles.NonSlidingMenuItemSelectedUnfocused);
                    this.ensureItemsVisible();
                }
                return;
            } else if (diff > 0) {
                newIndex++;
            } else if (diff < 0) {
                newIndex--;
            }
        }
    };
    
    this.onAlphaIndicesResponse = function (responseData, options) {
        if (this.visible !== true) {
            return;
        }
        
        this.alphaIndices = $htv.Platform.parseJSON(responseData);
        this.alphaIndices["#"] = 0;
    };
    
    this.getAlphaIndex = function (letter) {
        if (this.alphaIndices && this.alphaIndices[letter] !== undefined) {
            return this.alphaIndices[letter];
        }
        return -1;
    };
};

$htv.Controls.AlphaMenu.prototype = new $htv.Controls.NonSlidingMenu();

$htv.Controls.RatingControl = function () {
    this.height = 0;
    this.width = 0;
    this.x = 0;
    this.y = 0;
    this.z = 0;
    this.node = null;
    this.className = "RatingControl";
    this.visible = true;
    this.titleLabel = null;
    this.messageLabel = null;
    this.canvas = null;
    this.ratingValue = 3;
    this.video_id = -1;
    this.show_id = -1;
    this.is_video = true;
    this.ratingSubmitted = false;
    this.title = "";
    this.show_canonical_name = "";
    this.stars = [];
    this.hasFocus = false;
    this.unfocusedMessage = null;
    this.leftBracket = null;
    this.rightBracket = null;
    this.showImage = null;
    
    this.initialize = function (position, target, url, options) {
        var i, ratingValue, titleLabelPosition, messageLabelPosition, starX, starY, starWidth, starHeight, starPadding;
        
        this.height = position.height;
        this.width = position.width;
        this.x = position.x;
        this.y = position.y;
        this.z = position.z;
        this.node = target;
        this.hasFocus = false;
        this.ratingValue = 3;
        this.video_id = -1;
        this.show_id = -1;
        this.ratingSubmitted = false;
        this.titleLabel = null;
        this.showImage = null;
        this.title = "";
        this.unfocusedMessage = "";
        this.show_canonical_name = "";
        if (options.hasOwnProperty("canvas")) {
            this.canvas = options.canvas;
        }
        if (options.hasOwnProperty("show_canonical_name")) {
            this.show_canonical_name = options.show_canonical_name;
        }
        if (options.hasOwnProperty("show_id")) {
            this.show_id = parseInt(options.show_id, 10);
        }
        if (options.hasOwnProperty("video_id")) {
            this.video_id = parseInt(options.video_id, 10);
        }
        
        if (this.video_id > 0) {
            this.title = options.video_title;
            ratingValue = parseInt($htv.Platform.readLocalData("videoRatingFile", this.video_id), 10);
            this.unfocusedMessage = "Press down to vote for this video";
            if (!isNaN(ratingValue) && ratingValue >= 0) {
                this.ratingSubmitted = true;
                this.ratingValue = parseInt(ratingValue, 10);
                this.unfocusedMessage = "You gave this video " + this.ratingValue + " stars";
            }
        }
        else if (this.show_id > 0) {
            ratingValue = parseInt($htv.Platform.readLocalData("showRatingFile", this.show_id), 10);
            this.unfocusedMessage = "Press down to vote for this show";
            if (!isNaN(ratingValue) && ratingValue >= 0) {
                this.ratingSubmitted = true;
                this.ratingValue = parseInt(ratingValue, 10);
                this.unfocusedMessage = "You gave this show " + this.ratingValue + " stars";
            }
        }
        
        titleLabelPosition = {
            x: this.x,
            y: this.y + 75,
            z: this.z,
            width: this.width,
            height: 20
        };
        messageLabelPosition = {
            x: this.x,
            y: this.y + 230,
            z: this.z,
            width: this.width,
            height: 30
        };
        starY = messageLabelPosition.y - 90;
        
        if (this.show_id > 0) {
            url = $htv.Utils.getURLForShowLogo(this.show_id, {
                width: 220,
                height: 80,
                maintain_ratio: true,
                format: "png"
            });
            this.showImage = $htv.Platform.createImage({
                x: this.x + this.width / 2 - 110,
                y: this.y + 24,
                z: this.z,
                width: 220,
                height: 80
            }, url, this.canvas);
        }
        
        if (!$htv.Utils.stringIsNullOrEmpty(this.title)) {
            if (this.showImage !== null) {
                titleLabelPosition.y = this.y + 130;
                messageLabelPosition.y = this.y + 250;
                starY = messageLabelPosition.y - 75;
            }
            this.titleLabel = $htv.Platform.createLabel(titleLabelPosition, "Rate \"" + this.title + "\"", this.canvas, {styleName: $htv.Styles.RateVideoTitle});
        }
        
        this.messageLabel = $htv.Platform.createLabel(messageLabelPosition, this.unfocusedMessage, this.canvas, {styleName: $htv.Styles.RateTextUnfocused});
        
        starWidth = 60;
        starHeight = 55;
        starPadding = 35;
        starX = this.x + this.width / 2 - (5 * starWidth + 4 * starPadding) / 2 + 35;
        for (i = 0; i < 5; i++) {
            this.stars[i] = $htv.Platform.createImage({
                x: starX + i * starWidth + (i - 1) * starPadding,
                y: starY,
                z: this.z,
                width: starWidth,
                height: starHeight
            }, "images/rating-grey-lg.png", this.canvas);
        }
        
        // Position gets updated in updateUI()
        this.leftBracket = $htv.Platform.createImage({
            x: -100,
            y: -100,
            z: this.z,
            width: 6,
            height: 27
        }, "images/bracket_small_left.png", this.canvas);
        this.rightBracket = $htv.Platform.createImage({
            x: -100,
            y: -100,
            z: this.z,
            width: 6,
            height: 27
        }, "images/bracket_small_right.png", this.canvas);
        
        // Update initial UI
        this.updateUI();
    };
    
    this.dispose = function () {
        if (this.titleLabel !== null) {
            $htv.Platform.deleteItem(this.titleLabel);
            this.titleLabel = null;
        }
        if (this.showImage !== null) {
            $htv.Platform.deleteItem(this.showImage);
            this.showImage = null;
        }
        $htv.Platform.deleteItem(this.leftBracket);
        this.leftBracket = null;
        $htv.Platform.deleteItem(this.rightBracket);
        this.rightBracket = null;
        $htv.Platform.deleteItem(this.messageLabel);
        this.messageLabel = null;
        while (this.stars.length > 0) {
            $htv.Platform.deleteItem(this.stars.pop());
        }
        this.ratingValue = 3;
        this.unfocusedMessage = null;
    };
    
    this.focus = function () {
        if (this.ratingSubmitted) {
            // Go back up to NSM (assumes parent control is up)
            this.node.view.fireEvent("LOSING_FOCUS", {nav_dir: "up"});
            return;
        }
        
        this.hasFocus = true;
        this.updateUI();
        this.messageLabel.setStyle($htv.Styles.RateTextFocused);
    };
    
    this.unfocus = function () {
        this.hasFocus = false;
        this.updateUI();
        this.messageLabel.setStyle($htv.Styles.RateTextUnfocused);
    };
    
    this.hide = function () {
        if (this.titleLabel !== null) {
            this.titleLabel.hide();
        }
        if (this.showImage !== null) {
            this.showImage.hide();
        }
        this.messageLabel.hide();
        for (var i = 0; i < this.stars.length; i++) {
            this.stars[i].hide();
        }
        if (this.leftBracket !== null) {
            this.leftBracket.hide();
        }
        if (this.rightBracket !== null) {
            this.rightBracket.hide();
        }
    };
    
    this.show = function () {
        if (this.titleLabel !== null) {
            this.titleLabel.show();
        }
        if (this.showImage !== null) {
            this.showImage.show();
        }
        this.messageLabel.show();
        for (var i = 0; i < this.stars.length; i++) {
            this.stars[i].show();
        }
    };
    
    this.handleEvent = function (eventName, eventData) {
        if (eventName === "USER_INPUT") {
            this.handleInput(eventData);
        } else {
            
        }
    };
    
    this.onRatingComplete = function (result) {
        this.unfocusedMessage = "Thanks for rating!";
        this.updateUI();
        
        if (this.video_id !== -1) {
            $htv.Platform.writeLocalData("videoRatingFile", this.video_id, this.ratingValue);
        } else if (this.show_id !== -1) {
            $htv.Platform.writeLocalData("showRatingFile", this.show_id, this.ratingValue);
        }
    };
    
    // Uses ratingSubmitted, ratingValue, and hasFocus to update
    this.updateUI = function () {
        var i, starPos, lbp, rbp, starY;
        for (i = 0; i < this.stars.length; i++) {
            if (i < this.ratingValue && this.ratingSubmitted) {
                this.stars[i].setURL("images/rating-white-lg.png");
            } else if (i < this.ratingValue && this.hasFocus) {
                this.stars[i].setURL("images/rating-green-lg.png");
            } else {
                this.stars[i].setURL("images/rating-grey-lg.png");
            }
        }
        
        if (!this.hasFocus) {
            this.messageLabel.setText(this.unfocusedMessage);
        } else if (!this.ratingSubmitted) {
            switch (this.ratingValue) {
            case 1:
                this.messageLabel.setText("Hated it");
                break;
            case 2:
                this.messageLabel.setText("Didn't like it");
                break;
            case 3:
                this.messageLabel.setText("Thought it was OK");
                break;
            case 4:
                this.messageLabel.setText("Liked it");
                break;
            case 5:
                this.messageLabel.setText("Loved it");
                break;
            default:
                this.messageLabel.setText("");
                break;
            }
        }
        
        if (!this.hasFocus || 
            this.ratingSubmitted ||
            this.ratingValue < 1 ||
            this.ratingValue > 5) {
                
            this.leftBracket.hide();
            this.rightBracket.hide();
        } else {
            starPos = this.stars[this.ratingValue - 1].getPosition();
            this.leftBracket.move({
                x: starPos.x - 15,
                y: starPos.y + starPos.height / 2 - this.leftBracket.getPosition().height / 2,
                z: starPos.z,
                width: 6,
                height: 27
            });
            this.rightBracket.move({
                x: starPos.x + starPos.width + 7,
                y: starPos.y + starPos.height / 2 - this.rightBracket.getPosition().height / 2,
                z: starPos.z,
                width: 6,
                height: 27
            });
            this.leftBracket.show();
            this.rightBracket.show();
            
            rbp = this.rightBracket.getPosition();
            lbp = this.leftBracket.getPosition();
            starY = this.stars[0].getPosition().y;
            $htv.Platform.updateSpotlight(lbp.x + 3 + (rbp.x - lbp.x) / 2, starY + 30, 2);
        }
    };
    
    this.handleInput = function (eventData) {
        if (!eventData.is_down || eventData.is_hold) {
            return;
        }
        
        switch (eventData.action) {
            
        case "PRESS_OK":
            if (this.ratingValue > 0) {
                this.unfocusedMessage = "Rating...";
                this.ratingSubmitted = true;
                if (this.video_id !== -1) {
                    $htv.Profile.rateVideo(this.video_id, this.ratingValue, this, this.onRatingComplete);
                } else if (this.show_id !== -1) {
                    $htv.Profile.rateShow(this.show_id, this.ratingValue, this, this.onRatingComplete);
                }
                // Go back up to NSM (assumes parent control is up)
                this.node.view.fireEvent("LOSING_FOCUS", {nav_dir: "up"});
            } // else display text about how you need to give a rating.
            break;
        case "MOVE_RIGHT":
            if (this.ratingValue < 5) {
                this.ratingValue++;
                this.updateUI();
            }
            break;
        case "MOVE_LEFT":
            if (this.ratingValue > 1) {
                this.ratingValue--;
                this.updateUI();
            }
            break;
        case "KEY_RETURN":
        case "MOVE_UP":
            this.node.view.fireEvent("LOSING_FOCUS", {nav_dir: "up"});
            break;
        default:
            
            
            break;
        }
    };
};


$htv.Controls.RatingStarsControl = function () {
    this.height = 0;
    this.width = 0;
    this.x = 0;
    this.y = 0;
    this.z = 0;
    this.node = null;
    this.className = "RatingStarsControl";
    this.canvas = null;
    this.stars = [];
    this.starsContainer = null;
    
    this.initialize = function (position, target, url, options) {
        this.height = position.height;
        this.width = position.width;
        this.x = position.x;
        this.y = position.y;
        this.z = position.z;
        this.node = target;
        if (options && options.hasOwnProperty("canvas")) {
            this.canvas = options.canvas;
        }
        
        this.starsContainer = $htv.Platform.createContainer({
            x: this.x,
            y: this.y,
            z: this.z,
            width: this.width,
            height: this.height
        }, this.canvas, {vertical: false, spacing: 2, edgePadding: 0});
        
        for (var i = 0; i < 5; i++) {
            this.stars[i] = $htv.Platform.createImage({
                x: 0,
                y: 0,
                z: this.z,
                width: 16,
                height: 16
            }, "images/rating-empty-sm.png", this.canvas);
            this.starsContainer.addItem(this.stars[i]);
        }
        
        if (options.hasOwnProperty("rating")) {
            this.setRating(options.rating);
        }
        
//        // REVIEW: use green stars to indicate user already rated?

//        // NC: probably want to use htv.Profile once we have access to old ratings.
//
//        if (options.hasOwnProperty("video_id")) {
//            var ratingValue = $htv.Platform.readLocalData("videoRatingFile", options.video_id)
//            if (ratingValue !== undefined) {
//                this.setRating(ratingValue);
//            };
//        }
//        if (options.hasOwnProperty("show_id")) {
//            var ratingValue = $htv.Platform.readLocalData("showRatingFile", options.show_id)
//            if (ratingValue !== undefined) {
//                this.setRating(ratingValue);
//            };
//        }
    };
    
    this.getContainer = function () {
        return this.starsContainer;
    };
    
    this.setRating = function (newRating) {
        var i, imageUrl;
        
        if (newRating === null) {
            newRating = 3;
        }
        for (i = 0; i < this.stars.length; i++) {
            imageUrl = "images/rating-empty-sm.png";
            if (i < Math.floor(newRating)) {
                imageUrl = "images/rating-full-sm.png";
            }
            else if (i + 0.5 < newRating) {
                imageUrl = "images/rating-half-sm.png";
            }
            this.stars[i].setURL(imageUrl);
        }
    };
    
    this.dispose = function () {
        while (this.stars.length > 0) {
            $htv.Platform.deleteItem(this.stars.pop());
        }
        $htv.Platform.deleteItem(this.starsContainer);
        this.starsContainer = null;
    };
    
    this.focus = function () {
    };
    
    this.unfocus = function () {
    };
    
    this.hide = function () {
        this.starsContainer.hide();
    };
    
    this.show = function () {
        this.starsContainer.show();
    };
    
    this.handleEvent = function (eventName, eventData) {
        if (eventName === "USER_INPUT") {
            this.handleInput(eventData);
        } else {
            
        }
    };
    
    this.handleInput = function (eventData) {
        if (!eventData.is_down || eventData.is_hold) {
            return;
        }
        
        switch (eventData.action) {
        case "PRESS_OK":
            break;
        case "MOVE_RIGHT":
            break;
        case "MOVE_LEFT":
            break;
        case "MOVE_UP":
            break;
        default:
            
            break;
        }
    };
};


$htv.Controls.SubscriptionControl = function () {
    this.height = 0;
    this.width = 0;
    this.x = 0;
    this.y = 0;
    this.z = 0;
    this.node = null;
    this.className = "SubscriptionControl";
    this.hasFocus = false;
    this.clipsLabel = null;
    this.episodesLabel = null;
    this.selectedLabel = 0;
    this.subscriptionState = null;
    this.showImage = null;
    this.leftBracket = null;
    this.rightBracket = null;
    this.leftSmallBracket = null;
    this.rightSmallBracket = null;
    this.episodesCheckbox = null;
    this.firstRunRadioButton = null;
    this.allRadioButton = null;
    this.allLabel = null;
    this.firstRunLabel = null;
    this.clipsCheckbox = null;
    this.hideEpisodes = false;
    this.show_id = -1;
    this.show_name = "";
    this.show_canonical_name = "";
    
    this.initialize = function (position, target, url, options) {
        var episodesLabelPosition, clipsLabelPosition;
        
        this.height = position.height;
        this.width = position.width;
        this.x = position.x;
        this.y = position.y;
        this.z = position.z;
        this.node = target;
        this.hasFocus = false;
        this.subscriptionState = null;
        this.hideEpisodes = false;
        this.show_id = -1;
        this.show_name = "";
        this.show_canonical_name = "";
    
        if (options.hasOwnProperty("canvas")) {
            this.canvas = options.canvas;
        }
        if (options.hasOwnProperty("show_id")) {
            this.show_id = options.show_id;
        }
        if (options.hasOwnProperty("show_name")) {
            this.show_name = options.show_name;
        }
        if (options.hasOwnProperty("show_canonical_name")) {
            this.show_canonical_name = options.show_canonical_name;
        }
        if (options.hasOwnProperty("total_seasons_count")) {
            this.hideEpisodes = (options.total_seasons_count !== null &&
                options.total_seasons_count !== undefined &&
                parseInt(options.total_seasons_count, 10) === 0);
        }
        
        episodesLabelPosition = {
            x: this.x + 405,
            y: this.y + 122,
            z: this.z,
            width: this.width,
            height: 30
        };
        clipsLabelPosition = {
            x: this.x + 405,
            y: (this.hideEpisodes ? this.y + 185 : this.y + 247),
            z: this.z,
            width: this.width,
            height: 30
        };
        
        this.allLabel = $htv.Platform.createLabel({
            x: this.x + 427,
            y: this.y + 162,
            z: this.z,
            width: this.width,
            height: 30
        }, "All episodes", this.canvas, {styleName: $htv.Styles.SubscribeTextDisabled});
        this.firstRunLabel = $htv.Platform.createLabel({
            x: this.x + 427,
            y: this.y + 196,
            z: this.z,
            width: this.width,
            height: 30
        }, "TV first-run only", this.canvas, {styleName: $htv.Styles.SubscribeTextDisabled});
        
        this.firstRunRadioButton = $htv.Platform.createImage({
            x: this.x + 400,
            y: this.y + 200,
            z: this.z,
            width: 16,
            height: 17
        }, "images/btn-radio-inactive.png", this.canvas);
        this.allRadioButton = $htv.Platform.createImage({
            x: this.x + 400,
            y: this.y + 166,
            z: this.z,
            width: 16,
            height: 17
        }, "images/btn-radio-inactive.png", this.canvas);
        this.leftBracket = $htv.Platform.createImage({
            x: -100,
            y: -100,
            z: this.z,
            width: 6,
            height: 36
        }, "images/bracket-yes-no-left.png", this.canvas);
        this.rightBracket = $htv.Platform.createImage({
            x: -100,
            y: -100,
            z: this.z,
            width: 6,
            height: 36
        }, "images/bracket-yes-no-right.png", this.canvas);
        this.leftSmallBracket = $htv.Platform.createImage({
            x: -100,
            y: -100,
            z: this.z,
            width: 6,
            height: 22
        }, "images/bracket-radio-btn-left.png", this.canvas);
        this.rightSmallBracket = $htv.Platform.createImage({
            x: -100,
            y: -100,
            z: this.z,
            width: 6,
            height: 22
        }, "images/bracket-radio-btn-right.png", this.canvas);
        this.episodesCheckbox = $htv.Platform.createImage({
            x: this.x + 375,
            y: this.y + 121,
            z: this.z,
            width: 24,
            height: 21
        }, "images/checkbox.png", this.canvas);
        this.clipsCheckbox = $htv.Platform.createImage({
            x: this.x + 375,
            y: (this.hideEpisodes ? this.y + 184 : this.y + 246),
            z: this.z,
            width: 24,
            height: 21
        }, "images/checkbox.png", this.canvas);
        
        if (this.show_id > 0) {
            url = $htv.Utils.getURLForShowLogo(this.show_id, {
                width: 220,
                height: 80,
                maintain_ratio: true,
                format: "png"
            });
            this.showImage = $htv.Platform.createImage({
                x: this.x + this.width / 2 - 110,
                y: this.y + 24,
                z: this.z,
                width: 220,
                height: 80
            }, url, this.canvas);
        }
        
        this.episodesLabel = $htv.Platform.createLabel(episodesLabelPosition, "Subscribe to episodes", this.canvas, {styleName: $htv.Styles.SubscribeTextUnfocused});
        this.clipsLabel = $htv.Platform.createLabel(clipsLabelPosition, "Subscribe to clips", this.canvas, {styleName: $htv.Styles.SubscribeTextUnfocused});
        
        if (this.hideEpisodes) {
            this.episodesLabel.hide();
            this.allLabel.hide();
            this.allRadioButton.hide();
            this.firstRunLabel.hide();
            this.firstRunRadioButton.hide();
            this.episodesCheckbox.hide();
            
            this.selectedLabel = 3;
        }
        else {
            this.selectedLabel = 0;
        }
        
        $htv.Profile.getSubscriptionInfo(this.show_id, this, this.initializeResult);
    };
    
    this.initializeResult = function (result) {
        
        describe(result);
        this.subscriptionState = {};
        this.subscriptionState.episodes = result.episodes;
        this.subscriptionState.clips = result.clips;
        this.episodesLabel.setText("Subscribe to episodes");
        this.clipsLabel.setText("Subscribe to clips");
        if (this.subscriptionState.episodes === "all") {
            this.episodesCheckbox.setURL("images/checkbox-checked.png");
            this.allRadioButton.setURL("images/btn-radio-active.png");
            this.firstRunRadioButton.setURL("images/btn-radio-inactive.png");
        } else if (this.subscriptionState.episodes === "first_run_only") {
            this.episodesCheckbox.setURL("images/checkbox-checked.png");
            this.allRadioButton.setURL("images/btn-radio-inactive.png");
            this.firstRunRadioButton.setURL("images/btn-radio-active.png");
        } else {
            this.episodesCheckbox.setURL("images/checkbox.png");
            this.allRadioButton.setURL("images/btn-radio-inactive.png");
            this.firstRunRadioButton.setURL("images/btn-radio-inactive.png");
        }
        if (this.subscriptionState.clips !== "none") {
            this.clipsCheckbox.setURL("images/checkbox-checked.png");
        } else {
            this.clipsCheckbox.setURL("images/checkbox.png");
        }
    };
    
    this.dispose = function () {
        $htv.Platform.deleteItem(this.episodesLabel);
        $htv.Platform.deleteItem(this.clipsLabel);
        $htv.Platform.deleteItem(this.showImage);
        $htv.Platform.deleteItem(this.leftBracket);
        $htv.Platform.deleteItem(this.rightBracket);
        $htv.Platform.deleteItem(this.episodesCheckbox);
        $htv.Platform.deleteItem(this.clipsCheckbox);
        $htv.Platform.deleteItem(this.firstRunRadioButton);
        $htv.Platform.deleteItem(this.allRadioButton);    
        $htv.Platform.deleteItem(this.allLabel);
        $htv.Platform.deleteItem(this.firstRunLabel);
        $htv.Platform.deleteItem(this.leftSmallBracket);
        $htv.Platform.deleteItem(this.rightSmallBracket);
        this.leftSmallBracket = null;
        this.rightSmallBracket = null;
        this.allLabel = null;
        this.firstRunLabel = null;
        this.firstRunRadioButton = null;
        this.allRadioButton = null;
        this.leftBracket = null;
        this.rightBracket = null;
        this.leftSmallBracket = null;
        this.rightSmallBracket = null;
        this.episodesCheckbox = null;
        this.clipsCheckbox = null;
        this.episodesLabel = null;
        this.clipsLabel = null;
        this.showImage = null;
        
        this.subscriptionState = null;
    };
    
    this.focus = function () {
        var lbp, rbp;
        this.hasFocus = true;
        // todo: wow, these really need to be buttons with state readers or something
        // easily the most website-like control..
        this.leftBracket.hide();
        this.rightBracket.hide();
        this.leftSmallBracket.hide();
        this.rightSmallBracket.hide();
        // reset states, then set the brackets/active
        this.episodesLabel.setStyle($htv.Styles.SubscribeTextUnfocused);
        this.allLabel.setStyle($htv.Styles.SubscribeTextDisabled);
        this.firstRunLabel.setStyle($htv.Styles.SubscribeTextDisabled);
        this.clipsLabel.setStyle($htv.Styles.SubscribeTextUnfocused);
        if (this.subscriptionState.episodes === "all") {
            this.episodesCheckbox.setURL("images/checkbox-checked.png");
            this.allRadioButton.setURL("images/btn-radio-active.png");
            this.firstRunRadioButton.setURL("images/btn-radio-inactive.png");
            this.allLabel.setStyle($htv.Styles.SubscribeTextUnfocused);
            this.firstRunLabel.setStyle($htv.Styles.SubscribeTextUnfocused);
        } else if (this.subscriptionState.episodes === "first_run_only") {
            this.episodesCheckbox.setURL("images/checkbox-checked.png");
            this.allRadioButton.setURL("images/btn-radio-inactive.png");
            this.firstRunRadioButton.setURL("images/btn-radio-active.png");
            this.allLabel.setStyle($htv.Styles.SubscribeTextUnfocused);
            this.firstRunLabel.setStyle($htv.Styles.SubscribeTextUnfocused);
        } else {
            this.episodesCheckbox.setURL("images/checkbox.png");
            this.allRadioButton.setURL("images/btn-radio-inactive.png");
            this.firstRunRadioButton.setURL("images/btn-radio-inactive.png");
        }
        if (this.subscriptionState.clips !== "none") {
            this.clipsCheckbox.setURL("images/checkbox-checked.png");
        } else {
            this.clipsCheckbox.setURL("images/checkbox.png");
        }
        
        if (this.selectedLabel === 0) {
            this.leftBracket.move({
                x: this.x + 352,
                y: this.y + 117,
                z: this.z,
                width: 6,
                height: 35
            });
            this.rightBracket.move({
                x: this.x + 623,
                y: this.y + 117,
                z: this.z,
                width: 6,
                height: 35
            });
            this.leftBracket.show();
            this.rightBracket.show();
            if (this.subscriptionState.episodes !== "none") {
                this.episodesCheckbox.setURL("images/checkbox-green-checked.png");
            } else {
                this.episodesCheckbox.setURL("images/checkbox-green.png");
            }
            this.episodesLabel.setStyle($htv.Styles.SubscribeTextFocused);
        } else if (this.selectedLabel === 1) {
            this.leftSmallBracket.move({
                x: this.x + 380,
                y: this.y + 164,
                z: this.z,
                width: 6,
                height: 22
            });
            this.rightSmallBracket.move({
                x: this.x + 555,
                y: this.y + 164,
                z: this.z,
                width: 6,
                height: 22
            });
            this.leftSmallBracket.show();
            this.rightSmallBracket.show();
            if (this.subscriptionState.episodes === "all") {
                this.allRadioButton.setURL("images/btn-radio-active-hover.png");
            } else {
                this.allRadioButton.setURL("images/btn-radio-hover.png");
            }
            this.allLabel.setStyle($htv.Styles.SubscribeTextFocused);
        } else if (this.selectedLabel === 2) {
            this.leftSmallBracket.move({
                x: this.x + 380,
                y: this.y + 197,
                z: this.z,
                width: 6,
                height: 22
            });
            this.rightSmallBracket.move({
                x: this.x + 592,
                y: this.y + 197,
                z: this.z,
                width: 6,
                height: 22
            });
            this.leftSmallBracket.show();
            this.rightSmallBracket.show();
            if (this.subscriptionState.episodes === "first_run_only") {
                this.firstRunRadioButton.setURL("images/btn-radio-active-hover.png");
            } else {
                this.firstRunRadioButton.setURL("images/btn-radio-hover.png");
            }
            this.firstRunLabel.setStyle($htv.Styles.SubscribeTextFocused);
        } else {
            this.leftBracket.move({
                x: this.x + 353,
                y: (this.hideEpisodes ? this.y + 180 : this.y + 242),
                z: this.z,
                width: 6,
                height: 35
            });
            this.rightBracket.move({
                x: this.x + 582,
                y: (this.hideEpisodes ? this.y + 180 : this.y + 242),
                z: this.z,
                width: 6,
                height: 35
            });
            this.leftBracket.show();
            this.rightBracket.show();
            if (this.subscriptionState.clips !== "none") {
                this.clipsCheckbox.setURL("images/checkbox-green-checked.png");
            } else {
                this.clipsCheckbox.setURL("images/checkbox-green.png");
            }
            this.clipsLabel.setStyle($htv.Styles.SubscribeTextFocused);
        }
        
        if (this.selectedLabel === 1 || this.selectedLabel === 2) {
            lbp = this.leftSmallBracket.getPosition();
            rbp = this.rightSmallBracket.getPosition();
        } else {
            lbp = this.leftBracket.getPosition();
            rbp = this.rightBracket.getPosition();
        }
        // NOTE: center spotlight for control instead of for each selected label
        $htv.Platform.updateSpotlight(this.x + this.width / 2, (lbp.y + lbp.height / 2), 2);
    };
    
    this.unfocus = function () {
        this.hasFocus = false;
        this.leftBracket.hide();
        this.rightBracket.hide();
        this.leftSmallBracket.hide();
        this.rightSmallBracket.hide();
        this.episodesLabel.setStyle($htv.Styles.SubscribeTextUnfocused);
        this.clipsLabel.setStyle($htv.Styles.SubscribeTextUnfocused);
        if (this.subscriptionState.episodes !== "none") {
            this.episodesCheckbox.setURL("images/checkbox-checked.png");
        } else {
            this.episodesCheckbox.setURL("images/checkbox.png");   
        }
        if (this.subscriptionState.clips !== "none") {
            this.clipsCheckbox.setURL("images/checkbox-checked.png");
        } else {
            this.clipsCheckbox.setURL("images/checkbox.png");
        }
    };
    
    this.hide = function () {
        this.episodesLabel.hide();
        this.clipsLabel.hide();
        if (this.showImage !== null) {
            this.showImage.hide();
        }
        this.clipsCheckbox.hide();
        this.episodesCheckbox.hide();
        this.allLabel.hide();
        this.firstRunLabel.hide();
        this.firstRunRadioButton.hide();
        this.allRadioButton.hide();
        this.leftBracket.hide();
        this.rightBracket.hide();
        this.leftSmallBracket.hide();
        this.rightSmallBracket.hide();
    };
    
    this.show = function () {
        if (!this.hideEpisodes) {
            this.episodesLabel.show();
            this.allLabel.show();
            this.allRadioButton.show();
            this.firstRunLabel.show();
            this.firstRunRadioButton.show();
            this.episodesCheckbox.show();
        }
        
        this.clipsCheckbox.show();
        this.clipsLabel.show();
        if (this.showImage !== null) {
            this.showImage.show();
        }
        if (this.hasFocus) {
            this.focus();
        }
    };
    
    this.handleEvent = function (eventName, eventData) {
        if (eventName === "USER_INPUT") {
            this.handleInput(eventData);
        } else {
            
        }
    };
    
    this.subscribingComplete = function (result) {
        if (this.selectedLabel === 0) {
            if (this.subscriptionState.episodes === "none") {
                this.subscriptionState.episodes = "all";
            } else {
                this.subscriptionState.episodes = "none";
            }
        } else if (this.selectedLabel === 1) {
            this.subscriptionState.episodes = "all";
        } else if (this.selectedLabel === 2) {
            this.subscriptionState.episodes = "first_run_only";
        } else {
            if (this.subscriptionState.clips === "none") {
                this.subscriptionState.clips = "all";
            }
            else {
                this.subscriptionState.clips = "none";
            }
        }
        this.focus();
    };
    
    this.handleInput = function (eventData) {
        if (!eventData.is_down || eventData.is_hold) {
            return;
        }
        
        switch (eventData.action) {
            
        case "PRESS_OK":
            if (this.selectedLabel === 0) {
                if (this.subscriptionState.episodes === "none") {
                    $htv.Profile.addSubscription(this.show_id, "episodes", this, this.subscribingComplete);
                }
                else {
                    $htv.Profile.removeSubscription(this.show_id, "episodes", this, this.subscribingComplete);
                }
            } else if (this.selectedLabel === 1) {
                if (this.subscriptionState.episodes !== "all") {
                    $htv.Profile.addSubscription(this.show_id, "episodes", this, this.subscribingComplete);
                } 
            } else if (this.selectedLabel === 2) {
                if (this.subscriptionState.episodes !== "first_run_only") {
                    $htv.Profile.addSubscription(this.show_id, "episodes_first_run_only", this, this.subscribingComplete);
                }
            } else if (this.selectedLabel === 3) {
                if (this.subscriptionState.clips === "none") {
                    $htv.Profile.addSubscription(this.show_id, "clips", this, this.subscribingComplete);
                } else {
                    $htv.Profile.removeSubscription(this.show_id, "clips", this, this.subscribingComplete);
                }
            }
            break;
        case "KEY_RETURN":
            this.node.view.fireEvent("LOSING_FOCUS", {
                    nav_dir: "up"
                });
            break;
        case "MOVE_UP":
            if (this.selectedLabel === 0 || this.hideEpisodes) {
                this.node.view.fireEvent("LOSING_FOCUS", {
                    nav_dir: "up"
                });
            } else {
                if (this.selectedLabel === 3 && this.subscriptionState.episodes === "none") {
                    this.selectedLabel = 0;
                }
                else {
                    this.selectedLabel = this.selectedLabel - 1;
                }
                this.focus();
            }
            break;
        case "MOVE_DOWN":
            if (this.hideEpisodes) {
                return;
            } else if (this.selectedLabel === 0 && this.subscriptionState.episodes === "none") {
                this.selectedLabel = 3;
            } else if (this.selectedLabel < 3) {
                this.selectedLabel++;
            }
            this.focus();
            break;
        default:
            
            
            break;
        }
    };
};

$htv.Controls.NextVideoDetails = function () {
    this.height = 0;
    this.width = 0;
    this.x = 0;
    this.y = 0;
    this.z = 0;
    this.node = null;
    this.className = "NextVideoDetails";
    this.visible = false;
    this.showTitleLabel = null;
    this.videoTitleLabel = null;
    this.videoDetailsLabel = null;
    this.videoThumbnail = null;
    this.videoThumbnailBackground = null;
    this.videoData = null;
    this.leftBracket = null;
    this.rightBracket = null;
    this.playArrow = null;
    this.hasFocus = false;
    this.canvas = null;
    
    this.initialize = function (position, target, url, options) {
        this.height = position.height;
        this.width = position.width;
        this.x = position.x;
        this.y = position.y;
        this.z = position.z;
        this.visible = true;
        this.hasFocus = false;
        this.node = target;
        if (options.hasOwnProperty("metadata")) {
            this.videoData = options.metadata;
        }
        this.render();        
    };
    
    this.updateLabels = function () {
        var textDims = null;
        if (this.videoThumbnail !== null) {
            this.videoThumbnail.setURL(this.videoData === null ? null : $htv.Utils.getURLForVideoThumb(this.videoData.content_id, { width: 300, height: 168.75 }));
        }
        if (this.showTitleLabel !== null) {
            this.showTitleLabel.setText(this.videoData === null ? "" : this.videoData.show_name);            
        }
        if (this.videoTitleLabel !== null && this.videoDetailsLabel !== null) {
            this.videoTitleLabel.setText(this.videoData === null ? "" : this.videoData.title);
            textDims = this.videoTitleLabel.getTextDimensions();
            this.videoDetailsLabel.move({
                x: this.x,
                y: this.y + 200 + textDims.textHeight + 5,
                z: this.z,
                width: this.width,
                height: 23
            });
        }
        if (this.videoDetailsLabel !== null) {
            this.videoDetailsLabel.setText($htv.Utils.formatVideoSubtitle(this.videoData)); 
        }
    };
    
    this.render = function () {
        this.leftBracket = $htv.Platform.createImage({
            x: this.x - 25,
            y: this.y,
            z: this.z,
            width: 17,
            height: Math.min(this.height, 169)
        }, "images/bracket_large_left.png", this.canvas);
        this.leftBracket.hide();
        
        this.rightBracket = $htv.Platform.createImage({
            x: this.x + this.width + 8,
            y: this.y,
            z: this.z,
            width: 17,
            height: Math.min(this.height, 169)
        }, "images/bracket_large_right.png", this.canvas);
        this.rightBracket.hide();
        
        this.playArrow = $htv.Platform.createImage({
            x: this.x + this.width / 2 - 53 / 2,
            y: this.y + 168.75 / 2 - 62 / 2,
            z: this.z + 2,
            width: 53,
            height: 62
        }, "images/play-arrow.png", this.canvas);
        this.playArrow.hide();
        
        this.videoThumbnailBackground = $htv.Platform.createBox({
            x: this.x - 2,
            y: this.y - 2,
            z: this.z,
            width: 304,
            height: 172.75
        }, "NextVideoBorder", this.canvas);
        
        this.videoThumbnail = $htv.Platform.createImage({
            x: this.x,
            y: this.y,
            z: this.z + 1,
            width: 300,
            height: 168.75
        }, "", this.canvas, {});
        
        this.showTitleLabel = $htv.Platform.createLabel({
            x: this.x,
            y: this.y + 180,
            z: this.z,
            width: this.width,
            height: 20
        }, "", this.canvas, {styleName: $htv.Styles.NextVideoShow});
        
        this.videoTitleLabel = $htv.Platform.createLabel({
            x: this.x,
            y: this.y + 205,
            z: this.z,
            width: this.width,
            height: 80
        }, "", this.canvas, {styleName: $htv.Styles.NextVideoTitle});
        
        this.videoDetailsLabel = $htv.Platform.createLabel({
            x: this.x,
            y: this.y + 200,
            z: this.z,
            width: this.width,
            height: 23
        }, "", this.canvas, {styleName: $htv.Styles.NextVideoDetails});
        
        this.updateLabels();
        
    };
    
    this.setMetadata = function (newMetadata) {
        this.videoData = newMetadata;
        this.updateLabels();
    };
    
    this.dispose = function () {
        $htv.Platform.deleteItem(this.videoThumbnail);
        $htv.Platform.deleteItem(this.videoThumbnailBackground);
        $htv.Platform.deleteItem(this.showTitleLabel);
        $htv.Platform.deleteItem(this.videoTitleLabel);
        $htv.Platform.deleteItem(this.videoDetailsLabel);
        $htv.Platform.deleteItem(this.leftBracket);
        $htv.Platform.deleteItem(this.rightBracket);
        $htv.Platform.deleteItem(this.playArrow);
        this.visible = false;
    };
    
    this.focus = function () {
        this.hasFocus = true;
        
        if (this.visible) {
            this.leftBracket.show();
            this.rightBracket.show();
            this.playArrow.show();
        }
        
        $htv.Platform.updateSpotlight(this.x + this.width / 2, this.y + this.height / 2 - 10, 1);
    };
    
    this.unfocus = function () {
        this.hasFocus = false;
        this.leftBracket.hide();
        this.rightBracket.hide();
        this.playArrow.hide();
    };
    
    this.hide = function () {
        this.visible = false;
        this.showTitleLabel.hide();
        this.videoTitleLabel.hide();            
        this.videoDetailsLabel.hide();
        this.videoThumbnail.hide();
        this.videoThumbnailBackground.hide();
        this.leftBracket.hide();
        this.rightBracket.hide();
        this.playArrow.hide();
    };
    
    this.show = function () {
        this.visible = true;
        this.showTitleLabel.show();
        this.videoTitleLabel.show();
        this.videoThumbnail.show();
        this.videoDetailsLabel.show();
        this.videoThumbnailBackground.show();
        if (this.hasFocus) {
            this.leftBracket.show();
            this.rightBracket.show();
            this.playArrow.show();
        }
    };

    this.handleEvent = function (eventName, eventData) {
        if (eventName === "USER_INPUT") {
            this.handleInput(eventData);
        } else {
            
        }
    };
    
    this.handleInput = function (eventData) {
        if (!eventData.is_down || eventData.is_hold) {
            return;
        }
        
        switch (eventData.action) {
        case "MOVE_UP":
            this.node.view.fireEvent("LOSING_FOCUS", {nav_dir: "up"});
            break;
        case "MOVE_LEFT":
            this.node.view.fireEvent("LOSING_FOCUS", {nav_dir: "left"});
            break;
        case "MOVE_RIGHT":
            this.node.view.fireEvent("LOSING_FOCUS", {nav_dir: "right"});
            break;
        case "MOVE_DOWN":
            this.node.view.fireEvent("LOSING_FOCUS", {nav_dir: "down"});
            break;
        case "PRESS_OK":
            this.node.view.fireEvent("BUTTON_ACTIVATED", {
                target: this.node,
                text: this.className
            });
            break;
        default:
            
            break;
        }
    };
};

$htv.Controls.ButtonHint = function () {
    this.className = "ButtonHint";
    this.height = 0;
    this.width = 0;
    this.x = 0;
    this.y = 0;
    this.z = 0;
    this.canvas = null;
    this.buttonHintContainer = null;
    this.buttonHintImage = null;
    this.buttonHintTextLeft = null;
    this.buttonHintTextRight = null;
    this.node = null;
    this.button_image_path = null;
    this.prefix_text = null;
    this.postfix_text = null;
    
    this.initialize = function (position, target, url, options) {
        this.height = position.height;
        this.width = position.width;
        this.x = position.x;
        this.y = position.y;
        this.z = position.z;
        this.node = target;
        
        if (options.hasOwnProperty("canvas")) {
            this.canvas = options.canvas;
        }
        
        if (options.hasOwnProperty("button_image_path")) {
            this.button_image_path = options.button_image_path;
        }
        
        if (options.hasOwnProperty("prefix_text")) {
            this.prefix_text = options.prefix_text;
        }
        
        if (options.hasOwnProperty("postfix_text")) {
            this.postfix_text = options.postfix_text;
        }
        
        this.buttonHintContainer = $htv.Platform.createContainer({
            x: this.x,
            y: this.y,
            z: this.z,
            width: this.width,
            height: this.height
        }, this.canvas, {center: true});
        
        if (this.button_image_path !== null) {
            this.buttonHintImage = $htv.Platform.createImage({
                x: 0,
                y: 0,
                z: this.z + 1,
                width: 30,
                height: 30
            }, this.button_image_path, this.canvas);
        }
        
        if (this.prefix_text !== null) {
            this.buttonHintTextLeft = $htv.Platform.createLabel({
                x: 0,
                y: 0,
                z: this.z + 1,
                width: this.width,
                height: 26
            }, this.prefix_text, this.canvas, {
                styleName: $htv.Styles.ButtonHint
            });
        }
        
        if (this.postfix_text !== null) {
            this.buttonHintTextRight = $htv.Platform.createLabel({
                x: 0,
                y: 0,
                z: this.z + 1,
                width: this.width,
                height: 26
            }, this.postfix_text, this.canvas, {
                styleName: $htv.Styles.ButtonHint
            });
        }
        
        if (this.buttonHintTextLeft !== null) {
            this.buttonHintContainer.addItem(this.buttonHintTextLeft);
        }
        if (this.buttonHintImage !== null) {
            this.buttonHintContainer.addItem(this.buttonHintImage);
        }
        if (this.buttonHintTextRight !== null) {
            this.buttonHintContainer.addItem(this.buttonHintTextRight);
        }
    };
    
    this.dispose = function () {
        if (this.buttonHintTextLeft !== null) {
            this.buttonHintContainer.removeItem(this.buttonHintTextLeft);
            $htv.Platform.deleteItem(this.buttonHintTextLeft);
            this.buttonHintTextLeft = null;
        }
        
        if (this.buttonHintImage !== null) {
            this.buttonHintContainer.removeItem(this.buttonHintImage);
            $htv.Platform.deleteItem(this.buttonHintImage);
            this.buttonHintImage = null;
        }
        
        if (this.buttonHintTextRight !== null) {
            this.buttonHintContainer.removeItem(this.buttonHintTextRight);
            $htv.Platform.deleteItem(this.buttonHintTextRight);
            this.buttonHintTextRight = null;
        }
        
        $htv.Platform.deleteItem(this.buttonHintContainer);
        this.buttonHintContainer = null;
    };
    
    this.hide = function () {
        if (this.buttonHintImage !== null) {
            this.buttonHintImage.hide();
        }
        if (this.buttonHintTextLeft !== null) {
            this.buttonHintTextLeft.hide();
        }
        if (this.buttonHintTextRight !== null) {
            this.buttonHintTextRight.hide();
        }
        
        this.buttonHintContainer.hide();
    };
    
    this.show = function () {
        if (this.buttonHintImage !== null) {
            this.buttonHintImage.show();
        }
        if (this.buttonHintTextLeft !== null) {
            this.buttonHintTextLeft.show();
        }
        if (this.buttonHintTextRight !== null) {
            this.buttonHintTextRight.show();
        }
        
        this.buttonHintContainer.show();
    };
    
    this.focus = function () {
        this.node.view.fireEvent("LOSING_FOCUS", {
            nav_dir: "up"
        });
    };
    
    this.unfocus = function () {
        
    };
    
    this.handleEvent = function (eventName, eventData) {
        if (eventName === "USER_INPUT") {
            this.handleInput(eventData);
        } else {
            
        }
    };
    
    this.handleInput = function (eventData) {
        if (!eventData.is_down || eventData.is_hold) {
            return;
        }
        
        switch (eventData.action) {
        case "MOVE_UP":
            this.node.view.fireEvent("LOSING_FOCUS", {
                nav_dir: "up"
            });
            break;
        case "MOVE_LEFT":
            this.node.view.fireEvent("LOSING_FOCUS", {
                nav_dir: "left"
            });
            break;
        case "MOVE_RIGHT":
            this.node.view.fireEvent("LOSING_FOCUS", {
                nav_dir: "right"
            });
            break;
        case "MOVE_DOWN":
            this.node.view.fireEvent("LOSING_FOCUS", {
                nav_dir: "down"
            });
            break;
        case "PRESS_OK":
            this.node.view.fireEvent("MENU_ITEM_ACTIVATED", {
                item: {},
                target: this.node
            });
            break;
        default:
            
            break;
        }
    };
};

$htv.Controls.AlertDialogControl = function () {
    this.alertDialogVeil = null;
    this.alertDialogVeilPosition = null;
    this.alertDialogTitle = null;
    this.alertDialogTitlePosition = null;
    this.alertDialogBoxOuter = null;
    this.alertDialogBoxInner = null;
    this.alertDialogBoxOuterPosition = null;
    this.alertDialogBoxInnerPosition = null;
    this.alertDialogText = null;
    this.alertDialogButton = null;
    
    this.node = null;
    
    this.title = null;
    this.text = null;
    
    
    this.initialize = function (position, target, options) {
    // pass in current view and.. z?
        this.title = "DEFAULT TITLE";
        this.text = "Sed justo dui, placerat eget vestibulum ut, tristique vestibulum risus. Donec cursus eros at tellus aliquam ut pulvinar elit dignissim. Nunc interdum, dui vel commodo molestie, enim arcu luctus arcu.";
        
        if (options !== undefined) {
            if (options.title !== undefined) {
                this.title = options.title;
            }
            
            if (options.text !== undefined) {
                this.text = options.text;
            }    
        }
    
        this.node = target;
    
        this.alertDialogVeilPosition = {
            x: 0,
            y: 0,
            z: 5, // over top of all existing UI elements
            width: 960,
            height: 540
        };

        this.alertDialogBoxOuterPosition = {
            x: this.alertDialogVeilPosition.x + 285,
            y: this.alertDialogVeilPosition.y + 108,
            z: this.alertDialogVeilPosition.z + 1,
            width: 390,
            height: 330
        };
        
        this.alertDialogBoxInnerPosition = {
            x: this.alertDialogBoxOuterPosition.x + 1,
            y: this.alertDialogBoxOuterPosition.y + 1,
            z: this.alertDialogBoxOuterPosition.z + 1,
            width: this.alertDialogBoxOuterPosition.width - 2,
            height: this.alertDialogBoxOuterPosition.height - 2
        };
        
        this.alertDialogTitlePosition = {
            x: this.alertDialogBoxOuterPosition.x,
            y: this.alertDialogBoxOuterPosition.y + 25,
            z: this.alertDialogBoxInnerPosition.z + 1,
            width: this.alertDialogBoxInnerPosition.width,
            height: 50
        };
        
        this.alertDialogTextPosition = {
            x: this.alertDialogBoxOuterPosition.x + 30,
            y: this.alertDialogBoxOuterPosition.y + 75,
            z: this.alertDialogBoxInnerPosition.z + 1,
            width: this.alertDialogBoxInnerPosition.width - 60,
            height: 170
        };
        
        
        this.alertDialogButton = {
            view: this.node.view,
            type: "ButtonControl",
            position: {
                x: this.alertDialogBoxOuterPosition.x + this.alertDialogBoxOuterPosition.width / 2 - 100,
                y: this.alertDialogBoxOuterPosition.y + this.alertDialogBoxOuterPosition.height - 60,
                z: this.alertDialogBoxInnerPosition.z + 1,
                width: 200,
                height: 29
            },
            
            control: null
        };
        
        this.alertDialogVeil = $htv.Platform.createBox(this.alertDialogVeilPosition, "AlertDialogVeil", this.canvas);
        this.alertDialogBoxOuter = $htv.Platform.createBox(this.alertDialogBoxOuterPosition, "AlertDialogBoxOuter", this.canvas);
        this.alertDialogBoxInner = $htv.Platform.createBox(this.alertDialogBoxInnerPosition, "AlertDialogBoxInner", this.canvas);
        this.alertDialogTitle = $htv.Platform.createLabel(this.alertDialogTitlePosition, this.title, this.canvas, {styleName: $htv.Styles.DialogBoxTitle});
        this.alertDialogText = $htv.Platform.createLabel(this.alertDialogTextPosition, this.text, this.canvas, {styleName: $htv.Styles.WebOnlyText});
        this.alertDialogButton.control = $htv.ControlPool.getObject("ButtonControl");
        this.alertDialogButton.control.initialize(this.alertDialogButton.position, this.alertDialogButton, null, {
            text: "Close",
            focused_style: $htv.Styles.DialogBoxButtonFocused,
            unfocused_style: $htv.Styles.DialogBoxButtonUnfocused,
            focused_image: "images/btn-preview-marketing-back.jpg",
            unfocused_image: "images/btn-preview-marketing-back.jpg",
            include_brackets: true
        });
    
    };
    
    this.show = function (text, title) {
        this.alertDialogVeil.show();
        this.alertDialogBoxOuter.show();
        this.alertDialogBoxInner.show();
        
        if (title !== undefined) {
            this.alertDialogTitle.setText(title);
        } else {
            this.alertDialogTitle.show();
        }
        
        if (text !== undefined) {
            this.alertDialogText.setText(text);
        } else {
            this.alertDialogText.show();
        }
        
        this.alertDialogText.show();
        this.alertDialogButton.control.show();
        this.alertDialogButton.control.focus();
    };
    
    this.hide = function () {
        this.alertDialogVeil.hide();
        this.alertDialogBoxOuter.hide();
        this.alertDialogBoxInner.hide();
        this.alertDialogTitle.hide();
        this.alertDialogText.hide();
        this.alertDialogButton.control.hide();
        
        this.alertDialogButton.control.unfocus();
    };
    
    this.focus = function () {
        this.alertDialogButton.control.focus();
    };
    
    this.unfocus = function () {
    
    };
    
    this.dispose = function () {
        $htv.Platform.deleteItem(this.alertDialogVeil);
        $htv.Platform.deleteItem(this.alertDialogBoxOuter);
        $htv.Platform.deleteItem(this.alertDialogBoxInner);
        $htv.Platform.deleteItem(this.alertDialogTitle);
        $htv.Platform.deleteItem(this.alertDialogText);
        $htv.Platform.deleteItem(this.alertDialogButton.control);
        
        this.alertDialogVeil = null;
        this.alertDialogVeilPosition = null;
        this.alertDialogTitle = null;
        this.alertDialogTitlePosition = null;
        this.alertDialogBoxOuter = null;
        this.alertDialogBoxInner = null;
        this.alertDialogBoxOuterPosition = null;
        this.alertDialogBoxInnerPosition = null;
        this.alertDialogText = null;
        this.alertDialogButton = null;
    
    };
    
    
    this.handleEvent = function (eventName, eventData) {
        this.alertDialogButton.control.handleEvent(eventName, eventData);
    };
};