/// <reference path="../../ScriptReference/jquery-1.5.2.js" />
/// <reference path="../../Scripts/jquery.enableTouch.js"/>
/// <reference path="../../Scripts/Mediasite.Core.js"/>
/// <reference path="../../Scripts/Mediasite.Geometry.js"/>
/// <reference path="../../Scripts/Mediasite.Player.Core.js"/>
/// <reference path="../../Scripts/Mediasite.Player.Localization.js"/>
/// <reference path="../../Scripts/SlideNav.js"/>
/// <reference path="../../Scripts/SlideInspector.js"/>
/// <reference path="../../Scripts/SpriteAnimation.js"/>
/*global Mediasite*/

Mediasite.namespace("Player");


// NewStandardView
// +===========================================================================
Mediasite.Player.NewStandardView = function () {

    //UpdateMediaInfo: function (mediaInfo) { },
    //UpdateMediaState: function (state) { },
    //UpdateMediaVolume: function (volume) { },
    //UpdatePlaybackRate: function (rateInfo) { },
    //UpdateOptions: function (options) { },
    //UpdateSlideBrowserView: function (view) { },      
    //InactivityExceeded: function () { },
    //SendQuestionComplete: function (success, message) { },
    //SendEmailComplete: function (success, message) { },
    //ToggleSlideText: function () { },
    //ToggleSlideBrowser: function () { },

    var selectors = {
        titleArea: '#titleArea',
        contentArea: '#contentArea',
        slideBox: '.stage-slideBox',
        slideInspector: '#inspector',
        slidePreview: '#slidePreview',
        videoBox: '.stage-videoBox',
        videoThumbContainer: '#videoThumbContainer',
        contentFramer: '.contentFramer',
        positionSlider: '#positionSlider',
        positionSliderHandle: '#positionSlider .ui-slider-handle',
        currentPosition: '#currentPosition',
        livePosition: '#live-position-text',
        duration: '#duration',
        controlBar: '#control-bar',
        controlsMiddle: '#controls-middle',
        controlsLeft: '#controls-left',
        controlsRight: '#controls-right',
        controlBarButtons: '#control-bar button',
        playPauseButton: '#playPauseButton',
        playStopButton: '#playStopButton',
        skipBackButton: '#skipBackButton',
        mediasiteSwirlButton: '#mediasite-swirl a',
        layoutButtons: '.stage-layoutControls button',
        pipButton: '.stage-pipButton',
        sideBySideButton: '.stage-sideBySideButton',
        fullFrameButton: '.stage-fullFrameButton',
        captionButton: '#captionButton',
        captionSearchButton: '#captionSearchButton',
        volumeButton: '#volumeButton',
        pollsButton: '#pollsButton',
        askButton: '#askButton',
        emailButton: '#emailButton',
        linksButton: '#linksButton',
        chaptersButton: '#chaptersButton',
        swapButton: '.stage-swapButton',
        infoPanel: '#infoPanel',
        captionPanel: '#captionPanel',
        captionSearchPanel: '#captionSearchPanel',
        askPanel: '#askPanel',
        emailPanel: '#emailPanel',
        linksPanel: '#linksPanel',
        chaptersPanel: '#chaptersPanel',
        infoButton: '#infoButton',
        presentationTitle: '#presentationTitle',
        closeDetailPanelButton: '#detailPanels .closePanelButton',
        closeInteractivityPanelButton: '#interactivityPanels .closePanelButton',
        helpButton: '#helpButton',
        mediaStateText: '.mediaState p',
        mediaStateDiv: '#mediaState',
        mediaStateStandalone: '#mediaStateStandalone',
        speedButton: '#playSpeedButton',
        buttonDivider: '#buttonDivider',
        broadcastingIndicator: '#broadcasting-indicator',
        volume: '#volumeButton',
        muteWrapper: '#ui-playervolume-mute-wrapper',
        unmuteWrapper: '#ui-playervolume-unmute-wrapper',
        volumeSlider: '#ui-playervolume-slider',
        panelStylesheet: 'link#panelStylesheet'
    };

    var classes = {
        popup: 'popupPanel'
    };

    var detailPanels = {
        None: 'None',
        Info: 'Info',
        Caption: 'Caption',
        Search: 'Search'
    };

    var interactivityPanels = {
        None: 'None',
        Polls: 'Polls',
        Ask: 'Ask',
        Email: 'Email',
        Links: 'Links'
    };

    var htmlElement = {
        Input: 'INPUT',
        Textarea: 'TEXTAREA'
    };

    var _presentation;
    var _slidePartitions;
    var _currentSlide;
    var _currentPosition;
    var _mediaState;
    var pollsWindow;
    var stage, slideNav, slideInspector, slidePreview, slidePreviewAnimation, broadcastingIndicator;
    var mediaDuration = 0;
    var positionChanging;
    var _currentDetailPanel = detailPanels.None;
    var _currentInteractivityPanel = interactivityPanels.None;
    var isCCHidden = true;
    var fadeSpeed = 'normal';
    var helpWindow;
    var _defaultAspect = 4 / 3;
    var _isIOS = Mediasite.BrowserDetect.IOS();
    var _isIOS5 = Mediasite.BrowserDetect.IOS5();
    var _isAndroid = Mediasite.BrowserDetect.Android();
    var _usePopupPanels = !!_isAndroid;  // Put interactivity panels in a new window
    var _currentPopupWindow = null;
    var _livePresentationHasEnded = false;

    var notifier = new Mediasite.Player.ViewEventNotifier();


    // Default Values for Player Options
    setOptionDefault('SlideAspect', '4:3');
    setOptionDefault('VideoAspect', '4:3');
    setOptionDefault('EnablePresentationInfo', true);
    setOptionDefault('EnableSofoBranding', true);
    setOptionDefault('AllowLayoutAdjustment', true);
    setOptionDefault('ShowSlideNavigation', true);
    setOptionDefault('EnableSearch', true);


    this.AddListener = function (list) {
        notifier.AddListener(list);
    };

    function setOptionDefault(optionKey, defaultValue) {
        var value = Mediasite.PlayerLayoutOptions[optionKey];
        if (typeof value === 'undefined' || typeof value === 'null') {
            Mediasite.PlayerLayoutOptions[optionKey] = defaultValue;
        }
    }

    function getAspectRatio(aspectString) {
        var components = aspectString.split(':');
        if (components.length === 2) {
            return parseInt(components[0], 10) / parseInt(components[1], 10);
        }

        return _defaultAspect; // parse error
    }

    this.LoadLayout = function () {
        jQuery.fx.interval = _isIOS ? 50 : jQuery.fx.interval; // the default 13ms is way too quick for some devices.

        stage = new Mediasite.Player.StageControl(selectors.contentArea, selectors.slideBox, selectors.videoBox, selectors.slidePreview);
        stage.setLayoutType(getStageLayoutTypeForInitialLayoutOption(Mediasite.PlayerLayoutOptions.FullInitialLayout));
        stage.setSlideAspect(getAspectRatio(Mediasite.PlayerLayoutOptions.SlideAspect));
        stage.setVideoAspect(getAspectRatio(Mediasite.PlayerLayoutOptions.VideoAspect));
        stage.setPrimaryContentElement(Mediasite.PlayerLayoutOptions.PrimaryContent);
        stage.setVideoSide(Mediasite.PlayerLayoutOptions.VideoPosition);

        slideNav = new Mediasite.Player.SlideNav($('#slide-navigator'), function (number, width, height) {
            if (!_presentation) {
                return null;
            }

            var aspect = (height > 0) ? width / height : 4 / 3;

            return _presentation.GetCacheFriendlySlideUrl(number, height, aspect);
        });
        slideNav.getElement().bind({
            'seek': function (e, data) { notifier.OnPositionChanged(data.position); },
            'beginPreview': slideNav_beginPreview,
            'endPreview': slideNav_endPreview
        });
        slideNav.getElement().enableTouch();

        slideInspector = new Mediasite.Player.SlideInspector($(selectors.slideInspector));




        slidePreview = new Mediasite.Player.SlidePreviewControl($(selectors.slidePreview));
        slidePreview.getElement().bind('slidePreviewInitiated', slidePreview_slidePreviewInitiated);

        slidePreviewAnimation = new Mediasite.Player.SlidePreviewAnimation($('body'));

        broadcastingIndicator = new Mediasite.SpriteAnimation($(selectors.broadcastingIndicator), { spriteWidth: 32, totalFrames: 5, frameDuration: 750 });

        $(selectors.infoPanel).hide();
        $(selectors.captionSearchPanel).hide();
        $(selectors.askPanel).hide();
        $(selectors.emailPanel).hide();
        $(selectors.linksPanel).hide();
        $(selectors.chaptersPanel).hide();

        var makeFramePart = function (cssClass) {
            return $('<div />').addClass(cssClass);
        };

        // Add borders to slide and video areas.
        $(selectors.contentFramer).append(makeFramePart('left')).append(makeFramePart('top')).append(makeFramePart('right')).append(makeFramePart('bottom'));


        // When stage size changes, inform children
        $(selectors.contentArea).bind('stageresize', function (evt) {
            evt.stopPropagation();

            $(selectors.slideInspector).trigger('containerresize');
        });

        updateLayout();
        $(window).resize(updateLayout);
        if (_usePopupPanels) {
            $(window).bind('beforeunload', clearInteractivityPopupWindow);
        }


        // setup position slider
        $(selectors.positionSlider).slider({
            range: 'min',
            min: 0,
            max: 10000,
            step: 1,
            start: function (event, ui) {
                positionChanging = true;
            },
            slide: function (event, ui) {
                updatePositionText(getMediaDuration() * (ui.value / 10000));
            },
            stop: function (event, ui) {
                positionChanging = false;
                notifier.OnPositionChanged(getMediaDuration() * (ui.value / 10000));
            }
        }).enableTouch();
        $(selectors.positionSliderHandle).append('<div id="currentPosition">00:00:00</div>');
        increaseSliderToucharea();

        $(selectors.speedButton).playerspeed({ notifier: notifier });
        $(selectors.volumeButton).playervolume({ notifier: notifier });

        setBroadcastingIndicatorTooltip(Mediasite.Player.Localization.LiveIndicator.WaitingTooltip);

        ///////////Hacking for iOS (touch) devices.  When iOS disable controls///////////
        if (_isIOS || _isAndroid) {
            setTouchLayout();
        }
        ///////////Fix me!!!//////////////////////////

        //$('#skipBackButton').imageButton('disable');
        //$('#infoButton').imageButton('disable');
        //$('#captionsButton').imageButton('disable');
        //$('#linksButton').imageButton('disable');       

        updateLayout();


        if (Mediasite.PlayerLayoutOptions.Images && Mediasite.PlayerLayoutOptions.Images.VideoThumb) {
            var img = $('<img />').attr({
                'src': Mediasite.PlayerLayoutOptions.Images.VideoThumb.ImageFilename,
                'alt': '' // TODO: Better alt text?
            });
            $(selectors.videoThumbContainer).empty().append(img);
        }


        notifier.OnLayoutLoaded();

    };

    this.ShowErrorMessage = function (message, details) {

        if (Mediasite.GlobalOptions.ErrorPage && Mediasite.GlobalOptions.ErrorPage.length > 0) {
            var errorPage = Mediasite.GlobalOptions.ErrorPage;
            window.location = errorPage;
        }
        else {

            var container = $('#errorAlertContainer');
            if (container.size() < 1) {
                container = $('<div id="errorAlertContainer"></div>').appendTo($('body'));
            }

            var numExistingAlerts = $('.errorAlert', container).size();
            var offset = (numExistingAlerts % 3) * 10;

            var alert = $('<div class="errorAlert"><h1></h1><div></div><button></button></div>')
                .css({
                    'margin-left': offset + 'px',
                    'margin-top': offset + 'px'
                })
                .appendTo(container);

            $('h1', alert).text(Mediasite.Player.Localization.Common.GeneralErrorTitle);
            $('div', alert)
                .append($('<p></p>').text(message))
                .append($('<p></p>').text(details));
            $('button', alert)
                .text(Mediasite.Player.Localization.Common.OK)
                .click(function () { alert.remove(); });
        }
    };

    this.UpdatePresentationData = function (modelPresentation) {
        _presentation = modelPresentation;

        slidePreview.setSlideUrlProvider(_presentation);

        setupButtons();
        updateLayoutButtonStates();
        updateBodyClasses();
        updateLayout();

        $(selectors.infoPanel).playerinfopanel({ presentation: _presentation, onChapterChanged: notifier.OnChapterChanged, defaultPresenterImageSrc: Mediasite.PlayerLayoutOptions.Images.DefaultPresenterImage ? Mediasite.PlayerLayoutOptions.Images.DefaultPresenterImage.ImageFilename : '' });
        $(selectors.captionSearchPanel).playerccsearchpanel({ presentation: _presentation, notifier: notifier, onCaptionClick: onCaptionClick });
        $(selectors.captionPanel).playercaptionpanel({ presentation: _presentation });
        $(selectors.chaptersPanel).playerchapterspanel({ chapters: _presentation.Chapters, onChapterChanged: notifier.OnChapterChanged });
        $(selectors.linksPanel).playerlinkspanel({ links: _presentation.Links });

        fixSlideTitles();

        _slidePartitions = new Mediasite.Player.SlidePartitions(_presentation.Slides);
        _slidePartitions.bind('currentpagechanged', slidePartitions_currentpagechanged);
        slideNav.setSlides(_slidePartitions.getCurrentPageItems());

        if (Mediasite.PlayerLayoutOptions.Images && Mediasite.PlayerLayoutOptions.Images.FullScreenBanner) {
            var titleArea = $(selectors.titleArea);
            titleArea.css({
                "background-image": "url('" + Mediasite.PlayerLayoutOptions.Images.FullScreenBanner.ImageFilename + "')",
                "alt": _presentation.Title,
                "title": _presentation.Title
            });
            if (Mediasite.PlayerLayoutOptions.Images.FullScreenBanner.ImageUrl != "") {
                imageAnchor = $(document.createElement('a'));
                imageAnchor.attr("href", Mediasite.PlayerLayoutOptions.Images.FullScreenBanner.ImageUrl);
                imageAnchor.attr("title", Mediasite.PlayerLayoutOptions.Images.FullScreenBanner.ImageUrl);
                imageAnchor.hover(
                  function () {
                      titleArea.css('filter', 'alpha(opacity=100)');
                      titleArea.css('opacity', '1.0');
                  },
                  function () {
                      titleArea.css('filter', 'alpha(opacity=80)');
                      titleArea.css('opacity', '0.8');
                  }
                );
                imageAnchor.css({
                    "display": "block",
                    "width": Mediasite.PlayerLayoutOptions.Images.FullScreenBanner.Width,
                    "height": Mediasite.PlayerLayoutOptions.Images.FullScreenBanner.Height,
                    "margin": "0 auto"
                });
                imageAnchor.appendTo(titleArea);
            }
        }

        if (_presentation.PlayStatus !== Mediasite.Player.PresentationStatus.OnDemand || Mediasite.BrowserDetect.Mobile()) {
            //$(selectors.speedButton).imageButton('disable');
            $(selectors.speedButton).hide();
        }



        var isSomeKindOfLive = (_presentation.PlayStatus !== Mediasite.Player.PresentationStatus.OnDemand &&
        _presentation.PlayStatus !== Mediasite.Player.PresentationStatus.NotAvailable);

        if (isSomeKindOfLive) {

        }

        //        switch (_presentation) {
        //            case Mediasite.Player.PresentationStatus.NotAvailable:
        //            case Mediasite.Player.PresentationStatus.ScheduledForLive:
        //            case Mediasite.Player.PresentationStatus.OpenForLive:
        //            case Mediasite.Player.PresentationStatus.Live:
        //            case Mediasite.Player.PresentationStatus.LivePaused:
        //            case Mediasite.Player.PresentationStatus.LiveEnded:
        //            case Mediasite.Player.PresentationStatus.OnDemand:
        //            default:
        //        }

        if (Mediasite.PlayerLayoutOptions.Images) {

            if (_presentation.PlayStatus === Mediasite.Player.PresentationStatus.ScheduledForLive ||
            _presentation.PlayStatus === Mediasite.Player.PresentationStatus.OpenForLive) {

                showOptionImageAsSlide(Mediasite.PlayerLayoutOptions.Images.WaitingForPresentationSlide);
            }
        }


        $(document).bind("keyup", function (event) {
            if (event.target.tagName !== htmlElement.Input && event.target.tagName !== htmlElement.Textarea) {
                notifier.OnKeyCommand(event);
            }
        });
    };

    this.UpdateCurrentSlide = function (slide) {
        _currentSlide = slide;

        if (slide.Number < 1) {
            if (Mediasite.PlayerLayoutOptions.Images && Mediasite.PlayerLayoutOptions.Images.DefaultSlide) {
                showOptionImageAsSlide(Mediasite.PlayerLayoutOptions.Images.DefaultSlide);
            }
            return;
        }

        var slideImage = new Mediasite.Player.SlideImage(slide.Number, _presentation);
        var tooltip = (slide.Text != "") ? slide.Text : Mediasite.Player.Localization.Common.Slide + " " + slide.Number;

        showSlide(slideImage, '', tooltip);
    };

    this.UpdatePosition = function (position) {
        if (!positionChanging) {
            updatePositionText(position);
            _currentPosition = position;

            setMediaDuration(position);

            if (getMediaDuration() > 0) {
                $(selectors.positionSlider).slider('option', 'value', position / getMediaDuration() * 10000);
            }
        }

        if (getMediaDuration() > 0) {
            slideNav.setNormalizedPosition(position / getMediaDuration());
        }

        if (isOnDemand() && (getMediaDuration() > 0) && (_currentPosition >= getMediaDuration())) {
            ShowPresentationEndedState();
        }
    };

    function ShowPresentationEndedState() {
        setBroadcastingIndicatorTooltip(Mediasite.Player.Localization.LiveIndicator.EndedTooltip);
        showOptionImageAsSlide(Mediasite.PlayerLayoutOptions.Images.PresentationEndedSlide);

        if (_presentation.PlayStatus != Mediasite.Player.PresentationStatus.OnDemand) {
            _livePresentationHasEnded = true;
        }
    }

    function isOnDemand() {
        return _presentation.PlayStatus === Mediasite.Player.PresentationStatus.OnDemand;
    }

    this.UpdateMediaInfo = function (mediaInfo) {
        setMediaDuration(mediaInfo.Duration);
        slideNav.setDuration(getMediaDuration());
        var durationString = getDisplayFromDuration(getMediaDuration(), true);
        $(selectors.duration).text(durationString);
        if (mediaInfo.AudioOnly) {
            setStageLayoutType(Mediasite.Player.StageLayoutType.PrimaryOnly);
            $(selectors.layoutButtons).hide();
        }

        if (Mediasite.PlaybackManifest.Slides.length == 0 && isOnDemand()) {
            stage.setPrimaryContentElement(Mediasite.Player.StageContentElement.Video);
            setStageLayoutType(Mediasite.Player.StageLayoutType.PrimaryOnly);

            $(selectors.layoutButtons).hide();
        }
    };

    this.UpdateMediaState = function (state) {
        hideVideoThumb();

        var mediaStateText = (state === Mediasite.Player.MediaState.Undefined) ? '' : Mediasite.Player.MediaState.GetDisplayName(state);
        $(selectors.mediaStateText).text(mediaStateText);

        var $mediaState = isVideoBoxShowing() ? $(selectors.mediaStateDiv) : $(selectors.mediaStateStandalone);
        if (state === Mediasite.Player.MediaState.Playing || state === Mediasite.Player.MediaState.Undefined) {
            $mediaState.stop(true, true).fadeOut(fadeSpeed);
        } else {
            $mediaState.stop(true, true).fadeIn(fadeSpeed);
        }

        $(selectors.playPauseButton).attr('disabled', false);
        $(selectors.playStopButton).attr('disabled', false);

        switch (state) {
            case Mediasite.Player.MediaState.Playing:
                togglePlayButton(false);
                break;
            case Mediasite.Player.MediaState.Paused:
            case Mediasite.Player.MediaState.Stopped:
            case Mediasite.Player.MediaState.MediaEnded:
                togglePlayButton(true);
                break;
            default:
                break;
        }

        if (state === Mediasite.Player.MediaState.MediaEnded && isOnDemand()) {
            // We can't trust MediaEnded during a live broadcast.
            ShowPresentationEndedState();
        }

        _mediaState = state;
        updateBroadcastingIndicator();
    };

    this.ShowHelp = function () {
        if (!helpWindow || helpWindow.closed) {
            var sep = Mediasite.GlobalOptions.AppRoot.length > 0 ? "/" : "";
            var url = Mediasite.GlobalOptions.AppRoot + sep + "Help/Mediasite/OverviewFullVersion.htm";
            helpWindow = createPopup(url, "Help", 800, 600, true, true);
        }
    };

    this.ShowPolls = function () {
        if (!_presentation.PollingEnabled || _presentation.IsStandAlone) {
            return;
        }

        if (!pollsWindow || pollsWindow.closed) {
            pollsWindow = createPopup(_presentation.PollingLocation, "Polls", 600, 450, true, false);
        }
    };

    this.ShowAskQuestionForm = function () {
        if (!_presentation.ForumEnabled || _presentation.IsStandAlone) {
            return;
        }

        toggleInteractivityPanel(interactivityPanels.Ask);

        if (_currentDetailPanel !== interactivityPanels.Ask) {
            $(selectors.askPanel).playeraskpanel({ presentation: _presentation, notifier: notifier, currentPosition: _currentPosition, labelMargin: 50, message: { cols: 30, rows: 8 }, dismissFunction: dismissInteractivityPanel });
        }
    };

    this.SendQuestionComplete = function (success, message) {
        //we do not want to hide the panel if successful. dialog should close it out when clicking OK
        //        if (success) {
        //            toggleInteractivityPanel(interactivityPanels.None);
        //        }
        $(selectors.askPanel).playeraskpanel('sendQuestionComplete', success, message);
    };

    this.UpdateEmailInvite = function (emailData) {
        if (!_presentation.SharingEnabled) {
            return;
        }
        //emailData.UseServerForSMTP = true; ///////////////////////////////////////////////////////////remove me!
        if (emailData.UseServerForSMTP) {
            toggleInteractivityPanel(interactivityPanels.Email);
        }

        var $invitePanel = $(selectors.emailPanel);
        $invitePanel.playerinvitepanel({ presentation: _presentation, notifier: notifier, currentPosition: _currentPosition, labelMargin: 50, message: { cols: 30, rows: 12 }, url: window.location.href, dismissFunction: dismissInteractivityPanel });
        $invitePanel.playerinvitepanel('updateEmailInvite', emailData);
    };

    this.SendEmailComplete = function (success, message) {
        $(selectors.emailPanel).playerinvitepanel('sendInviteComplete', success, message);
    };

    this.ShowLinks = function () {

        if (_presentation.Links.length > 0) {
            toggleInteractivityPanel(interactivityPanels.Links);
        }
    };

    this.ShowChapters = function () {

        if (_presentation.Chapters.length > 0) {
            toggleInteractivityPanel(interactivityPanels.Chapters);
        }
    };

    this.ShowInfo = function () {
        var showing = _currentDetailPanel !== detailPanels.Info;
        toggleDetailPanel(detailPanels.Info);

        if (showing) {
            $(selectors.infoPanel).playerinfopanel('updateLayout');
        }
    };

    this.ToggleCaptionSearch = function () {
        if (!maySearch()) {
            return;
        }

        var $captionSearchButton = $(selectors.captionSearchButton);
        var showing = _currentDetailPanel !== detailPanels.Search;

        toggleDetailPanel(detailPanels.Search);
        if (showing) {
            $(selectors.captionSearchPanel).playerccsearchpanel('updateLayout');
        }
    };

    this.ToggleCaptionDisplay = function () {
        if (!_presentation.HasCaptions) {
            return;
        }

        var $captionPanel = $(selectors.captionPanel);
        var $ccButton = $(selectors.captionButton);
        $captionPanel.playercaptionpanel('toggleVisibility');
        if (isCCHidden) {
            $captionPanel.playercaptionpanel('show');
            $ccButton.attr({ title: Mediasite.Player.Localization.Buttons.HideCaptioning });
            isCCHidden = false;
        }
        else {
            $captionPanel.playercaptionpanel('hide');
            $ccButton.attr({ title: Mediasite.Player.Localization.Buttons.ShowCaptioning });
            isCCHidden = true;
        }
    };

    this.DisplaySearchTextResults = function (searchTerm, results) {
        var $captionPanel = $(selectors.captionSearchPanel);
        $captionPanel.playerccsearchpanel('displayResults', searchTerm, results);
    };

    this.UpdateCurrentCaption = function (caption) {
        $(selectors.captionPanel).playercaptionpanel('updateCaption', caption);
    };

    this.LiveStatusChange = function (status) {
        //alert(status);
        switch (status) {
            case Mediasite.Player.PresentationStatus.Live:
                setBroadcastingIndicatorTooltip(Mediasite.Player.Localization.LiveIndicator.LiveTooltip);
                if (!_currentSlide || _currentSlide.Number < 1) {
                    showOptionImageAsSlide(Mediasite.PlayerLayoutOptions.Images.DefaultSlide);
                }
                break;
            case Mediasite.Player.PresentationStatus.LivePaused:
                setBroadcastingIndicatorTooltip(Mediasite.Player.Localization.LiveIndicator.PausedTooltip);
                break;
            case Mediasite.Player.PresentationStatus.LiveEnded:
                ShowPresentationEndedState();
                break;
            default:
                break;
        }
    };

    this.AddNewSlide = function (slide) {
        // TODO: Hide default slide

        setMediaDuration(slide.Time);

        if (slide.Text == "" && slide.Number > 0) {
            slide.Text = Mediasite.Player.Localization.NewStandardPlayer.DefaultSlideTitleFormat.replaceholders(slide.Number);
        }

        this.UpdateCurrentSlide(slide);

        _slidePartitions = new Mediasite.Player.SlidePartitions(_presentation.Slides);
        _slidePartitions.bind('currentpagechanged', slidePartitions_currentpagechanged);
        slideNav.setSlides(_slidePartitions.getCurrentPageItems());

        slideNav.setDuration(slide.Time); // Let's be clever and pin the last slide at 100% duration.
        slideNav.setNormalizedPosition(1.0);
    };



    function setBroadcastingIndicatorTooltip(text) {
        $(selectors.broadcastingIndicator).attr('title', text);
    }

    function getGreatestSlideTime() {
        if (!_presentation || !_presentation.Slides || _presentation.Slides.length < 1) {
            return 0;
        }

        return _presentation.Slides[_presentation.Slides.length - 1].Time;
    }

    function getMediaDuration() {
        return mediaDuration;
    }
    function setMediaDuration(position) {
        if (position == Infinity) {
            // infinity is worthless as a duration. 
            // Use the greatest slide time instead.
            position = getGreatestSlideTime();
        }

        // The duration should never shrink during playback.
        // During live, we need to continuously extend the duration to 
        // include the current position and slide times.
        mediaDuration = Math.max(mediaDuration, position);

        // The duration displayed in the info panel is a different beast.
        // For a live presentation, the true duration can significantly 
        // exceed the duration delivered by the manifest. If the media 
        // duration grows beyond the configured presentation duration, 
        // show the greater one.
        $(selectors.infoPanel).playerinfopanel('updateDuration', Math.max(_presentation.Duration, mediaDuration));
    }

    function fixSlideTitles() {
        var i;
        for (i = 0; i < _presentation.Slides.length; i++) {
            var slide = _presentation.Slides[i];
            if (slide.Text == "") {
                slide.Text = Mediasite.Player.Localization.NewStandardPlayer.DefaultSlideTitleFormat.replaceholders(i + 1);
            }
        }
    }

    this.UpdatePlaybackRate = function (rateInfo) {
        $(selectors.speedButton).playerspeed("setPlaybackRate", rateInfo.Current);
    }

    function getStageLayoutTypeForInitialLayoutOption(optionValue) {
        var slt = Mediasite.Player.StageLayoutType;

        switch (optionValue) {
            case 'SlideOnly':
                return slt.PrimaryOnly;
            case 'PictureInPicture':
                return slt.PictureInPicture;
            default:
                return slt.SideBySide;
        }
    }

    function showSlide(slideImage, link, tooltip) {
        if (_livePresentationHasEnded) {
            return;
        }

        slideInspector.setSlideImage(slideImage);
        slideInspector.setSlideToolTip(tooltip);

        // In some browsers (ahem... Chrome), the fact that the contentFramer box 
        // is above the slideInspector box can hide the slideInspector's tooltip. 
        // If the tooltip applied to the slideBox which wraps them both, the 
        // tooltip shows up when hovering over the zoom in/out buttons. 
        // So... apply the tooltip to the contentFramer box.
        $('.contentFramer', $(selectors.slideBox)).attr('title', tooltip);

        // TODO: slideInspector.setSlideLinkUrl(link);
    }

    function showOptionImageAsSlide(optionImage) {
        if (!optionImage) {
            optionImage = { ImageFilename: '', ImageUrl: '' };
        }

        showSlide(new SpecialSlideImage(optionImage.ImageFilename), optionImage.ImageUrl, Mediasite.Player.Localization.CurrentSlide.SlideImage);
    }

    function updateBroadcastingIndicator() {
        if (!_mediaState || !_presentation || !_presentation.PlayStatus) {
            return;
        }

        if (_mediaState === Mediasite.Player.MediaState.Playing) {
            broadcastingIndicator.Start();
        } else {
            broadcastingIndicator.Stop();
            broadcastingIndicator.Reset();
        }
    }

    function getPanelSelector(panel) {
        switch (panel) {
            case detailPanels.Info:
                return selectors.infoPanel;
            case detailPanels.Caption:
                //return selectors.cap;
            case detailPanels.Search:
                return selectors.captionSearchPanel;
            case interactivityPanels.Ask:
                return selectors.askPanel;
            case interactivityPanels.Email:
                return selectors.emailPanel;
            case interactivityPanels.Links:
                return selectors.linksPanel;
            case interactivityPanels.Chapters:
                return selectors.chaptersPanel;
        }
    }

    function fadePanel(panelSelector, show) {
        if (show) {
            $(panelSelector).stop(true, true).fadeIn(fadeSpeed, function () {
                if (panelSelector && !_isIOS) {
                    // Focus on first form element found
                    $('input, textarea', panelSelector).first().focus();
                }
            });
        } else {
            $(panelSelector).stop(true, true).fadeOut(fadeSpeed);
        }
    }

    ///////////Hacking for iOS (touch) devices.  When iOS, rearrange controls///////////
    function setTouchLayout() {
        $(selectors.speedButton).hide();
        $(selectors.volumeButton).hide();
        $(selectors.buttonDivider + '1').hide();
        $(selectors.captionSearchButton).css("left", "140px");
        $(selectors.captionButton).css("left", "172px");
        $(selectors.controlsMiddle).css("margin", "28px 192px 0px 219px");
    }
    ///////////Fix me!!!//////////////////////////

    //increase slider toucharea for smoother seeking
    function increaseSliderToucharea() {
        var touchAreaInHandle = $(document.createElement('div'));
        touchAreaInHandle.addClass('ui-slider-handle-toucharea');
        touchAreaInHandle.appendTo($('a.ui-slider-handle'));
    }

    function onCaptionClick(position) {
        _currentPosition = position;
        notifier.OnPositionChanged(position);
        $(selectors.mediaStateDiv).hide();
    }

    function createPopup(url, name, width, height, scrollbars, resizeable) {
        width = Math.floor(width);
        height = Math.floor(height);

        var features = "width=" + width + ",height=" + height;

        if (scrollbars) {
            features += ",scrollbars=yes";
        }
        else {
            features += ",scrollbars=no";
        }

        if (resizeable) {
            features += ",resizable=yes";
        }
        else {
            features += ",resizable=no";
        }

        var popup = window.open(url, name, features);

        return popup;
    }

    function togglePlayButton(showPlay) {
        // interpret checked to mean 'is playing'.
        $(selectors.playPauseButton)
		.imageButton('setIsChecked', !showPlay);
        $(selectors.playStopButton)
		.imageButton('setIsChecked', !showPlay);
    }

    function isVideoBoxShowing() {
        var isShowing = false;

        if ($(selectors.videoBox).is(":visible") && $(selectors.videoBox).css('opacity') != 0) {
            isShowing = true;
        }
        return isShowing;
    }

    function setStageLayoutType(layoutType) {
        var showingMediaState = $(selectors.mediaStateDiv).add(selectors.mediaStateStandalone).is(":visible");

        stage.setLayoutType(layoutType);
        updateLayoutButtonStates();

        if (showingMediaState) {
            var $mediaStateShow = $(selectors.mediaStateStandalone);
            var $mediaStateHide = $(selectors.mediaStateDiv);
            if (isVideoBoxShowing()) {
                var temp = $mediaStateShow;
                $mediaStateShow = $mediaStateHide;
                $mediaStateHide = temp;
            }

            $mediaStateShow.show();
            $mediaStateHide.hide();
        }
    }

    function updateLayoutButtonStates() {
        var layoutType = stage.getLayoutType();

        $(selectors.pipButton).imageButton('setIsChecked', layoutType === Mediasite.Player.StageLayoutType.PictureInPicture);
        $(selectors.sideBySideButton).imageButton('setIsChecked', layoutType === Mediasite.Player.StageLayoutType.SideBySide);
        $(selectors.fullFrameButton).imageButton('setIsChecked', layoutType === Mediasite.Player.StageLayoutType.PrimaryOnly);
    }

    function maySearch() {
        return (Mediasite.PlayerLayoutOptions.EnableSearch && (_presentation.HasCaptions || _presentation.SearchPresentationTextOnServer));
    }

    function setupButtons() {
        $(selectors.mediasiteSwirlButton).imageButton();

        $(selectors.playPauseButton)
		.imageButton({ isCheckButton: true, checkedPosition: '0 -381px', normalTitle: Mediasite.Player.Localization.Buttons.Play, checkedTitle: Mediasite.Player.Localization.Buttons.Pause })
		.click(function () {
		    notifier.OnClickCommand(Mediasite.Player.ClickCommand.TogglePlayPause);
		})
        .attr('disabled', true);
        $(selectors.playStopButton)
		.imageButton({ isCheckButton: true, checkedPosition: '0 -681px', normalTitle: Mediasite.Player.Localization.Buttons.Play, checkedTitle: Mediasite.Player.Localization.Buttons.Stop })
		.click(function () {
		    notifier.OnClickCommand(Mediasite.Player.ClickCommand.TogglePlayPause);
		})
        .attr('disabled', true);

        $(selectors.skipBackButton)
		.attr({ title: Mediasite.Player.Localization.Buttons.Skipback })
		.imageButton()
		.click(function () {
		    notifier.OnClickCommand(Mediasite.Player.ClickCommand.SkipBack);
		});
        $(selectors.pipButton)
		.attr({ title: 'Picture in Picture' }) // add to Localization
		.imageButton({ isCheckButton: true, checkedPosition: '-144px -413px' })
		.click(function () {
		    setStageLayoutType(Mediasite.Player.StageLayoutType.PictureInPicture);
		});
        $(selectors.sideBySideButton)
		.attr({ title: 'Side by Side' }) // add to Localization
		.imageButton({ isCheckButton: true, checkedPosition: '-144px -577px' })
		.click(function () {
		    setStageLayoutType(Mediasite.Player.StageLayoutType.SideBySide);
		});
        $(selectors.fullFrameButton)
		.attr({ title: 'Full Frame' }) // add to Localization
		.imageButton({ isCheckButton: true, checkedPosition: '-144px -645px' })
		.click(function () {
		    setStageLayoutType(Mediasite.Player.StageLayoutType.PrimaryOnly);
		});
        $(selectors.swapButton)
		.attr({ title: 'Swap Media Elements' }) // add to Localization
		.imageButton()
		.click(function () {
		    stage.setFlipLayout(stage.getFlipLayout() ^ 1);
		});
        $(selectors.infoButton)
		.attr({ title: Mediasite.Player.Localization.Buttons.Info })
		.imageButton({ isCheckButton: true, checkedPosition: '-128px -285px' })
		.click(function () {
		    notifier.OnClickCommand(Mediasite.Player.ClickCommand.ShowInfo);
		});

        var $caption = $(selectors.captionButton)
		.imageButton({
		    isCheckButton: true,
		    checkedPosition: '-128px -32px',
		    normalTitle: Mediasite.Player.Localization.Buttons.ShowCaptioning,
		    checkedTitle: Mediasite.Player.Localization.Buttons.HideCaptioning
		})
		.click(function () { notifier.OnClickCommand(Mediasite.Player.ClickCommand.ToggleCaptions); });

        var $captionSearch = $(selectors.captionSearchButton)
		.imageButton({
		    isCheckButton: true,
		    checkedPosition: '-128px -513px',
		    normalTitle: Mediasite.Player.Localization.Buttons.ShowCaptionSearch,
		    checkedTitle: Mediasite.Player.Localization.Buttons.HideCaptionSearch
		})
		.click(function () { notifier.OnClickCommand(Mediasite.Player.ClickCommand.ToggleCaptionSearch); });

        if (!_presentation.HasCaptions) {
            $caption.imageButton('disable');
        }

        if (!maySearch()) {
            $captionSearch.hide();
        }

        $(selectors.closeDetailPanelButton)
		.imageButton({ spriteOffset: 32, normalTitle: Mediasite.Player.Localization.Buttons.Close })
		.click(function () { toggleDetailPanel(detailPanels.None); });

        $(selectors.closeInteractivityPanelButton)
		.imageButton({ spriteOffset: 32, normalTitle: Mediasite.Player.Localization.Buttons.Close })
		.click(function () { toggleInteractivityPanel(interactivityPanels.None); });

        var $polls = $(selectors.pollsButton)
		.attr({ title: Mediasite.Player.Localization.Buttons.ShowPolls })
		.imageButton()
		.click(function () { notifier.OnClickCommand(Mediasite.Player.ClickCommand.ShowPolls); });

        if (!_presentation.PollingEnabled) {
            $polls.imageButton('disable'); // hide or just disable?
        }

        var $ask = $(selectors.askButton)
        .attr({ title: Mediasite.Player.Localization.Buttons.Ask })
			.imageButton()
        .click(function () { notifier.OnClickCommand(Mediasite.Player.ClickCommand.AskQuestion); });

        if (!_presentation.ForumEnabled) {
            $ask.imageButton('disable');
        }

        var $email = $(selectors.emailButton)
        .attr({ title: Mediasite.Player.Localization.Buttons.Email })
			.imageButton()
        .click(function () { notifier.OnClickCommand(Mediasite.Player.ClickCommand.OpenEmail); });

        if (!_presentation.SharingEnabled) {
            $email.imageButton('disable');
        }

        var $links = $(selectors.linksButton)
        .attr({ title: Mediasite.Player.Localization.Buttons.Links })
			.imageButton()
        .click(function () { notifier.OnClickCommand(Mediasite.Player.ClickCommand.ShowLinks); });

        if (_presentation.Links.length < 1) {
            $links.imageButton('disable');
        }

        var $chapters = $(selectors.chaptersButton)
        .attr({ title: Mediasite.Player.Localization.Buttons.Chapters })
			.imageButton()
        .click(function () { notifier.OnClickCommand(Mediasite.Player.ClickCommand.ShowChapters); });
        if (_presentation.Chapters.length < 1) {
            $chapters.imageButton('disable');
        }

        $(selectors.helpButton)
		.attr({ title: Mediasite.Player.Localization.Buttons.Help })
		.imageButton()
		.click(function () { notifier.OnClickCommand(Mediasite.Player.ClickCommand.ShowHelp); });
    }

    this.UpdateMediaVolume = function (volume) {
        if (!(volume > 0)) {
            //mute
            $(selectors.volume).playervolume("mute");
        }
        else {
            //unmute
            $(selectors.volume).playervolume("unmute", volume);
        }
    }

    function togglePlayPause() {
        notifier.OnClickCommand(Mediasite.Player.ClickCommand.TogglePlayPause);
    }

    function removePx(pxString) {
        return pxString.replace('px', '');
    }

    function updateStageSize() {
        var stage = $(selectors.contentArea).first();
        stage.css('marginRight', '');
        stage.height(jQuery(window).height() - removePx(stage.css('marginTop')) - removePx(stage.css('marginBottom')));
        stage.width(jQuery(window).width() - removePx(stage.css('marginLeft')) - removePx(stage.css('marginRight')));

        stage.trigger('containerresize');
    }

    function updateLayout() {
        updateStageSize();

        // show/hide approprite buttons before we measure things.
        if (!Mediasite.PlayerLayoutOptions.EnablePresentationInfo) {
            $(selectors.infoButton).hide();
        }

        if (!Mediasite.PlayerLayoutOptions.EnableSofoBranding) {
            $(selectors.mediasiteSwirlButton).hide();
        }

        $(selectors.controlsMiddle).css({
            'margin-left': $(selectors.controlsLeft).outerWidth() + 'px',
            'margin-right': ($(selectors.controlsRight).outerWidth() + 20) + 'px'
        });
    }

    function getCurrentDetailPanel() {
        return _currentDetailPanel;
    }

    function setCurrentDetailPanel(value) {

        if (!Mediasite.PlayerLayoutOptions.EnablePresentationInfo && value === detailPanels.Info) {
            return;
        }


        fadePanel(getPanelSelector(_currentDetailPanel), false);
        if (value !== _currentDetailPanel) {
            _currentDetailPanel = value;

            fadePanel(getPanelSelector(_currentDetailPanel), true);

            $(selectors.infoButton).imageButton('setIsChecked', _currentDetailPanel === detailPanels.Info);
            $(selectors.captionSearchButton).imageButton('setIsChecked', _currentDetailPanel === detailPanels.Search);
        }

    }

    function toggleDetailPanel(panel) {

        if (panel === _currentDetailPanel) {
            setCurrentDetailPanel(detailPanels.None);
        }
        else {
            setCurrentDetailPanel(panel);
        }
    }

    function dismissInteractivityPanel() {
        toggleInteractivityPanel(interactivityPanels.None);
    }

    function clearInteractivityPopupWindow() {
        if (!_usePopupPanels) return;

        if (_currentPopupWindow && _currentPopupWindow.close) {
            _currentPopupWindow.close();
        }
        _currentPopupWindow = null;
    }

    function setCurrentInteractivityPanel(value) {
        fadePanel(getPanelSelector(_currentInteractivityPanel), false);
        clearInteractivityPopupWindow();

        if (_usePopupPanels && (value == interactivityPanels.Ask || value == interactivityPanels.Email)) {
            if (value !== interactivityPanels.None) {
                _currentPopupWindow = window.open('', 'interactivity', 'width=500,height=500', true);

                if (!_currentPopupWindow) {
                    // Pop up window failed
                    alert(Mediasite.Player.Localization.Common.PopupsBlocked);
                    _usePopupPanels = false;
                    setCurrentInteractivityPanel(value);
                    return;
                }

                var selector = $('body', _currentPopupWindow.document);
                selector.addClass(classes.popup);
                $(selectors.panelStylesheet).clone().appendTo(selector);

                switch (value) {
                    case interactivityPanels.Ask:
                        selectors.askPanel = selector;
                        break;
                    case interactivityPanels.Email:
                        selectors.emailPanel = selector;
                        break;
                }
            }

            // Can't detect when popup closes:
            // * $(_currentPopupWindow).bind('beforeunload') attaches it to the main window
            // * polling is inefficient
            _currentInteractivityPanel = interactivityPanels.None;
        } else {

            if (value !== _currentInteractivityPanel) {
                _currentInteractivityPanel = value;

                fadePanel(getPanelSelector(_currentInteractivityPanel), true);
            }
        }

    }

    function toggleInteractivityPanel(panel) {

        if (panel === _currentInteractivityPanel) {
            setCurrentInteractivityPanel(interactivityPanels.None);
        } else {
            setCurrentInteractivityPanel(panel);
        }
    }

    function getDisplayFromDuration(durationInMS, padHours) {
        if (durationInMS <= 1000) { // Android reports 1000ms when video is not yet loaded
            return "";
        }
        var whole = durationInMS;
        var hours = Math.floor(whole / 3600000);
        whole = whole - (hours * 3600000);
        if (hours < 10) {
            hours = "0" + hours;
        }
        var minutes = Math.floor(whole / 60000);
        whole = whole - (minutes * 60000);
        var seconds = Math.floor(whole / 1000);
        whole = whole - (seconds * 1000);
        if (minutes < 10) {
            minutes = "0" + minutes;
        }
        if (seconds < 10) {
            seconds = "0" + seconds;
        }
        if (hours === "00" && !padHours) {
            return (minutes + ":" + seconds);
        }
        return (hours + ":" + minutes + ":" + seconds);
    }

    function updatePositionText(position) {
        $(selectors.currentPosition).text(getDisplayFromDuration(position, true));
        $(selectors.livePosition).text(getDisplayFromDuration(position, true));
    }

    function updateBodyClasses() {
        var bod = $('body').removeClass().addClass(getBodyClassForPlayStatus(_presentation.PlayStatus));

        if (_presentation.PlayStatus === Mediasite.Player.PresentationStatus.ScheduledForLive ||
        _presentation.PlayStatus === Mediasite.Player.PresentationStatus.OpenForLive ||
        _presentation.PlayStatus === Mediasite.Player.PresentationStatus.Live ||
        _presentation.PlayStatus === Mediasite.Player.PresentationStatus.LivePaused ||
        _presentation.PlayStatus === Mediasite.Player.PresentationStatus.LiveEnded) {

            bod.addClass('isLively');
        }

        if (!Mediasite.PlayerLayoutOptions.AllowLayoutAdjustment) {
            bod.addClass('noLayoutAdjustment');
        }

        if (!Mediasite.PlayerLayoutOptions.ShowSlideNavigation) {
            bod.addClass('noSlideNavigation');
        }

        if (Mediasite.BrowserDetect.IOS()) {
            bod.addClass('is-ios');
        } else {
            bod.addClass('not-ios');
        }

        if (!(Mediasite.BrowserDetect.Android() || Mediasite.BrowserDetect.IOS())) {
            bod.addClass('styledScrollbars');
        }

        if (Mediasite.BrowserDetect.IOS5()) {
            bod.addClass('is-ios5');
        }
    }

    function getBodyClassForPlayStatus(playStatus) {
        // WARNING: The class name returned is coupled to the string value of the playStatus member, 
        // an detail which could change. If this becomes an issue, expand this function to return 
        // explicit values to match those expected in CSS.
        return playStatus;
    }

    function hideVideoThumb() {
        $(selectors.videoThumbContainer).css('display', 'none');
    }

    function slideNav_beginPreview(e) {
        slidePreview.setPreviewSlide(slideNav.getPreviewSlide());
    }

    function slideNav_endPreview(e) {
        slidePreview.setPreviewSlide(null);
    }

    function slidePreview_slidePreviewInitiated(e) {
        var thumbArea = slideNav.getPreviewThumbArea();
        var previewArea = slidePreview.getPreviewArea();
        var src = slidePreview.getPreviewSrc();

        slidePreviewAnimation.animate(src, thumbArea, previewArea);
    }

    function slidePartitions_currentpagechanged(e) {
        slideNav.setSlides(_slidePartitions.getCurrentPageItems());
    }



    // ===================================================================
    // A basic implementation of the Mediasite.Player.SlideImage interface
    // ===================================================================
    function SpecialSlideImage(imageFilename) {
        return {
            getSlideNumber: function () { return 0; },
            getFullUrl: function () { return imageFilename; },
            getCacheFriendlyUrl: function (height, aspect) { return imageFilename; }
        };
    }
};
// -=====


// Stage
// +============

// StageControl
// +===========
Mediasite.Player.StageControl = function (panel, slideBox, videoBox, slidePreviewBox, layoutEngine) {
    var _panel = $(panel);
    var _slideBox = $(slideBox);
    var _videoBox = $(videoBox);
    var _slidePreviewBox = $(slidePreviewBox);
    var _layoutType, _flipLayout;

    // layoutEngine is an optional parameter.
    var _layoutEngine = layoutEngine || new Mediasite.Player.StageLayoutEngine();

     $(window).resize(function () {
        _panel.trigger('resize');
    });

    function applyRect(element, rect) {
        element.width(rect.width());
        element.height(rect.height());
        element.css('left', rect.left());
        element.css('top', rect.top());
    }

    function updateLayout() {
        if (_panel.width() <= 0 || _panel.height() <= 0) {
            return;
        }

        var layout = _layoutEngine.getLayout();

        applyRect(_slideBox, layout.primary());
        applyRect(_videoBox, layout.secondary());
        applyRect(_slidePreviewBox, layout.primary());

        // adjust z-indexes
        var slideBoxZIndex = 0;
        if (_layoutEngine.flipLayout()) {
            slideBoxZIndex = slideBoxZIndex ^ 1;
        }

        if (_layoutEngine.layoutType() === Mediasite.Player.StageLayoutType.PrimaryOnly) {
            slideBoxZIndex = slideBoxZIndex ^ 1;
        }

        _slideBox.css('zIndex', slideBoxZIndex);
        _videoBox.css('zIndex', slideBoxZIndex ^ 1);
        _slidePreviewBox.css('zIndex', 3);

        _slideBox.css('opacity', 0);

        _slideBox.css('margin-top', '0'); // See "Move the hidden slide area..." comment below.

        // adjust opacities
        if (_layoutEngine.layoutType() === Mediasite.Player.StageLayoutType.PrimaryOnly) {
            var slideBoxOpacity = 1;
            if (_layoutEngine.flipLayout()) {
                slideBoxOpacity = 0;
                // Move the hidden slide area off screen to prevent the user from clicking on 
                // the invisible slide zoom buttons when the slide aspect is wider than the 
                // video aspect, the video is primary, and the layout is PrimaryOnly. 
                // NOTE: Using display:none caused the slide image to change size on each reveal.
                // NOTE: This will be very broken if/when we add animations between stage layouts.
                _slideBox.css('margin-top', '9999px');
            }
            _slideBox.css('opacity', slideBoxOpacity);
            _videoBox.css('opacity', slideBoxOpacity ^ 1);
        } else {
            _slideBox.css('opacity', '1');
            _videoBox.css('opacity', '1');
        }

        _panel.trigger('stageresize');
    }

    _panel.bind('containerresize', function (evt) {
        evt.stopPropagation();
        // The containerresize event should only be handled when triggered from above.
        // If this handler is called from an event propagating up, 
        // then a handler farther down the DOM tree should prevent propagation.

        _layoutEngine.boundingRect(Mediasite.Player.StageRect.fromElement(_panel));
        updateLayout();
    });

    updateLayout();

    this.getLayoutType = function () { return _layoutEngine.layoutType(); };
    this.setLayoutType = function (value) {
        _layoutEngine.layoutType(value);
        updateLayout();
    };
    this.getPrimaryContentElement = function () { return this.getFlipLayout() ? Mediasite.Player.StageContentElement.Video : Mediasite.Player.StageContentElement.Slide; };
    this.setPrimaryContentElement = function (value) {
        this.setFlipLayout(value === Mediasite.Player.StageContentElement.Video);
    };
    this.getFlipLayout = function () { return _layoutEngine.flipLayout(); };
    this.setFlipLayout = function (value) {
        _layoutEngine.flipLayout(value);
        updateLayout();
    };
    this.getVideoSide = function () { return _layoutEngine.secondarySide(); };
    this.setVideoSide = function (value) {
        var pos = value;
        if (_layoutEngine.flipLayout()) {
            pos = (pos === Mediasite.Player.RightOrLeft.Left) ? Mediasite.Player.RightOrLeft.Right : Mediasite.Player.RightOrLeft.Left;
        }

        _layoutEngine.secondarySide(pos);
        updateLayout();
    };
    this.getSlideAspect = function () { return _layoutEngine.primaryAspect(); };
    this.setSlideAspect = function (value) {
        _layoutEngine.primaryAspect(value);
        updateLayout();
    };
    this.getVideoAspect = function () { return _layoutEngine.secondaryAspect(); };
    this.setVideoAspect = function (value) {
        _layoutEngine.secondaryAspect(value);
        updateLayout();
    };
};
// -=====

// StageLayoutEngine
// +================
Mediasite.Player.StageLayoutEngine = function (layoutStrategyFactory) {

    var _layoutStrategyFactory = layoutStrategyFactory || Mediasite.Player.StageLayoutStrategy.forType;
    var _layoutType = Mediasite.Player.StageLayoutType.SideBySide;
    var _currentLayoutStrategy = null;
    var _boundingRect = new Mediasite.Player.StageRect(0, 0, 400, 300);
    var _primaryAspect = 4 / 3;
    var _secondaryAspect = 4 / 3;
    var _flipLayout = false;
    var _smallBoxSide = Mediasite.Player.RightOrLeft.Right;

    function updateCurrentLayoutStrategy() {
        _currentLayoutStrategy = _layoutStrategyFactory(_layoutType);
    }

    updateCurrentLayoutStrategy();

    this.layoutType = function (value) {
        if (typeof value !== 'undefined') {
            _layoutType = value;
            updateCurrentLayoutStrategy();
        }
        return _layoutType;
    };

    this.boundingRect = function (value) {
        if (typeof value !== 'undefined') {
            _boundingRect = value;
        }
        return _boundingRect;
    };

    this.primaryAspect = function (value) {
        if (typeof value !== 'undefined') {
            _primaryAspect = value;
        }
        return _primaryAspect;
    };

    this.secondaryAspect = function (value) {
        if (typeof value !== 'undefined') {
            _secondaryAspect = value;
        }
        return _secondaryAspect;
    };

    this.flipLayout = function (value) {
        if (typeof value !== 'undefined') {
            _flipLayout = value;
        }
        return _flipLayout;
    };

    this.secondarySide = function (value) {
        if (typeof value !== 'undefined') {
            _smallBoxSide = value;
        }
        return _smallBoxSide;
    };

    this.getLayout = function () {
        var l;
        if (_flipLayout) {
            l = _currentLayoutStrategy.getLayout(_boundingRect, _secondaryAspect, _primaryAspect);
            l = new Mediasite.Player.StageLayout(l.secondary(), l.primary());
        } else {
            l = _currentLayoutStrategy.getLayout(_boundingRect, _primaryAspect, _secondaryAspect);
        }

        if (_smallBoxSide === Mediasite.Player.RightOrLeft.Left) {
            l = new Mediasite.Player.StageLayout(
			l.primary().flipHorizontal(_boundingRect.width(), _boundingRect.left()),
			l.secondary().flipHorizontal(_boundingRect.width(), _boundingRect.left()));
        }

        return l;
    };
};
// -=====

Mediasite.Player.RightOrLeft = {
    Right: 'Right',
    Left: 'Left'
};

Mediasite.Player.StageContentElement = {
    Video: 'Video',
    Slide: 'Slide'
};

Mediasite.Player.StageLayoutType = {
    SideBySide: 0,
    PictureInPicture: 1,
    PrimaryOnly: 2
};

// StageLayout
// +==========
Mediasite.Player.StageLayout = function (primaryRect, secondaryRect) {
    var _primary = primaryRect;
    var _secondary = secondaryRect;

    this.primary = function () {
        return _primary;
    };
    this.secondary = function () {
        return _secondary;
    };
};

Mediasite.Player.StageLayout.maxSecondaryItemWidth = 320;

Mediasite.Player.StageLayout.getFittedRect = function (rect, aspect) {
    var boundingAspect = rect.width() / rect.height();

    var height = rect.height();
    var width = rect.width();
    var top = rect.top();
    var left = rect.left();


    if (boundingAspect > aspect) {
        // Bounding Rect has wider aspect.
        width = height * aspect;
        left = (rect.width() - width) / 2.0 + rect.left();
    }
    else {
        // Bounding Rect has taller aspect.
        height = width / aspect;
        top = (rect.height() - height) / 2.0 + rect.top();
    }

    return new Mediasite.Player.StageRect(left, top, width, height);
};

Mediasite.Player.StageLayout.SideBySide = function (boundingRect, primaryAspect, secondaryAspect) {
    var margin = 8;
    var maxSecondaryItemFraction = 0.33; // Maximum portion of the stage that a side item can take up.

    var secondaryColumnWidth = Math.min(Mediasite.Player.StageLayout.maxSecondaryItemWidth, boundingRect.width() * maxSecondaryItemFraction + margin * 2);
    var primaryColumnWidth = boundingRect.width() - secondaryColumnWidth;

    var primaryColumn = new Mediasite.Player.StageRect(boundingRect.left(), boundingRect.top(), primaryColumnWidth, boundingRect.height());
    primaryColumn = primaryColumn.contract(margin, margin);
    var primaryRect = Mediasite.Player.StageLayout.getFittedRect(primaryColumn, primaryAspect);

    var secondaryColumn = new Mediasite.Player.StageRect(boundingRect.left() + primaryColumnWidth, boundingRect.top(), secondaryColumnWidth, boundingRect.height());
    secondaryColumn = secondaryColumn.contract(margin, margin);
    var secondaryRect = Mediasite.Player.StageLayout.getFittedRect(secondaryColumn, secondaryAspect);

    // Place the secondary item just below the primary item
    if (primaryRect.bottom() > secondaryRect.bottom()) {
        secondaryRect = secondaryRect.copy(
		{ top: primaryRect.bottom() + margin * 2 - secondaryRect.height() });
    }


    return new Mediasite.Player.StageLayout(primaryRect, secondaryRect);
};

Mediasite.Player.StageLayout.PictureInPicture = function (boundingRect, primaryAspect, secondaryAspect) {
    var margin = 8;
    var maxInnerItem = 0.4; // Maximum portion of the primary item covered by the secondary item.

    var primaryColumn = boundingRect.contract(margin * 3, margin * 3);
    var primaryRect = Mediasite.Player.StageLayout.getFittedRect(primaryColumn, primaryAspect);

    var secondaryColumnWidth = Math.min(Mediasite.Player.StageLayout.maxSecondaryItemWidth, primaryRect.width() * maxInnerItem + margin * 2);
    var secondaryColumn = new Mediasite.Player.StageRect(primaryRect.right() - secondaryColumnWidth, boundingRect.top(), secondaryColumnWidth, boundingRect.height());
    var secondaryRect = Mediasite.Player.StageLayout.getFittedRect(secondaryColumn, secondaryAspect);

    // place the secondary item just below and just to the right of the primary item.
    secondaryRect = secondaryRect.copy({
        left: primaryRect.right() + margin * 2 - secondaryRect.width(),
        top: primaryRect.bottom() + margin * 2 - secondaryRect.height()
    });

    return new Mediasite.Player.StageLayout(primaryRect, secondaryRect);
};

Mediasite.Player.StageLayout.PrimaryOnly = function (boundingRect, primaryAspect, secondaryAspect) {
    var margin = 8;

    var column = boundingRect.contract(margin * 3, margin * 3.0);
    var primaryRect = Mediasite.Player.StageLayout.getFittedRect(column, primaryAspect);
    var secondaryRect = Mediasite.Player.StageLayout.getFittedRect(column, secondaryAspect);

    return new Mediasite.Player.StageLayout(primaryRect, secondaryRect);
};
// -=====

// StageLayoutStrategy
// +==================
Mediasite.Player.StageLayoutStrategy = function (getLayout) {
    this.getLayout = getLayout;
};

Mediasite.Player.StageLayoutStrategy.forType = function (layoutType) {
    if (layoutType === Mediasite.Player.StageLayoutType.PrimaryOnly) {
        return new Mediasite.Player.StageLayoutStrategy(Mediasite.Player.StageLayout.PrimaryOnly);
    } else if (layoutType === Mediasite.Player.StageLayoutType.PictureInPicture) {
        return new Mediasite.Player.StageLayoutStrategy(Mediasite.Player.StageLayout.PictureInPicture);
    } else {
        return new Mediasite.Player.StageLayoutStrategy(Mediasite.Player.StageLayout.SideBySide); // default (even if layoutType is junk).
    }
};
// -=====

// StageRect
// +========
Mediasite.Player.StageRect = function (left, top, width, height) {
    Mediasite.Geometry.Rect.apply(this, arguments);
}
jQuery.extend(Mediasite.Player.StageRect.prototype, {

    // this is the verb 'contract' which is the opposite of expand.
    contract: function (x, y) {
        x = x || 0;
        y = y || 0;

        var newWidth = this.width();
        var newHeight = this.height();
        var newLeft = this.left();
        var newTop = this.top();

        if (x * 2 < this.width() && y * 2 < this.height()) {
            newWidth -= x * 2;
            newHeight -= y * 2;
            newLeft += x;
            newTop += y;
        }

        return new Mediasite.Player.StageRect(newLeft, newTop, newWidth, newHeight);
    },

    copy: function (changeProps) {
        if (!changeProps) {
            return new Mediasite.Player.StageRect(this.left(), this.top(), this.width(), this.height());
        }

        var left = (typeof changeProps.left === 'undefined') ? this.left() : changeProps.left;
        var top = (typeof changeProps.top === 'undefined') ? this.top() : changeProps.top;
        var width = (typeof changeProps.width === 'undefined') ? this.width() : changeProps.width;
        var height = (typeof changeProps.height === 'undefined') ? this.height() : changeProps.height;

        return new Mediasite.Player.StageRect(left, top, width, height);
    },

    flipHorizontal: function (containerWidth, containerLeft) {
        var newLeft = (containerWidth + 2 * containerLeft) - this.right();

        return this.copy({ left: newLeft });
    }
});
Mediasite.Player.StageRect.fromElement = function (element) {
    if (!element) {
        return new Mediasite.Player.StageRect();
    }

    var position = element.position();
    return new Mediasite.Player.StageRect(position.left, position.top, element.width(), element.height());

};
// -=====

// -=====
