


var centa_desk_util = (function () {


    function isMobile() { 
        var a = navigator.userAgent || navigator.vendor || window.opera;
        if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4)))
        {
            return true;
        } 
        else {
            return false;            
        }  
    }

    ///////////////
    function isIENight() {
        var browser = getBrowser().split(' ');
        if ((browser[0] == "IE" || browser[0].indexOf('MSIE') > -1) && browser[1] == 9) {
            return true;
        }
        else {
            return false;
        }
    }

    function isBelowIEEight() {
        var browser = getBrowser().split(' ');
        if ((browser[0] == "IE" || browser[0].indexOf('MSIE') > -1) && browser[1] <= 8) {
            return true;
        }
        else {
            return false;
        }
    };

    function getBrowser() {
        var ua = navigator.userAgent, tem,
            M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*([\d\.]+)/i) || [];
        if (/trident/i.test(M[1])) {
            tem = /\brv[ :]+(\d+(\.\d+)?)/g.exec(ua) || [];
            return 'IE ' + (tem[1] || '');
        }
        M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
        if ((tem = ua.match(/version\/([\.\d]+)/i)) != null) M[2] = tem[1];
        return M.join(' ');
    }

    ///////////////


    //var webSetting = { serverPath: "http://hk.centanet.com/findproperty", culturalInfo: $("#culture-info").val() };
    var webSetting = { serverPath: $("#server-path").val(), culturalInfo: $("#culture-info").val() };
    function ViewerOverlay(parent) {
        var $body = $("body");
        var clsPartial = { wrapper: 'ags-viewWrapperPart', cntHolder: 'ags-viewContentHolderPart', centerWrapper: 'ags-centerContentPart', closeBtn: 'ags-viewWrapperClosePart' };
        var clsFull = { wrapper: 'ags-viewWrapper', cntHolder: 'ags-viewContentHolder', centerWrapper: 'ags-centerContent', closeBtn: 'ags-viewWrapperClose' };
        var isShown = false;
        var isFull = parent ? false : true;
        var $parent = isFull ? $body : $(parent);
        var cls = isFull ? clsFull : clsPartial;
        var $viewWrapper = $("<div style='display:none;' >").addClass(cls.wrapper);
        var $viewContentHolder = $("<div>").addClass(cls.cntHolder);
        var $closeBtn = $("<div>").addClass(cls.closeBtn); //.text("X");
        var bodyScrollTop = $body.scrollTop();
        //
        var $centerDiv = $("<div>").addClass('ags-centerDiv'); //ags-centerDiv as identifier only
        $centerDiv.addClass(cls.centerWrapper); //ags-centerContent as style
        $centerDiv.click(function (e) {
            e.stopPropagation(); //prevent the click propagates to parent and trigger the close of the entire overlay
        });
        $viewContentHolder.append($centerDiv);
        //

        $viewWrapper.click(toggleView);
        $closeBtn.click(toggleView);
        $viewWrapper.append($viewContentHolder);
        $viewWrapper.append($closeBtn);

        $($parent).prepend($viewWrapper);

        /////////

        function addToggler(selector) {
            $(selector).click(toggleView);
        }

        function setListeners(selector, evName, callback) {
            if (typeof (evName) === "undefined") {
                logMsg('unspecified event name for selector: ' + selector);
                return;
            }

            if (typeof (callback) === "function") {
                $(selector).on(evName, { container: this }, callback);
            }

        }

        function toggleView(e) {
            e.stopPropagation();
            if (isShown) {
                showView(false);
            } else {
                showView(true);
            }
        }

        function show(content, widthRation, heightRation) {
            if (typeof (content) !== "undefined") {
                setContentCenter(content, widthRation, heightRation);
            }
            showView(true);
        }

        function setContentCenter(content, widthRatio, heightRatio) {

            if (widthRatio) {
                $centerDiv.css({ width: widthRatio + "%", left: ((100 - widthRatio) / 2) + "%" });
            }
            if (heightRatio) {
                $centerDiv.css({ height: heightRatio + "%", top: ((100 - heightRatio) / 2) + "%" });
            }

            $centerDiv.html("").append(content);
        }

        function clearContent() {
            $centerDiv.html("");
        }

        function hide() {
            showView(false);
        }


        function showView(show) {
            if (show) {
                if (isFull) {
                    bodyScrollTop = $body.scrollTop();
                    $body.addClass("ags-noScroll");
                }
                $viewWrapper.show();
                isShown = true;
            } else {
                if (isFull) {
                    $body.removeClass("ags-noScroll");
                    $body.scrollTop(bodyScrollTop);
                }
                $viewWrapper.hide();
                isShown = false;
            }
        }

        function append(content) {
            $centerDiv.append(content);
        }

        function prepend(content) {
            $centerDiv.prepend(content);
        }


        function getContentHolderDimension() {
            return { width: $centerDiv.width(), height: $centerDiv.height() };
        }

        //
        function logMsg(msg) {
            if (typeof (console) !== "undefined") {
                console.log(msg);
            } else {
                alert("noconsole. log msg:" + msg);
            }
        }

        function zIndex(newIndex) {
            if (newIndex) {
                $viewWrapper.css({ "z-index": newIndex });
            }
            return $viewWrapper.css("z-index");
        }

        function vCenterToParent($elm) {
            var $p = $elm.parent();
            var pH = $p.height();
            var cH = $elm.height();
            $elm.css({ top: Math.floor((pH - cH) / 2) + "px" });
        }
        /////////////////////////////

        var inst = {
            wrapper: $viewWrapper
            //, contentHolder: $viewContentHolder
          , closeBtn: $closeBtn
          , visible: isShown
          , toggle: toggleView
          , clickToggler: addToggler
          , show: show
          , hide: hide
          , clearContent: clearContent
          , append: append
          , prepend: prepend
          , setListeners: setListeners
          , setCenterContent: setContentCenter
          , getContentHolderDimension: getContentHolderDimension
          , contentDiv: $centerDiv
          , zIndex: zIndex
          , vCenterToParent: vCenterToParent
        };

        return inst;

    }
    //end ViewerOverlay

    function videoPlayer($playerHolder, defaultOptions) {
        var enableIE9SurrogateFullScreen = false;
        var enableIE8SurrogateFullScreen = false;
        var defaultOpts = defaultOptions || {};
        var resList = [{ res: 360 }, { res: 480 }, { res: 720 }, { res: 1080}];
        var defaultRes = isMobile() ? resList[1] : resList[3];

        var hideBubbles = defaultOpts.hideBubbles === true;
        var hideResolutionMenu = defaultOpts.hideResolutionMenu === true;
        var autoLoop = defaultOpts.autoLoop === true;
        var vdoLogParam = typeof (defaultOpts.vdoLogParam) != "undefined" ? defaultOpts.vdoLogParam : "";

        var $container = $playerHolder;
        var keeper = {};

        //var video = '<video controls="controls" style="width:100%; height:100%;" autoplay="autoplay">' +
        //             '<source src="{{Path}}" type="video/mp4" />' +
        //             '<object style="width:100%; height:100%;" type="application/x-shockwave-flash" data="' + webSetting.serverPath + '/Content/mediaelement/flashmediaelement.swf"> <param name="allowFullScreen" value="true" /><param name="wmode" value="transparent" />' +
        //             '<param name="movie" value="' + webSetting.serverPath + '/Content/mediaelement/flashmediaelement.swf" />' +
        //             '<param name="flashvars" value="controls=true&amp;file={{Path}}" />' +
        //             '<img src="{{Thumbnail}}" style="width:100%; height:100%;" alt="No video playback capabilities" />' +
        //             '</object>' +
        //             '</video>';

        //var video = '<video controls="controls" style="width:100%; height:100%;" autoplay="autoplay" poster="{{Thumbnail}}" preload="none" playsinline webkit-playsinline>' +
        //             '<source src="{{Path}}" type="video/mp4" />' +
        //             '<object style="width:100%; height:100%;" type="application/x-shockwave-flash" data="' + webSetting.serverPath + '/Content/mediaelement/flashmediaelement.swf"> <param name="allowFullScreen" value="true" /><param name="wmode" value="transparent" />' +
        //             '<param name="movie" value="' + webSetting.serverPath + '/Content/mediaelement/flashmediaelement.swf" />' +
        //             '<param name="flashvars" value="controls=true&amp;file={{Path}}" />' +
        //             '<img src="{{Thumbnail}}" style="width:100%; height:100%;" alt="No video playback capabilities" />' +
        //             '</object>' +
        //             '</video>';

        var video = '<video id="player1" style="width:100%; height:100%;" preload="none" style="max-width: 100%" controls poster="{{Thumbnail}}" playsinline webkit-playsinline>' +
                    '<source src="{{Path}}" type="video/mp4">' +
                    '</video>'
        var currentSrcID;

        function setVideo($holder, typeSource, imgPath, options) {
            var opts = options || {};
            var resVal = opts.res || defaultRes;
            currentSrcID = opts.srcID;
            var startAt = opts.startAt || 0;
            var isFullScreen = opts.isFullScreen === true;
            var videoWxH = null;

            if (typeof (opts.videoWidth) != "undefined" && typeof (opts.videoHeight) != "undefined") {
                videoWxH = { videoWidth: opts.videoWidth, videoHeight: opts.videoHeight };
            }
            var isAlwaysShowControl = opts.alwaysShowControls === true; // || isBelowIEEight();
            var prev = keeper[currentSrcID];
            if (!prev) {
                var $player = $("<div>").css({ position: "relative", width: "100%", height: "100%" }).addClass("centaVideoInner");

                var videoPath = getVideoUrlByRes(typeSource, resVal);
                if (videoPath == "" || videoPath == null) {
                    var resIndex = -1;
                    $.each(resList, function (index, item) {

                        if (resVal.res == item.res) {
                            resIndex = index;
                        }
                    });

                    for (var i = resIndex - 1; i >= 0; i--) {
                        resVal = resList[i];
                        videoPath = getVideoUrlByRes(typeSource, resVal);
                        if (videoPath != "" && videoPath != null) {
                            break;
                        }
                    }
                }

                $player.html(video.replace(/{{Path}}/g, videoPath).replace(/{{Thumbnail}}/g, imgPath));
                var $videoTag = $player.find('video');
                var mediaOpts = {
                    autoRewind: false,
                    alwaysShowControls: isAlwaysShowControl,
                    loop: autoLoop,
                    success: function (mediaElement, domObject) {

                        if (typeof (opts.mute) != "undefined") {
                            mediaElement.setMuted(opts.mute);
                        }

                        if (isBelowIEEight()) {
                            setTimeout(function () {
                                $videoTag.trigger("mouseenter");
                                $videoTag.trigger("mouseleave");
                            }, 3000);
                        }

                        if (typeof (currentSrcID) != "undefined") {
                            keeper[currentSrcID] = {
                                holderElm: $player,
                                mediaElm: mediaElement,
                                playing: false,
                                beginRes: resVal,
                                newRes: resVal,
                                currentTime: startAt,
                                constructParams: { typeSource: typeSource, imgPath: imgPath, options: opts },
                                hasResChanged: function () {
                                    return this.beginRes.res != this.newRes.res;
                                }
                            };
                        }

                        mediaElement.addEventListener('canplay', function () {
                            mediaElement.play();
                        }, false);

                        mediaElement.addEventListener('play', function () {
                            //showTheLessMaxBubble(mediaElement.currentTime);
                            updateCurrentKeeper(function (rec) {
                                rec.playing = true;
                                return rec;
                            });
                            if (typeof (currentSrcID) != "undefined") {
                                var kp = keeper[currentSrcID];
                                if (kp && kp.hasResChanged()) {
                                    setVideoWithNewSource();
                                }
                            }
                        }, false);

                        mediaElement.addEventListener('pause', function () {
                            updateCurrentKeeper(function (rec) {
                                rec.playing = false;
                                return rec;
                            });
                        }, false);

                        mediaElement.addEventListener('loadeddata', function () {
                            mediaElement.setCurrentTime(getCurrentStartAt());

                            if (isReCreate()) {


                                if (!isBelowIEEight()) {
                                    if (!hideBubbles) {
                                        addTimelineMarker($player, typeSource.Meta, mediaElement);
                                    }

                                    if (!hideResolutionMenu) {
                                        addResolutionMenu($player, mediaElement, { res: resVal });
                                    }
                                }

                                var isIE8 = isBelowIEEight();
                                var isIE9 = isIENight();
                                var $fullScreenBtn = $(".mejs-fullscreen-button");
                                if (isIE8 || isIE9) {
                                    if (isIE8 && !enableIE8SurrogateFullScreen) {
                                        $(".mejs-fullscreen-button").hide();
                                    }
                                    if (isIE8) { $fullScreenBtn.addClass("ie8Class"); }
                                    if (isIE9) { $fullScreenBtn.addClass("ie9Class"); }
                                    var $fsCover = $("<div>").addClass("centaControlCover");
                                    $fullScreenBtn.append($fsCover);
                                    $fsCover.click(function (e) {
                                        e.stopPropagation();
                                    });
                                    if ((isIE9 && enableIE9SurrogateFullScreen) || (isIE8 && enableIE8SurrogateFullScreen)) {
                                        addSurrogateFullscreenBtn($player);
                                    }
                                } else {
                                    $fullScreenBtn.addClass("otherBrowserClass");
                                }

                                $fullScreenBtn.click(function () {
                                    screenSizeCheckByBtnClass($fullScreenBtn);
                                });
                                if (isFullScreen) {
                                    $fullScreenBtn.click(); //enter fullscreen
                                }
                                thisInst.videoLoaded({ isReCreate: true });
                            } else {
                                thisInst.videoLoaded({ isReCreate: false });
                            }

                            //hide resolution that has no videoUrl
                            var kp = getCurrentKeeper();
                            if (kp) {
                                var ts = kp.constructParams.typeSource;
                                var $resMenu = $container.find(".resolutionMenuItemList");
                                $resMenu.find("li").show();

                                if (ts.Vdo1080URL == null || ts.Vdo1080URL == "") {
                                    $resMenu.find(".res_1080").hide();
                                }
                                if (ts.Vdo720URL == null || ts.Vdo720URL == "") {
                                    $resMenu.find(".res_720").hide();
                                }
                                if (ts.Vdo480URL == null || ts.Vdo480URL == "") {
                                    $resMenu.find(".res_480").hide();
                                }
                                if (ts.Vdo360URL == null || ts.Vdo360URL == "") {
                                    $resMenu.find(".res_360").hide();
                                }
                            }

                        });

                        mediaElement.addEventListener('timeupdate', function () {
                            var intCurrentTime = parseInt(mediaElement.currentTime);
                            updateCurrentKeeper(function (rec) {
                                rec.currentTime = intCurrentTime;
                                return rec;
                            });
                        }, false);

                    }
                };

                if (videoWxH) {
                    $.extend(mediaOpts, videoWxH);
                }

                if (isBelowIEEight()) {
                    $.extend(mediaOpts, { features: ['playpause', 'current', 'progress', 'duration', 'tracks', 'volume'] });
                }

                $videoTag.mediaelementplayer(mediaOpts);
                $holder.append($player);
            } else {
                //resume
                if (!prev.hasResChanged()) {
                    prev.holderElm.show();
                    if (isBelowIEEight()) {
                        prev.holderElm.find(".mejs-playpause-button button[title='Play']").click();
                    } else {
                        prev.mediaElm.play();
                    }
                } else {
                    setVideoWithNewSource();
                }
            }
        }

        function showTheLessMaxBubble(currentTime) {
            var kp = getCurrentKeeper();
            if (kp) {
                var $tMarkers = kp.holderElm.find(".timeMarker");
                $tMarkers.each(function () {
                    var $this = $(this);
                    var dt = $this.attr("data-time") * 1;
                    if (dt < currentTime) {
                        $this.trigger("mouseover");
                    }
                });
            }
        }

        function screenSizeCheckByBtnClass($fsBtn) {
            setTimeout(function () {
                var isFull = $fsBtn.hasClass("mejs-unfullscreen");
                thisInst.screenSizeChange({ isFullScreen: isFull, action: "fsBtn" });
            }, 200);
        }

        function getVideoUrlByRes(typeSource, res) {
            var url = "";
            switch (res.res) {
                case 360:
                    url = typeSource.Vdo360URL;
                    break;
                case 480:
                    url = typeSource.Vdo480URL;
                    break;
                case 720:
                    url = typeSource.Vdo720URL;
                    break;
                case 1080:
                    url = typeSource.Vdo1080URL;
                    break;
                default:
                    url = typeSource.Vdo360URL;
                    break;
            }

            //console.log(url, '<url, res.res >', res.res,'typesource',typeSource);
            if (url == null) {
                return null;
            }
            return url + "?" + vdoLogParam;
        }



        function setVideoWithNewSource() {
            var kp = getCurrentKeeper();
            if (!kp) { return; }
            var isFull = kp.holderElm.find(".mejs-fullscreen-button").hasClass("mejs-unfullscreen");
            var cparams = kp.constructParams;
            cparams.options.startAt = kp.currentTime;
            cparams.options.res = kp.newRes;
            cparams.options.isFullScreen = isFull;

            if (isBelowIEEight()) {
                cparams.options.reCreate = true;
                kp.holderElm.remove();
                updateCurrentKeeper(function () {
                    return null;
                });
                setVideo($playerHolder, cparams.typeSource, cparams.imgPath, cparams.options);
            } else {
                cparams.options.reCreate = false;
                kp.beginRes = kp.newRes;
                kp.mediaElm.setSrc(getVideoUrlByRes(cparams.typeSource, kp.newRes));
            }

        }

        function isReCreate() {
            var kp = getCurrentKeeper();
            if (kp) {
                var recreate = kp.constructParams.options.reCreate;
                if (typeof (recreate) != "undefined") {
                    return recreate;
                }
            }
            return true;
        }

        function getCurrentStartAt() {
            var kp = getCurrentKeeper();
            if (kp) {
                var startAt = kp.constructParams.options.startAt;
                if (typeof (startAt) != "undefined") {
                    return startAt;
                }
            }
            return 0;
        }
        function getCurrentKeeper() {
            if (typeof (currentSrcID) != "undefined") {
                return keeper[currentSrcID];
            }
        }

        function updateCurrentKeeper(updateFunc) {
            if (typeof (currentSrcID) != "undefined") {
                var rec = keeper[currentSrcID];
                if (rec) {
                    keeper[currentSrcID] = updateFunc(rec);
                }
            }
        }

        function hideCurrentPlayer() {
            var rec = keeper[currentSrcID];
            if (rec) {
                //if (isBelowIEEight()) {
                //    rec.holderElm.find(".mejs-playpause-button button[title='Pause']").click();
                //} else {
                //    rec.mediaElm.stop();
                //}
                pause();
                rec.holderElm.hide();
            }
        }

        function pause() {
            var rec = keeper[currentSrcID];
            if (rec) {
                if (isBelowIEEight()) {
                    rec.holderElm.find(".mejs-playpause-button button[title='Pause']").click();
                } else {
                    rec.mediaElm.stop();
                }
            }
        }

        function showPlayerIfExists(srcID) {
            var rec = keeper[srcID];
            if (rec) {
                rec.holderElm.show();
                thisInst.show();
            }
        }

        //surrogate fullscreen
        function addSurrogateFullscreenBtn($holder) {
            var kp = getCurrentKeeper();
            var $holder = kp.holderElm;
            var cparams = kp.constructParams;

            var $mejs_controls = $holder.find(".mejs-controls");
            var $div = $("<div>").addClass("surrogateFullScreenBtn full");
            var isIE8 = isBelowIEEight();
            var isIE9 = isIENight();
            if (isIE8) { $div.addClass("ie8Class"); }
            if (isIE9) { $div.addClass("ie9Class"); }

            $div.click(function () {
                var isUnfull = $(this).hasClass("unfull");
                if (isUnfull) {
                    thisInst.screenSizeChange({ isFullScreen: true, action: "surrogate" });
                } else {
                    var fsOlay = centa_desk_util.overlay();
                    fsOlay.closeBtn.hide();
                    var $testHolder = $("<div>").css({ width: "100%", height: "100%", background: "red" });
                    fsOlay.show($testHolder, 100, 100);
                    var fsVideo = centa_desk_util.videoPlayer($testHolder, { videoWidth: $testHolder.width(), videoHeight: $testHolder.height() });
                    fsVideo.videoLoaded = function (args) {
                        if (args.isReCreate == true) {
                            $testHolder.find(".surrogateFullScreenBtn").removeClass("full").addClass("unfull");
                        }
                    };
                    fsVideo.screenSizeChange = function (args) {
                        fsOlay.hide();
                    };
                    fsVideo.setVideo(cparams.typeSource, cparams.imgPath, currentSrcID, { startAt: thisInst.getCurrentTime() });

                    fsOlay.zIndex(123456789);
                }
            });

            $mejs_controls.append($div);
        }
        //end surrogate fullscreen

        //for resolution
        function addResolutionMenu($holder, mediaPlayer, options) {
            var opts = options || {};
            var resVal = opts.res || defaultRes;
            var $mejs_controls = $holder.find(".mejs-controls");
            var $resolutionMenu = $("<div>").addClass("resolutionMenu");
            var $itemListHolder = $("<div>").addClass("resolutionMenuItemList");
            var $dispay = $("<p>").css({ "width": "100%", "text-align": "center" }).text(resVal.res + "p");
            var $ul = $("<ul>");
            var length = resList.length;
            for (var i = 0; i < length; i++) {
                var item = resList[length - i - 1];
                var $li = $("<li>").text(item.res + "p").addClass("res_" + item.res);
                if (item.res == resVal.res) {
                    $li.addClass("selected");
                }
                $ul.append($li);
 
                $li.click(function (arg, player) {
                    return function () { 
                        player.stop();
                        $dispay.text(arg.res + "p");
                        $ul.find("li").removeClass("selected");
                        $(this).addClass("selected");
                        updateCurrentKeeper(function (rec) {
                            rec.newRes = arg;
                            return rec;
                        });
                        var kp = getCurrentKeeper();
                        if (kp) {
                            if (kp.playing) {
                                setVideoWithNewSource();
                            }
                        }
                        player.play();
                    }
                }(item, mediaPlayer));
            }


            $mejs_controls.append($resolutionMenu);
            $resolutionMenu.append($dispay);
            $resolutionMenu.append($itemListHolder);
            $itemListHolder.append($ul);

            $resolutionMenu.click(function () {
                $itemListHolder.toggle();
            });

        }
        //end for resolution

        //for bubbles
        function addTimelineMarker($holder, jsonData, mediaPlayer) {

            if (!jsonData) {
                return;
            }

            var duration = mediaPlayer.duration;
            var json = jsonData;
            var $mejs_time_total = $holder.find(".mejs-time-total");
            var $mejs_time_rail = $holder.find(".mejs-time-rail");
            var $bubbleHolder = $("<div>").addClass("centaMejsBubbleHolder");
            $mejs_time_rail.append($bubbleHolder);
            for (var i = 0; i < json.length; i++) {
                var t = json[i].time.split(":");
                t = (t[0] * 1) * 60 * 60 + (t[1] * 1) * 60 + (t[2] * 1); //in seconds
                $bubbleHolder.append('<div class="timeMarker" data-time="' + t + '">'
                                     + '<div class="bubble hide" data-time="' + t + '"><div class="bubbleTriangle"></div><div class="bubbleContent">'
                                     + json[i].display + '</div></div>' + '</div>');
            }

            var $timeMarkers = $mejs_time_rail.find(".timeMarker");
            $timeMarkers.each(function (index) {
                var $this = $timeMarkers.eq(index);
                $this.height($mejs_time_total.height());
                var dtm = parseFloat($this.attr("data-time"));
                var percent = (dtm / duration) * 100;
                $this.css("left", percent + "%");
            });

            var $bubbles = $mejs_time_rail.find(".bubble");

            $bubbleHolder.on("mouseenter", ".timeMarker", function () {
                $bubbles.addClass("hide");
                $(this).find(".bubble").removeClass("hide");
            });

            $bubbleHolder.on("mouseleave", ".timeMarker", function () {
                var $bubble = $(this).find(".bubble");
                setTimeout(function () {
                    $bubble.addClass("hide");
                }, 3000);
            });

            $bubbleHolder.on("click", ".timeMarker", function () {
                var $this = $(this);
                var startTime = parseFloat($this.data("time"));
                mediaPlayer.setCurrentTime(startTime);

                $this.parent().find(".bubble").addClass("hide");
                $this.prev().removeClass("hide");

                return false;
            });

            mediaPlayer.addEventListener('timeupdate', function () {
                //var intCurrentTime = parseInt(mediaPlayer.currentTime);
                //var $timeMarker = $bubbleHolder.find(".timeMarker[data-time=" + intCurrentTime + "]");
                //if ($timeMarker.length > 0) {
                //    $timeMarker.trigger("mouseenter");
                //}
            });

            mediaPlayer.addEventListener('ended', function () {
                $bubbles.addClass("hide");
            });

        }
        //
        $(document).keydown(function (e) {
            var isEsc = e.which == 27;
            if (isEsc) {
                thisInst.screenSizeChange({ isFullScreen: false, action: "esc" });
            }
        });

        $(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange', function () {
            var kp = getCurrentKeeper();
            if (kp) {
                var $fullScreenBtn = kp.holderElm.find(".mejs-fullscreen-button");
                screenSizeCheckByBtnClass($fullScreenBtn);
            }
        });

        var thisInst = {
            show: function () {
                $container.show();
            },
            hide: function () {
                $container.hide();
                hideCurrentPlayer();
            },
            setVideo: function (typeSource, imgPath, srcID, options) {
                var opts = $.extend(defaultOpts, { srcID: srcID });
                if (options) {
                    $.extend(opts, options);
                }
                setVideo($container, typeSource, imgPath, opts);
            },
            clearVideo: function () {
                //$container.html("");
            },
            showIfHasRecord: showPlayerIfExists,
            screenSizeChange: function (args) {
                //to be replaced by user for event handling
            },
            videoLoaded: function (args) {
                //to be replaced by user for event handling
            },
            getCurrentTime: function () {
                var kp = getCurrentKeeper();
                if (kp) {
                    if (typeof (kp.currentTime) != "undefined") {
                        return kp.currentTime;
                    }
                }
                return 0;
            },
            clearHistory: function () {
                if (keeper != null) {
                    for (var n in keeper) {
                        var item = keeper[n];
                        item.mediaElm = null;
                        item.holderElm.remove();
                    }
                }
                keeper = {};
            },
            pauseVideo: function () {
                pause();
            }
        }
        return thisInst;
    }


    return {
        overlay: ViewerOverlay,
        videoPlayer: videoPlayer
    }
})();
