if (!Mediasite) {
    var Mediasite = {};
}
Mediasite.Player = Mediasite.Player || {};

//=============================================================================
// StreamView Module
//=============================================================================
Mediasite.Player.StreamView = (function ($, geometry, mvLayout, undefined) {

    function BasicStreamView(stageElement, streamDefinition, defaultStreamImageUrl) {
        var priorityClasses = ['primary', 'secondary', 'tertiary', 'quaternary'];
        var result;
        var _imageViewer;
        var outerElement, mediaElementContainer, videoViewElement, imageViewElement;
        var _currentSlideStuff;
        var _currentImage;
        var _isImageViewerActive = false;
        var _currentMode;


        function constructor() {
            stageElement = $(stageElement);

            outerElement = makeStreamViewElement(streamDefinition.StreamOrdinal);
            outerElement.appendTo(stageElement);

            imageViewElement = outerElement.find('.slide-view');
            videoViewElement = outerElement.find('.video-view');
            mediaElementContainer = outerElement.find('.media-element-container');

            result = {
                outerElement: outerElement,
                mediaElementContainer: mediaElementContainer,
                streamDefinition: streamDefinition,
                updateCurrentSlide: function (slide, slideUrlProvider) {
                    _currentSlideStuff = { slide: slide, slideUrlProvider: slideUrlProvider };
                    _currentMode.updateImageView();
                },
                getCurrentSlide: function () {
                    if (hasCurrentSlideStuff()) {
                        return _currentSlideStuff.slide;
                    } else {
                        return undefined;
                    }
                },
                setDisplayContent: function (contentType) {
                    streamDefinition.DisplayContent = contentType;
                    adjustForContentType(contentType);
                }
            };


            adjustForContentType(streamDefinition.DisplayContent);

            outerElement.on('element-resize', function (e) { _currentMode.updateImageView(); });

            return result;
        }



        var mode = {
            none: {
                enter: function () {
                    enterImageMode();
                },
                updateImageView: function () {
                    var url = streamDefinition.StreamThumbnailUrl || defaultStreamImageUrl;
                    displayImage(makeSpecialImage(url), StreamImageViewer.FitCalculations.trim);
                }
            },
            slide: {
                enter: function () {
                    enterImageMode();
                },
                updateImageView: function () {
                    var image, fit;
                    if (hasCurrentSlideStuff() && _currentSlideStuff.slide.Number > 0) {
                        image = new Mediasite.Player.SlideImage(_currentSlideStuff.slide.Number, _currentSlideStuff.slideUrlProvider);
                        fit = StreamImageViewer.FitCalculations.pad;
                    } else {
                        image = makeSpecialImage(defaultStreamImageUrl);
                        fit = StreamImageViewer.FitCalculations.trim;
                    }
                    displayImage(image, fit);
                }
            },
            video: {
                enter: function () {
                    enterVideoMode();
                },
                updateImageView: function () { }
            }
        };


        function getModeForContentType(contentType) {
            if (contentType === Mediasite.ContentType.None) {
                return mode.none;
            } else if (contentType === Mediasite.ContentType.Slide) {
                return mode.slide;
            } else if (contentType === Mediasite.ContentType.Video) {
                return mode.video;
            }
        }


        function adjustForContentType(contentType) {
            _currentMode = getModeForContentType(contentType);
            _currentMode.enter();
            _currentMode.updateImageView();
        }

        function enterImageMode() {
            showElement(imageViewElement);
            hideElement(videoViewElement);

            if (!hasImageViewer()) {
                createImageViewer();
            }
        }

        function enterVideoMode() {
            if (hasImageViewer()) {
                destroyImageViewer();
            }

            showElement(videoViewElement);
            hideElement(imageViewElement);
        }

        function hasImageViewer() {
            return typeof _imageViewer !== 'undefined';
        }

        function createImageViewer() {
            _imageViewer = new StreamImageViewer(imageViewElement);
        }

        function destroyImageViewer(undefined) {
            _imageViewer = undefined;
            imageViewElement.empty();
        }

        function showElement(element) {
            element.css({ 'display': 'block' });
        }
        function hideElement(element) {
            element.css({ 'display': 'none' });
        }

        function makeSpecialImage(url) {
            return new Mediasite.Player.SpecialSlideImage(url);
        }

        function displayImage(image, fitCalculator) {
            if (hasImageViewer()) {
                _imageViewer.displayImage(image, fitCalculator);
            }
        }

        function hasCurrentSlideStuff() {
            return _currentSlideStuff && _currentSlideStuff.slide && _currentSlideStuff.slideUrlProvider;
        }

        function makeStreamViewElement(streamOrdinal) {
            var streamBoxElement = $(
            '<div class="stream">' +
                '<div class="video-view">' +
                    '<div class="media-element-container"></div>' +
                    '<div class="video-stream-overlay"></div>' +
                '</div>' +
                '<div class="slide-view"></div>' +
                '<div class="framer"></div>' +
            '</div>'
            );
            //.addClass(makePriorityClassName(streamOrdinal))
            //.addClass(makePositionClassName(streamOrdinal));

            return streamBoxElement;
        }

        function makePriorityClassName(index) {
            return priorityClasses[index];
        }

        function makePositionClassName(index) {
            return 'position' + index;
        }



        return constructor();
    };


    function StreamImageViewer(element) {
        var self = this;
        var _lastAppliedHeight = 0;
        var _lastShownImageSrc = null;

        var _container = element;
        var _img = $('<img />').appendTo(_container).width('100%').height('100%');

        var _imageSizeProvider = new Mediasite.Player.ImageSizeProvider();
        var _slideImage, _fitCalculation;
        var _emptySize = new Mediasite.Geometry.Size(0, 0);
        var _nativeSize = new Mediasite.Geometry.Size(800, 600);


        // accessors
        // +========
        this.getElement = function () { return _container; };

        this.setImageSizeProvider = function (value) { _imageSizeProvider = value; };

        this.getToolTip = function () { return _img.attr('title'); };
        this.setToolTip = function (value) {
            _img.attr('alt', value).attr('title', value);
        };

        // -=====


        this.displayImage = function (slideImage, fitCalculation) {
            _slideImage = slideImage;
            _fitCalculation = fitCalculation;
            loadSlide();
        };


        function loadSlide() {
            if (!hasSlide()) {
                showImage('', StreamImageViewer.FitCalculations.pad);
                _nativeSize = _emptySize;
                return;
            }

            var fullUrl = _slideImage.getFullUrl();
            _imageSizeProvider.getSize(fullUrl, function (size) {
                // Remember the measured size, since it's kind of a pain to get it.
                _nativeSize = size;

                // Calculate the size and position of the img.
                var containerRect = new Mediasite.Geometry.Rect(0, 0, _container.width(), _container.height());
                var imgAspect = _nativeSize.width() / _nativeSize.height();
                var imgRect = _fitCalculation(containerRect, imgAspect);

                // Size and position the img.
                _img.css({
                    'left': imgRect.left(),
                    'top': imgRect.top(),
                    'width': imgRect.width(),
                    'height': imgRect.height()
                });

                // Load the img by setting the appropriate src value.
                loadRightSizedImage(imgRect.height());
            });
        }

        function loadRightSizedImage(height) {
            var h = height || _lastAppliedHeight;

            if (!hasSlide()) {
                return;
                // TODO: Unload last slide image?
            }

            var url = null;
            var nativeAspect = _nativeSize.width() / _nativeSize.height();
            var cacheFriendlySize = Mediasite.Slide.getCacheFriendlyImageSize(h, nativeAspect);
            if (cacheFriendlySize.height() < _nativeSize.height()) {
                url = _slideImage.getCacheFriendlyUrl(h, nativeAspect);
            } else {
                url = _slideImage.getFullUrl();
            }
            showImage(url);
        }

        function hasSlide() {
            return (_slideImage && typeof (_slideImage.getSlideNumber()) == "number");
        }

        function showImage(src) {
            if (src === _lastShownImageSrc) {
                return;
            } else if (typeof src === 'string' && src.length > 0) {
                _img.attr('src', src);
                setImgOpacity(1);
            } else {
                _img.removeAttr('src');
                setImgOpacity(0);
            }

            _lastShownImageSrc = src;

            // TODO: Animate the transition.
        }

        function setImgOpacity(value) {
            var currentValue = Number(_img.css('opacity'));
            if (value !== currentValue) {
                _img.css('opacity', value);
            }
        }


        // Borrowed from Mediasite.Player.StageLayout.getFittedRect.
        // Return value type changed from StageRect to Rect.
        function getFittedRect(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.Geometry.Rect(left, top, width, height);
        };
    };


    StreamImageViewer.FitCalculations = (function () {

        return {
            pad: pad,
            trim: trim,
            fitWidth: fitWidth,
            fitHeight: fitHeight
        };


        function pad(outerRect, innerAspect) {
            var outerAspect = outerRect.width() / outerRect.height();

            if (outerAspect > innerAspect) {
                // Outer Rect has wider aspect.
                return fitHeight(outerRect, innerAspect);
            }
            else {
                // Outer Rect has taller aspect.
                return fitWidth(outerRect, innerAspect);
            }
        }

        function trim(outerRect, innerAspect) {
            var outerAspect = outerRect.width() / outerRect.height();

            if (outerAspect > innerAspect) {
                // Outer Rect has wider aspect.
                return fitWidth(outerRect, innerAspect);
            }
            else {
                // Outer Rect has taller aspect.
                return fitHeight(outerRect, innerAspect);
            }
        }

        function fitWidth(outerRect, innerAspect) {
            var height, width, top, left;

            width = outerRect.width();
            height = outerRect.width() / innerAspect;

            left = outerRect.left();
            top = (outerRect.height() - height) / 2.0 + outerRect.top();

            return new Mediasite.Geometry.Rect(left, top, width, height);
        }

        function fitHeight(outerRect, innerAspect) {
            var height, width, top, left;

            width = outerRect.height() * innerAspect;
            height = outerRect.height();

            left = (outerRect.width() - width) / 2.0 + outerRect.left();
            top = outerRect.top();

            return new Mediasite.Geometry.Rect(left, top, width, height);
        }

    })();



    // Public Module Defined
    return {
        BasicStreamView: BasicStreamView
    };

})(jQuery, Mediasite.Geometry, Mediasite.Player.MultiViewLayout);