(function ($) {

    $.extend(mejs.MepDefaults, {
        usePluginFullScreen: true,
        newWindowCallback: function () {
            return '';
        },
        fullscreenText: mejs.i18n.t('Fullscreen')
    });

    $.extend(MediaElementPlayer.prototype, {

        isFullScreen: false,

        isNativeFullScreen: false,

        isInIframe: false,

        // Possible modes
        // (1) 'native-native' 	HTML5 video  + browser fullscreen (IE10+, etc.)
        // (2) 'plugin-native' 	plugin video + browser fullscreen (fails in some versions of Firefox)
        // (3) 'fullwindow' 	Full window (retains all UI)
        // usePluginFullScreen = true
        // (4) 'plugin-click' 	Flash 1 - click through with pointer events
        // (5) 'plugin-hover' 	Flash 2 - hover popup in flash (IE6-8)		
        fullscreenMode: '',

        buildfullscreen: function (player, controls, layers, media) {

            if (!player.isVideo)
                return;

            player.isInIframe = (window.location != window.parent.location);

            // detect on start
            media.addEventListener('play', function () {
                player.detectFullscreenMode();
            });

            // build button
            var t = this,
                hideTimeout = null,
                fullscreenBtn =
                    $('<div class="mejs-button mejs-fullscreen-button">' +
                        '<button type="button" aria-controls="' + t.id + '" title="' + t.options.fullscreenText + '" aria-label="' + t.options.fullscreenText + '"></button>' +
                        '</div>')
                        .appendTo(controls)
                        .on('click', function () {

                            // toggle fullscreen
                            var isFullScreen = (mejs.MediaFeatures.hasTrueNativeFullScreen && mejs.MediaFeatures.isFullScreen()) || player.isFullScreen;

                            if (isFullScreen) {
                                player.exitFullScreen();
                            } else {
                                player.enterFullScreen();
                            }
                        })
                        .on('mouseover', function () {

                            // very old browsers with a plugin
                            if (t.fullscreenMode == 'plugin-hover') {
                                if (hideTimeout !== null) {
                                    clearTimeout(hideTimeout);
                                    delete hideTimeout;
                                }

                                var buttonPos = fullscreenBtn.offset(),
                                    containerPos = player.container.offset();

                                media.positionFullscreenButton(buttonPos.left - containerPos.left, buttonPos.top - containerPos.top, true);
                            }

                        })
                        .on('mouseout', function () {

                            if (t.fullscreenMode == 'plugin-hover') {
                                if (hideTimeout !== null) {
                                    clearTimeout(hideTimeout);
                                    delete hideTimeout;
                                }

                                hideTimeout = setTimeout(function () {
                                    media.hideFullscreenButton();
                                }, 1500);
                            }

                        });


            player.fullscreenBtn = fullscreenBtn;

            t.globalBind('keydown', function (e) {
                if (e.keyCode == 27 && ((mejs.MediaFeatures.hasTrueNativeFullScreen && mejs.MediaFeatures.isFullScreen()) || t.isFullScreen)) {
                    player.exitFullScreen();
                }
            });

            t.normalHeight = 0;
            t.normalWidth = 0;

            // setup native fullscreen event
            if (mejs.MediaFeatures.hasTrueNativeFullScreen) {

                // chrome doesn't alays fire this in an iframe
                var fullscreenChanged = function (e) {
                    if (player.isFullScreen) {
                        if (mejs.MediaFeatures.isFullScreen()) {
                            player.isNativeFullScreen = true;
                            // reset the controls once we are fully in full screen
                            player.setControlsSize();
                        } else {
                            player.isNativeFullScreen = false;
                            // when a user presses ESC
                            // make sure to put the player back into place
                            player.exitFullScreen();
                        }
                    }
                };

                player.globalBind(mejs.MediaFeatures.fullScreenEventName, fullscreenChanged);
            }

        },

        detectFullscreenMode: function () {

            var t = this,
                mode = '',
                features = mejs.MediaFeatures;

            if (features.hasTrueNativeFullScreen && t.media.pluginType === 'native') {
                mode = 'native-native';
            } else if (features.hasTrueNativeFullScreen && t.media.pluginType !== 'native' && !features.hasFirefoxPluginMovingProblem) {
                mode = 'plugin-native';
            } else if (t.usePluginFullScreen) {
                if (mejs.MediaFeatures.supportsPointerEvents) {
                    mode = 'plugin-click';
                    // this needs some special setup
                    t.createPluginClickThrough();
                } else {
                    mode = 'plugin-hover';
                }

            } else {
                mode = 'fullwindow';
            }


            t.fullscreenMode = mode;
            return mode;
        },

        isPluginClickThroughCreated: false,

        createPluginClickThrough: function () {

            var t = this;

            // don't build twice
            if (t.isPluginClickThroughCreated) {
                return;
            }

            // allows clicking through the fullscreen button and controls down directly to Flash

            /*
             When a user puts his mouse over the fullscreen button, we disable the controls so that mouse events can go down to flash (pointer-events)
             We then put a divs over the video and on either side of the fullscreen button
             to capture mouse movement and restore the controls once the mouse moves outside of the fullscreen button
            */

            var fullscreenIsDisabled = false,
                restoreControls = function () {
                    if (fullscreenIsDisabled) {
                        // hide the hovers
                        for (var i in hoverDivs) {
                            hoverDivs[i].hide();
                        }

                        // restore the control bar
                        t.fullscreenBtn.css('pointer-events', '');
                        t.controls.css('pointer-events', '');

                        // prevent clicks from pausing video
                        t.media.removeEventListener('click', t.clickToPlayPauseCallback);

                        // store for later
                        fullscreenIsDisabled = false;
                    }
                },
                hoverDivs = {},
                hoverDivNames = ['top', 'left', 'right', 'bottom'],
                i, len,
                positionHoverDivs = function () {
                    var fullScreenBtnOffsetLeft = fullscreenBtn.offset().left - t.container.offset().left,
                        fullScreenBtnOffsetTop = fullscreenBtn.offset().top - t.container.offset().top,
                        fullScreenBtnWidth = fullscreenBtn.outerWidth(true),
                        fullScreenBtnHeight = fullscreenBtn.outerHeight(true),
                        containerWidth = t.container.width(),
                        containerHeight = t.container.height();

                    for (i in hoverDivs) {
                        hoverDivs[i].css({position: 'absolute', top: 0, left: 0}); //, backgroundColor: '#f00'});
                    }

                    // over video, but not controls
                    hoverDivs['top']
                        .width(containerWidth)
                        .height(fullScreenBtnOffsetTop);

                    // over controls, but not the fullscreen button
                    hoverDivs['left']
                        .width(fullScreenBtnOffsetLeft)
                        .height(fullScreenBtnHeight)
                        .css({top: fullScreenBtnOffsetTop});

                    // after the fullscreen button
                    hoverDivs['right']
                        .width(containerWidth - fullScreenBtnOffsetLeft - fullScreenBtnWidth)
                        .height(fullScreenBtnHeight)
                        .css({
                            top: fullScreenBtnOffsetTop,
                            left: fullScreenBtnOffsetLeft + fullScreenBtnWidth
                        });

                    // under the fullscreen button
                    hoverDivs['bottom']
                        .width(containerWidth)
                        .height(containerHeight - fullScreenBtnHeight - fullScreenBtnOffsetTop)
                        .css({top: fullScreenBtnOffsetTop + fullScreenBtnHeight});
                };

            t.globalBind('resize', function () {
                positionHoverDivs();
            });

            for (i = 0, len = hoverDivNames.length; i < len; i++) {
                hoverDivs[hoverDivNames[i]] = $('<div class="mejs-fullscreen-hover" />').appendTo(t.container).mouseover(restoreControls).hide();
            }

            // on hover, kill the fullscreen button's HTML handling, allowing clicks down to Flash
            fullscreenBtn.on('mouseover', function () {

                if (!t.isFullScreen) {

                    var buttonPos = fullscreenBtn.offset(),
                        containerPos = player.container.offset();

                    // move the button in Flash into place
                    media.positionFullscreenButton(buttonPos.left - containerPos.left, buttonPos.top - containerPos.top, false);

                    // allows click through
                    t.fullscreenBtn.css('pointer-events', 'none');
                    t.controls.css('pointer-events', 'none');

                    // restore click-to-play
                    t.media.addEventListener('click', t.clickToPlayPauseCallback);

                    // show the divs that will restore things
                    for (i in hoverDivs) {
                        hoverDivs[i].show();
                    }

                    positionHoverDivs();

                    fullscreenIsDisabled = true;
                }

            });

            // restore controls anytime the user enters or leaves fullscreen
            media.addEventListener('fullscreenchange', function (e) {
                t.isFullScreen = !t.isFullScreen;
                // don't allow plugin click to pause video - messes with
                // plugin's controls
                if (t.isFullScreen) {
                    t.media.removeEventListener('click', t.clickToPlayPauseCallback);
                } else {
                    t.media.addEventListener('click', t.clickToPlayPauseCallback);
                }
                restoreControls();
            });


            // the mouseout event doesn't work on the fullscren button, because we already killed the pointer-events
            // so we use the document.mousemove event to restore controls when the mouse moves outside the fullscreen button

            t.globalBind('mousemove', function (e) {

                // if the mouse is anywhere but the fullsceen button, then restore it all
                if (fullscreenIsDisabled) {

                    var fullscreenBtnPos = fullscreenBtn.offset();


                    if (e.pageY < fullscreenBtnPos.top || e.pageY > fullscreenBtnPos.top + fullscreenBtn.outerHeight(true) ||
                        e.pageX < fullscreenBtnPos.left || e.pageX > fullscreenBtnPos.left + fullscreenBtn.outerWidth(true)
                    ) {

                        fullscreenBtn.css('pointer-events', '');
                        t.controls.css('pointer-events', '');

                        fullscreenIsDisabled = false;
                    }
                }
            });


            t.isPluginClickThroughCreated = true;
        },

        cleanfullscreen: function (player) {
            player.exitFullScreen();
        },

        containerSizeTimeout: null,

        enterFullScreen: function () {

            var t = this;

            if (mejs.MediaFeatures.isiOS && mejs.MediaFeatures.hasiOSFullScreen && typeof t.media.webkitEnterFullscreen === 'function') {
                t.media.webkitEnterFullscreen();
                return;
            }

            // set it to not show scroll bars so 100% will work
            $(document.documentElement).addClass('mejs-fullscreen');

            // store sizing
            t.normalHeight = t.container.height();
            t.normalWidth = t.container.width();


            // attempt to do true fullscreen
            if (t.fullscreenMode === 'native-native' || t.fullscreenMode === 'plugin-native') {

                mejs.MediaFeatures.requestFullScreen(t.container[0]);
                //return;

                if (t.isInIframe) {
                    // sometimes exiting from fullscreen doesn't work
                    // notably in Chrome <iframe>. Fixed in version 17
                    setTimeout(function checkFullscreen() {

                        if (t.isNativeFullScreen) {
                            var percentErrorMargin = 0.002, // 0.2%
                                windowWidth = $(window).width(),
                                screenWidth = screen.width,
                                absDiff = Math.abs(screenWidth - windowWidth),
                                marginError = screenWidth * percentErrorMargin;

                            // check if the video is suddenly not really fullscreen
                            if (absDiff > marginError) {
                                // manually exit
                                t.exitFullScreen();
                            } else {
                                // test again
                                setTimeout(checkFullscreen, 500);
                            }
                        }

                    }, 1000);
                }

            } else if (t.fullscreeMode == 'fullwindow') {
                // move into position

            }

            // make full size
            t.container
                .addClass('mejs-container-fullscreen')
                .width('100%')
                .height('100%');
            //.css({position: 'fixed', left: 0, top: 0, right: 0, bottom: 0, overflow: 'hidden', width: '100%', height: '100%', 'z-index': 1000});

            // Only needed for safari 5.1 native full screen, can cause display issues elsewhere
            // Actually, it seems to be needed for IE8, too
            //if (mejs.MediaFeatures.hasTrueNativeFullScreen) {
            t.containerSizeTimeout = setTimeout(function () {
                t.container.css({width: '100%', height: '100%'});
                t.setControlsSize();
            }, 500);
            //}

            if (t.media.pluginType === 'native') {
                t.$media
                    .width('100%')
                    .height('100%');
            } else {
                t.container.find('.mejs-shim')
                    .width('100%')
                    .height('100%');

                setTimeout(function () {
                    var win = $(window),
                        winW = win.width(),
                        winH = win.height();

                    t.media.setVideoSize(winW, winH);
                }, 500);
            }

            t.layers.children('div')
                .width('100%')
                .height('100%');

            if (t.fullscreenBtn) {
                t.fullscreenBtn
                    .removeClass('mejs-fullscreen')
                    .addClass('mejs-unfullscreen');
            }

            t.setControlsSize();
            t.isFullScreen = true;

            t.container.find('.mejs-captions-text').css('font-size', screen.width / t.width * 1.00 * 100 + '%');
            t.container.find('.mejs-captions-position').css('bottom', '45px');

            t.container.trigger('enteredfullscreen');
        },

        exitFullScreen: function () {

            var t = this;

            // Prevent container from attempting to stretch a second time
            clearTimeout(t.containerSizeTimeout);

            // firefox can't adjust plugins
            /*
            if (t.media.pluginType !== 'native' && mejs.MediaFeatures.isFirefox) {
                t.media.setFullscreen(false);
                //player.isFullScreen = false;
                return;
            }
            */

            // come out of native fullscreen
            if (mejs.MediaFeatures.hasTrueNativeFullScreen && (mejs.MediaFeatures.isFullScreen() || t.isFullScreen)) {
                mejs.MediaFeatures.cancelFullScreen();
            }

            // restore scroll bars to document
            $(document.documentElement).removeClass('mejs-fullscreen');

            t.container
                .removeClass('mejs-container-fullscreen')
                .width(t.normalWidth)
                .height(t.normalHeight);

            if (t.media.pluginType === 'native') {
                t.$media
                    .width(t.normalWidth)
                    .height(t.normalHeight);
            } else {
                t.container.find('.mejs-shim')
                    .width(t.normalWidth)
                    .height(t.normalHeight);

                t.media.setVideoSize(t.normalWidth, t.normalHeight);
            }

            t.layers.children('div')
                .width(t.normalWidth)
                .height(t.normalHeight);

            t.fullscreenBtn
                .removeClass('mejs-unfullscreen')
                .addClass('mejs-fullscreen');

            t.setControlsSize();
            t.isFullScreen = false;

            t.container.find('.mejs-captions-text').css('font-size', '');
            t.container.find('.mejs-captions-position').css('bottom', '');

            t.container.trigger('exitedfullscreen');
        }
    });

})(mejs.$);
