/*! @name videojs-contrib-ads @version 6.7.0 @license Apache-2.0 */
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("video.js"),require("global/window"),require("global/document")):"function"==typeof define&&define.amd?define(["video.js","global/window","global/document"],t):(e=e||self).videojsContribAds=t(e.videojs,e.window,e.document)}(this,function(e,t,n){"use strict";e=e&&e.hasOwnProperty("default")?e.default:e,t=t&&t.hasOwnProperty("default")?t.default:t,n=n&&n.hasOwnProperty("default")?n.default:n;var a="6.7.0";var o=function(e,t){t.isImmediatePropagationStopped=function(){return!0},t.cancelBubble=!0,t.isPropagationStopped=function(){return!0}},r=function(e,t,n){o(0,n),e.trigger({type:t+n.type,originalEvent:n})},i=function(e,t){e.ads.isInAdMode()&&(e.ads.isContentResuming()?e.ads._contentEnding&&r(e,"content",t):r(e,"ad",t))},s=function(e,t){e.ads.isInAdMode()?e.ads.isContentResuming()?(o(0,t),e.trigger("resumeended")):r(e,"ad",t):e.ads._contentHasEnded||e.ads.stitchedAds()||(r(e,"content",t),e.trigger("readyforpostroll"))},d=function(e,t){if(!("loadstart"===t.type&&!e.ads._hasThereBeenALoadStartDuringPlayerLife||"loadeddata"===t.type&&!e.ads._hasThereBeenALoadedData||"loadedmetadata"===t.type&&!e.ads._hasThereBeenALoadedMetaData))if(e.ads.inAdBreak())r(e,"ad",t);else{if(e.currentSrc()!==e.ads.contentSrc)return;r(e,"content",t)}},l=function(e,t){e.ads.inAdBreak()?r(e,"ad",t):e.ads.isContentResuming()&&r(e,"content",t)};function u(e){"playing"===e.type?i(this,e):"ended"===e.type?s(this,e):"loadstart"===e.type||"loadeddata"===e.type||"loadedmetadata"===e.type?d(this,e):"play"===e.type?l(this,e):this.ads.isInAdMode()&&(this.ads.isContentResuming()?r(this,"content",e):r(this,"ad",e))}var c=function(e,t){return t?encodeURIComponent(e):e},h=function(e,t,n){if(e&&e[n])for(var a=e[n],o=Object.keys(a),r=0;r<o.length;r++){t["{mediainfo."+n+"."+o[r]+"}"]=a[o[r]]}};var f={processMetadataTracks:function(e,t){for(var n=e.textTracks(),a=function(n){"metadata"===n.kind&&(e.ads.cueTextTracks.setMetadataTrackMode(n),t(e,n))},o=0;o<n.length;o++)a(n[o]);n.addEventListener("addtrack",function(e){a(e.track)})},setMetadataTrackMode:function(e){},getSupportedAdCue:function(e,t){return t},isSupportedAdCue:function(e,t){return!0},getCueId:function(e,t){return t.id}},p=function(e,t){return void 0!==t&&e.ads.includedCues[t]},g=function(e,t){void 0!==t&&""!==t&&(e.ads.includedCues[t]=!0)};function y(){!1!==this.ads._shouldBlockPlay&&(this.paused()||(this.ads.debug("Playback was canceled by cancelContentPlay"),this.pause()),this.ads._cancelledPlay=!0)}f.processAdTrack=function(t,n,a,o){t.ads.includedCues={};for(var r=0;r<n.length;r++){var i=n[r],s=this.getSupportedAdCue(t,i);if(!this.isSupportedAdCue(t,i))return void e.log.warn("Skipping as this is not a supported ad cue.",i);var d=this.getCueId(t,i),l=i.startTime;if(p(t,d))return void e.log("Skipping ad already seen with ID "+d);o&&o(t,s,d,l),a(t,s,d,l),g(t,d)}};var v={},m=e;v.isMiddlewareMediatorSupported=function(){return!m.browser.IS_IOS&&!m.browser.IS_ANDROID&&!!(m.use&&m.middleware&&m.middleware.TERMINATOR)},v.playMiddleware=function(t){return{setSource:function(e,t){t(null,e)},callPlay:function(){if(t.ads&&!0===t.ads._shouldBlockPlay)return t.ads.debug("Using playMiddleware to block content playback"),t.ads._playBlocked=!0,m.middleware.TERMINATOR},play:function(n,a){t.ads&&t.ads._playBlocked&&n?(t.ads.debug("Play call to Tech was terminated."),t.trigger("play"),t.addClass("vjs-has-started"),t.ads._playBlocked=!1):a&&a.catch&&a.catch(function(n){"NotAllowedError"!==n.name||e.browser.IS_SAFARI||t.trigger("pause")})}}},v.testHook=function(e){m=e};var A=v.playMiddleware,S=v.isMiddlewareMediatorSupported,_=function(){if(e.getPlugin)return Boolean(e.getPlugin("ads"));var t=e.getComponent("Player");return Boolean(t&&t.prototype.ads)};var P=function(){function e(){}return e.getState=function(t){if(t)return e.states_&&e.states_[t]?e.states_[t]:void 0},e.registerState=function(t,n){if("string"!=typeof t||!t)throw new Error('Illegal state name, "'+t+'"; must be a non-empty string.');return e.states_||(e.states_={}),e.states_[t]=n,n},e}(),b=function(){function t(e){this.player=e}t._getName=function(){return"Anonymous State"};var n=t.prototype;return n.transitionTo=function(e){var t=this.player;this.cleanup(t);var n=new e(t);t.ads._state=n,t.ads.debug(this.constructor._getName()+" -> "+n.constructor._getName());for(var a=arguments.length,o=new Array(a>1?a-1:0),r=1;r<a;r++)o[r-1]=arguments[r];n.init.apply(n,[t].concat(o))},n.init=function(){},n.cleanup=function(){},n.onPlay=function(){},n.onPlaying=function(){},n.onEnded=function(){},n.onAdEnded=function(){},n.onAdsReady=function(){e.log.warn("Unexpected adsready event")},n.onAdsError=function(){},n.onAdsCanceled=function(){},n.onAdTimeout=function(){},n.onAdStarted=function(){},n.onContentChanged=function(){},n.onContentResumed=function(){},n.onReadyForPostroll=function(){e.log.warn("Unexpected readyforpostroll event")},n.onNoPreroll=function(){},n.onNoPostroll=function(){},n.startLinearAdMode=function(){e.log.warn("Unexpected startLinearAdMode invocation (State via "+this.constructor._getName()+")")},n.endLinearAdMode=function(){e.log.warn("Unexpected endLinearAdMode invocation (State via "+this.constructor._getName()+")")},n.skipLinearAdMode=function(){e.log.warn("Unexpected skipLinearAdMode invocation (State via "+this.constructor._getName()+")")},n.isAdState=function(){throw new Error("isAdState unimplemented for "+this.constructor._getName())},n.isWaitingForAdBreak=function(){return!1},n.isContentResuming=function(){return!1},n.inAdBreak=function(){return!1},n.handleEvent=function(e){var t=this.player;"play"===e?this.onPlay(t):"adsready"===e?this.onAdsReady(t):"adserror"===e?this.onAdsError(t):"adscanceled"===e?this.onAdsCanceled(t):"adtimeout"===e?this.onAdTimeout(t):"ads-ad-started"===e?this.onAdStarted(t):"contentchanged"===e?this.onContentChanged(t):"contentresumed"===e?this.onContentResumed(t):"readyforpostroll"===e?this.onReadyForPostroll(t):"playing"===e?this.onPlaying(t):"ended"===e?this.onEnded(t):"nopreroll"===e?this.onNoPreroll(t):"nopostroll"===e?this.onNoPostroll(t):"adended"===e&&this.onAdEnded(t)},t}();function k(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}P.registerState("State",b);var C=function(e){function t(t){var n;return(n=e.call(this,t)||this).contentResuming=!1,n.waitingForAdBreak=!1,n}k(t,e);var n=t.prototype;return n.isAdState=function(){return!0},n.onPlaying=function(){var e=P.getState("ContentPlayback");this.contentResuming&&this.transitionTo(e)},n.onContentResumed=function(){var e=P.getState("ContentPlayback");this.contentResuming&&this.transitionTo(e)},n.isWaitingForAdBreak=function(){return this.waitingForAdBreak},n.isContentResuming=function(){return this.contentResuming},n.inAdBreak=function(){return!0===this.player.ads._inLinearAdMode},t}(b);P.registerState("AdState",C);var T=function(e){function t(){return e.apply(this,arguments)||this}k(t,e);var n=t.prototype;return n.isAdState=function(){return!1},n.onContentChanged=function(e){var t=P.getState("BeforePreroll"),n=P.getState("Preroll");e.ads.debug("Received contentchanged event (ContentState)"),e.paused()?this.transitionTo(t):(this.transitionTo(n,!1),e.pause(),e.ads._pausedOnContentupdate=!0)},t}(b);P.registerState("ContentState",T);var w,R=function(t){function n(){return t.apply(this,arguments)||this}k(n,t),n._getName=function(){return"AdsDone"};var a=n.prototype;return a.init=function(e){e.ads._contentHasEnded=!0,e.trigger("ended")},a.startLinearAdMode=function(){e.log.warn("Unexpected startLinearAdMode invocation (AdsDone)")},n}(P.getState("ContentState"));P.registerState("AdsDone",R);var B={start:function(t){t.ads.debug("Starting ad break"),t.ads._inLinearAdMode=!0,t.trigger("adstart"),t.ads.shouldTakeSnapshots()&&(t.ads.snapshot=function(t){var n;n=e.browser.IS_IOS&&t.ads.isLive(t)&&t.seekable().length>0?t.currentTime()-t.seekable().end(0):t.currentTime();var a=t.$(".vjs-tech"),o=t.textTracks?t.textTracks():[],r=[],i={ended:t.ended(),currentSrc:t.currentSrc(),sources:t.currentSources(),src:t.tech_.src(),currentTime:n,type:t.currentType()};a&&(i.style=a.getAttribute("style"));for(var s=0;s<o.length;s++){var d=o[s];r.push({track:d,mode:d.mode}),d.mode="disabled"}return i.suppressedTracks=r,i}(t)),t.ads.shouldPlayContentBehindAd(t)&&(t.ads.preAdVolume_=t.volume(),t.volume(0)),t.addClass("vjs-ad-playing"),t.hasClass("vjs-live")&&t.removeClass("vjs-live"),t.ads.removeNativePoster()},end:function(t,n){t.ads.debug("Ending ad break"),void 0===n&&(n=function(){}),t.ads.adType=null,t.ads._inLinearAdMode=!1,t.trigger("adend"),t.removeClass("vjs-ad-playing"),t.ads.isLive(t)&&t.addClass("vjs-live"),t.ads.shouldTakeSnapshots()?function(t,n){var a=t.ads.snapshot;if(void 0===n&&(n=function(){}),!0===t.ads.disableNextSnapshotRestore)return t.ads.disableNextSnapshotRestore=!1,delete t.ads.snapshot,void n();var o,r=t.$(".vjs-tech"),i=20,s=a.suppressedTracks,d=function(){for(var e=0;e<s.length;e++)(o=s[e]).track.mode=o.mode},l=function(){var n;if(e.browser.IS_IOS&&t.ads.isLive(t)){if(a.currentTime<0&&(n=t.seekable().length>0?t.seekable().end(0)+a.currentTime:t.currentTime(),t.currentTime(n)),t.paused()){var o=t.play();o&&o.catch&&o.catch(function(t){e.log.warn("Play promise rejected in IOS snapshot resume",t)})}}else if(a.ended)t.currentTime(t.duration());else{t.currentTime(a.currentTime);var r=t.play();r&&r.catch&&r.catch(function(t){e.log.warn("Play promise rejected in snapshot resume",t)})}t.ads.shouldRemoveAutoplay_&&(t.autoplay(!1),t.ads.shouldRemoveAutoplay_=!1)},u=function n(){if(t.off("contentcanplay",n),w&&t.clearTimeout(w),(r=t.el().querySelector(".vjs-tech")).readyState>1)return l();if(void 0===r.seekable)return l();if(r.seekable.length>0)return l();if(i--)t.setTimeout(n,50);else try{l()}catch(t){e.log.warn("Failed to resume the content after an advertisement",t)}};if("style"in a&&r.setAttribute("style",a.style||""),t.ads.videoElementRecycled())t.one("resumeended",function(){delete t.ads.snapshot,n()}),t.one("contentloadedmetadata",d),e.browser.IS_IOS&&!t.autoplay()&&(t.autoplay(!0),t.ads.shouldRemoveAutoplay_=!0),t.src(a.sources),t.one("contentcanplay",u),w=t.setTimeout(u,2e3);else{if(d(),!t.ended()){var c=t.play();c&&c.catch&&c.catch(function(t){e.log.warn("Play promise rejected in snapshot restore",t)})}delete t.ads.snapshot,n()}}(t,n):(t.volume(t.ads.preAdVolume_),n())}},L=function(t){function n(){return t.apply(this,arguments)||this}k(n,t),n._getName=function(){return"Preroll"};var a=n.prototype;return a.init=function(e,t,n){if(this.waitingForAdBreak=!0,e.addClass("vjs-ad-loading"),n||e.ads.nopreroll_)return this.resumeAfterNoPreroll(e);var a=e.ads.settings.timeout;"number"==typeof e.ads.settings.prerollTimeout&&(a=e.ads.settings.prerollTimeout),this._timeout=e.setTimeout(function(){e.trigger("adtimeout")},a),t?this.handleAdsReady():this.adsReady=!1},a.onAdsReady=function(t){t.ads.inAdBreak()?e.log.warn("Unexpected adsready event (Preroll)"):(t.ads.debug("Received adsready event (Preroll)"),this.handleAdsReady())},a.handleAdsReady=function(){this.adsReady=!0,this.readyForPreroll()},a.afterLoadStart=function(e){var t=this.player;t.ads._hasThereBeenALoadStartDuringPlayerLife?e():(t.ads.debug("Waiting for loadstart..."),t.one("loadstart",function(){t.ads.debug("Received loadstart event"),e()}))},a.noPreroll=function(){var e=this;this.afterLoadStart(function(){e.player.ads.debug("Skipping prerolls due to nopreroll event (Preroll)"),e.resumeAfterNoPreroll(e.player)})},a.readyForPreroll=function(){var e=this.player;this.afterLoadStart(function(){e.ads.debug("Triggered readyforpreroll event (Preroll)"),e.trigger("readyforpreroll")})},a.onAdsCanceled=function(e){var t=this;e.ads.debug("adscanceled (Preroll)"),this.afterLoadStart(function(){t.resumeAfterNoPreroll(e)})},a.onAdsError=function(t){var n=this;e.log("adserror (Preroll)"),this.inAdBreak()?t.ads.endLinearAdMode():this.afterLoadStart(function(){n.resumeAfterNoPreroll(t)})},a.startLinearAdMode=function(){var t=this.player;!this.adsReady||t.ads.inAdBreak()||this.isContentResuming()?e.log.warn("Unexpected startLinearAdMode invocation (Preroll)"):(this.clearTimeout(t),t.ads.adType="preroll",this.waitingForAdBreak=!1,B.start(t),t.ads._shouldBlockPlay=!1)},a.onAdStarted=function(e){e.removeClass("vjs-ad-loading")},a.endLinearAdMode=function(){var e=this.player;this.inAdBreak()&&(e.removeClass("vjs-ad-loading"),e.addClass("vjs-ad-content-resuming"),this.contentResuming=!0,B.end(e))},a.skipLinearAdMode=function(){var t=this,n=this.player;n.ads.inAdBreak()||this.isContentResuming()?e.log.warn("Unexpected skipLinearAdMode invocation"):this.afterLoadStart(function(){n.trigger("adskip"),n.ads.debug("skipLinearAdMode (Preroll)"),t.resumeAfterNoPreroll(n)})},a.onAdTimeout=function(e){var t=this;this.afterLoadStart(function(){e.ads.debug("adtimeout (Preroll)"),t.resumeAfterNoPreroll(e)})},a.onNoPreroll=function(t){t.ads.inAdBreak()||this.isContentResuming()?e.log.warn("Unexpected nopreroll event (Preroll)"):this.noPreroll()},a.resumeAfterNoPreroll=function(e){if(this.contentResuming=!0,e.ads._shouldBlockPlay=!1,this.cleanupPartial(e),e.paused()&&(e.ads._playRequested||e.ads._pausedOnContentupdate)){var t=e.play();t&&t.then&&t.then(null,function(e){})}},a.cleanup=function(t){t.ads._hasThereBeenALoadStartDuringPlayerLife||e.log.warn("Leaving Preroll state before loadstart event can cause issues."),this.cleanupPartial(t)},a.cleanupPartial=function(e){e.removeClass("vjs-ad-loading"),e.removeClass("vjs-ad-content-resuming"),this.clearTimeout(e)},a.clearTimeout=function(e){e.clearTimeout(this._timeout),this._timeout=null},n}(P.getState("AdState"));P.registerState("Preroll",L);var M=function(e){function t(){return e.apply(this,arguments)||this}k(t,e),t._getName=function(){return"BeforePreroll"};var n=t.prototype;return n.init=function(e){this.adsReady=!1,this.shouldResumeToContent=!1,e.ads._shouldBlockPlay=!0},n.onAdsReady=function(e){e.ads.debug("Received adsready event (BeforePreroll)"),this.adsReady=!0},n.onPlay=function(e){var t=P.getState("Preroll");e.ads.debug("Received play event (BeforePreroll)"),this.transitionTo(t,this.adsReady,this.shouldResumeToContent)},n.onAdsCanceled=function(e){e.ads.debug("adscanceled (BeforePreroll)"),this.shouldResumeToContent=!0},n.onAdsError=function(){this.player.ads.debug("adserror (BeforePreroll)"),this.shouldResumeToContent=!0},n.onNoPreroll=function(){this.player.ads.debug("Skipping prerolls due to nopreroll event (BeforePreroll)"),this.shouldResumeToContent=!0},n.skipLinearAdMode=function(){var e=this.player;e.trigger("adskip"),e.ads.debug("skipLinearAdMode (BeforePreroll)"),this.shouldResumeToContent=!0},n.onContentChanged=function(){this.init(this.player)},t}(P.getState("ContentState"));P.registerState("BeforePreroll",M);var j=function(e){function t(){return e.apply(this,arguments)||this}k(t,e),t._getName=function(){return"Midroll"};var n=t.prototype;return n.init=function(e){e.ads.adType="midroll",B.start(e),e.addClass("vjs-ad-loading")},n.onAdStarted=function(e){e.removeClass("vjs-ad-loading")},n.endLinearAdMode=function(){var e=this.player;this.inAdBreak()&&(this.contentResuming=!0,e.addClass("vjs-ad-content-resuming"),e.removeClass("vjs-ad-loading"),B.end(e))},n.onAdsError=function(e){this.inAdBreak()&&e.ads.endLinearAdMode()},n.cleanup=function(e){e.removeClass("vjs-ad-loading"),e.removeClass("vjs-ad-content-resuming")},t}(P.getState("AdState"));P.registerState("Midroll",j);var N=function(t){function n(){return t.apply(this,arguments)||this}k(n,t),n._getName=function(){return"Postroll"};var a=n.prototype;return a.init=function(e){if(this.waitingForAdBreak=!0,e.ads._contentEnding=!0,e.ads.nopostroll_){this.resumeContent(e);var t=P.getState("AdsDone");this.transitionTo(t)}else{e.addClass("vjs-ad-loading");var n=e.ads.settings.timeout;"number"==typeof e.ads.settings.postrollTimeout&&(n=e.ads.settings.postrollTimeout),this._postrollTimeout=e.setTimeout(function(){e.trigger("adtimeout")},n)}},a.startLinearAdMode=function(){var t=this.player;t.ads.inAdBreak()||this.isContentResuming()?e.log.warn("Unexpected startLinearAdMode invocation (Postroll)"):(t.ads.adType="postroll",t.clearTimeout(this._postrollTimeout),this.waitingForAdBreak=!1,B.start(t))},a.onAdStarted=function(e){e.removeClass("vjs-ad-loading")},a.endLinearAdMode=function(){var e=this,t=this.player,n=P.getState("AdsDone");this.inAdBreak()&&(t.removeClass("vjs-ad-loading"),this.resumeContent(t),B.end(t,function(){e.transitionTo(n)}))},a.skipLinearAdMode=function(){var t=this.player;t.ads.inAdBreak()||this.isContentResuming()?e.log.warn("Unexpected skipLinearAdMode invocation"):(t.ads.debug("Postroll abort (skipLinearAdMode)"),t.trigger("adskip"),this.abort(t))},a.onAdTimeout=function(e){e.ads.debug("Postroll abort (adtimeout)"),this.abort(e)},a.onAdsError=function(e){e.ads.debug("Postroll abort (adserror)"),e.ads.inAdBreak()?e.ads.endLinearAdMode():this.abort(e)},a.onContentChanged=function(e){if(this.isContentResuming()){var t=P.getState("BeforePreroll");this.transitionTo(t)}else if(!this.inAdBreak()){var n=P.getState("Preroll");this.transitionTo(n)}},a.onNoPostroll=function(t){this.isContentResuming()||this.inAdBreak()?e.log.warn("Unexpected nopostroll event (Postroll)"):this.abort(t)},a.resumeContent=function(e){this.contentResuming=!0,e.addClass("vjs-ad-content-resuming")},a.abort=function(e){var t=P.getState("AdsDone");this.resumeContent(e),e.removeClass("vjs-ad-loading"),this.transitionTo(t)},a.cleanup=function(e){e.removeClass("vjs-ad-content-resuming"),e.clearTimeout(this._postrollTimeout),e.ads._contentEnding=!1},n}(P.getState("AdState"));P.registerState("Postroll",N);var E=function(e){function t(){return e.apply(this,arguments)||this}k(t,e),t._getName=function(){return"ContentPlayback"};var n=t.prototype;return n.init=function(e){e.ads._shouldBlockPlay=!1},n.onAdsReady=function(e){e.ads.debug("Received adsready event (ContentPlayback)"),e.ads.nopreroll_||(e.ads.debug("Triggered readyforpreroll event (ContentPlayback)"),e.trigger("readyforpreroll"))},n.onReadyForPostroll=function(e){var t=P.getState("Postroll");e.ads.debug("Received readyforpostroll event"),this.transitionTo(t)},n.startLinearAdMode=function(){var e=P.getState("Midroll");this.transitionTo(e)},t}(P.getState("ContentState"));P.registerState("ContentPlayback",E);var I=function(e){function t(){return e.apply(this,arguments)||this}k(t,e),t._getName=function(){return"StitchedContentPlayback"};var n=t.prototype;return n.init=function(){this.player.ads._shouldBlockPlay=!1},n.onContentChanged=function(){this.player.ads.debug("Received contentchanged event ("+this.constructor._getName()+")")},n.startLinearAdMode=function(){var e=P.getState("StitchedAdRoll");this.transitionTo(e)},t}(P.getState("ContentState"));P.registerState("StitchedContentPlayback",I);var x=function(e){function t(){return e.apply(this,arguments)||this}k(t,e),t._getName=function(){return"StitchedAdRoll"};var n=t.prototype;return n.init=function(){this.waitingForAdBreak=!1,this.contentResuming=!1,this.player.ads.adType="stitched",B.start(this.player)},n.onPlaying=function(){},n.onContentResumed=function(){},n.onAdEnded=function(){this.endLinearAdMode(),this.player.trigger("ended")},n.endLinearAdMode=function(){var e=P.getState("StitchedContentPlayback");B.end(this.player),this.transitionTo(e)},t}(P.getState("AdState"));P.registerState("StitchedAdRoll",x);var D=v.isMiddlewareMediatorSupported,O=e.getTech("Html5").Events,F={timeout:5e3,prerollTimeout:void 0,postrollTimeout:void 0,debug:!1,stitchedAds:!1,contentIsLive:void 0,liveCuePoints:!0},U=function(o){var r=this,i=e.mergeOptions(F,o),s=[];O.concat(["firstplay","loadedalldata"]).forEach(function(e){-1===s.indexOf(e)&&s.push(e)}),r.on(s,u),D()||function(t,n){n&&e.log("Using cancelContentPlay to block content playback"),t.on("play",y)}(r,i.debug),r.setTimeout(function(){r.ads._hasThereBeenALoadStartDuringPlayerLife||""===r.src()||e.log.error("videojs-contrib-ads has not seen a loadstart event 5 seconds after being initialized, but a source is present. This indicates that videojs-contrib-ads was initialized too late. It must be initialized immediately after video.js in the same tick. As a result, some ads will not play and some media events will be incorrect. For more information, see http://videojs.github.io/videojs-contrib-ads/integrator/getting-started.html")},5e3),r.on("ended",function(){r.hasClass("vjs-has-started")||r.addClass("vjs-has-started")}),r.on("contenttimeupdate",function(){r.removeClass("vjs-waiting")}),r.on(["addurationchange","adcanplay"],function(){if(!r.ads.settings.stitchedAds&&!r.hasStarted()&&(!r.ads.snapshot||r.currentSrc()!==r.ads.snapshot.currentSrc)&&r.ads.inAdBreak()){var t=r.play();t&&t.catch&&t.catch(function(t){e.log.warn("Play promise rejected when playing ad",t)})}}),r.on("nopreroll",function(){r.ads.debug("Received nopreroll event"),r.ads.nopreroll_=!0}),r.on("nopostroll",function(){r.ads.debug("Received nopostroll event"),r.ads.nopostroll_=!0}),r.on("playing",function(){r.ads._cancelledPlay=!1,r.ads._pausedOnContentupdate=!1}),r.on("play",function(){r.ads._playRequested=!0}),r.one("loadstart",function(){r.ads._hasThereBeenALoadStartDuringPlayerLife=!0}),r.on("loadeddata",function(){r.ads._hasThereBeenALoadedData=!0}),r.on("loadedmetadata",function(){r.ads._hasThereBeenALoadedMetaData=!0}),r.ads=function(t){return{disableNextSnapshotRestore:!1,_contentEnding:!1,_contentHasEnded:!1,_hasThereBeenALoadStartDuringPlayerLife:!1,_hasThereBeenALoadedData:!1,_hasThereBeenALoadedMetaData:!1,_inLinearAdMode:!1,_shouldBlockPlay:!1,_playBlocked:!1,_playRequested:!1,adType:null,VERSION:a,reset:function(){t.ads.disableNextSnapshotRestore=!1,t.ads._contentEnding=!1,t.ads._contentHasEnded=!1,t.ads.snapshot=null,t.ads.adType=null,t.ads._hasThereBeenALoadedData=!1,t.ads._hasThereBeenALoadedMetaData=!1,t.ads._cancelledPlay=!1,t.ads._shouldBlockPlay=!1,t.ads._playBlocked=!1,t.ads.nopreroll_=!1,t.ads.nopostroll_=!1,t.ads._playRequested=!1},startLinearAdMode:function(){t.ads._state.startLinearAdMode()},endLinearAdMode:function(){t.ads._state.endLinearAdMode()},skipLinearAdMode:function(){t.ads._state.skipLinearAdMode()},stitchedAds:function(t){return void 0!==t&&(e.log.warn("Using player.ads.stitchedAds() as a setter is deprecated, it should be set as an option upon initialization of contrib-ads."),this.settings.stitchedAds=!!t),this.settings.stitchedAds},videoElementRecycled:function(){if(t.ads.shouldPlayContentBehindAd(t))return!1;if(!this.snapshot)throw new Error("You cannot use videoElementRecycled while there is no snapshot.");var e=t.tech_.src()!==this.snapshot.src,n=t.currentSrc()!==this.snapshot.currentSrc;return e||n},isLive:function(n){return void 0===n&&(n=t),"boolean"==typeof n.ads.settings.contentIsLive?n.ads.settings.contentIsLive:n.duration()===1/0||"8"===e.browser.IOS_VERSION&&0===n.duration()},shouldPlayContentBehindAd:function(n){if(void 0===n&&(n=t),n)return!!n.ads.settings.liveCuePoints&&!e.browser.IS_IOS&&!e.browser.IS_ANDROID&&n.duration()===1/0;throw new Error("shouldPlayContentBehindAd requires a player as a param")},shouldTakeSnapshots:function(e){return void 0===e&&(e=t),!this.shouldPlayContentBehindAd(e)&&!this.stitchedAds()},isInAdMode:function(){return this._state.isAdState()},isWaitingForAdBreak:function(){return this._state.isWaitingForAdBreak()},isContentResuming:function(){return this._state.isContentResuming()},isAdPlaying:function(){return this._state.inAdBreak()},inAdBreak:function(){return this._state.inAdBreak()},removeNativePoster:function(){var e=t.$(".vjs-tech");e&&e.removeAttribute("poster")},debug:function(){if(this.settings.debug){for(var t=arguments.length,n=new Array(t),a=0;a<t;a++)n[a]=arguments[a];1===n.length&&"string"==typeof n[0]?e.log("ADS: "+n[0]):e.log.apply(e,["ADS:"].concat(n))}}}}(r),r.ads.settings=i,i.stitchedAds=!!i.stitchedAds,i.stitchedAds?r.ads._state=new(P.getState("StitchedContentPlayback"))(r):r.ads._state=new(P.getState("BeforePreroll"))(r),r.ads._state.init(r),r.ads.cueTextTracks=f,r.ads.adMacroReplacement=function(a,o,r){var i=this,s={};a=a.replace(/{([^}=]+)=([^}]+)}/g,function(e,t,n){return s["{"+t+"}"]=n,"{"+t+"}"}),void 0===o&&(o=!1);var d={};for(var l in void 0!==r&&(d=r),d["{player.id}"]=this.options_["data-player"],d["{player.height}"]=this.currentHeight(),d["{player.width}"]=this.currentWidth(),d["{mediainfo.id}"]=this.mediainfo?this.mediainfo.id:"",d["{mediainfo.name}"]=this.mediainfo?this.mediainfo.name:"",d["{mediainfo.duration}"]=this.mediainfo?this.mediainfo.duration:"",d["{player.duration}"]=this.duration(),d["{player.pageUrl}"]=e.dom.isInFrame()?n.referrer:t.location.href,d["{playlistinfo.id}"]=this.playlistinfo?this.playlistinfo.id:"",d["{playlistinfo.name}"]=this.playlistinfo?this.playlistinfo.name:"",d["{timestamp}"]=(new Date).getTime(),d["{document.referrer}"]=n.referrer,d["{window.location.href}"]=t.location.href,d["{random}"]=Math.floor(1e12*Math.random()),["description","tags","reference_id","ad_keys"].forEach(function(e){i.mediainfo&&i.mediainfo[e]?d["{mediainfo."+e+"}"]=i.mediainfo[e]:s["{mediainfo."+e+"}"]?d["{mediainfo."+e+"}"]=s["{mediainfo."+e+"}"]:d["{mediainfo."+e+"}"]=""}),h(this.mediainfo,d,"custom_fields"),h(this.mediainfo,d,"customFields"),d)a=a.split(l).join(c(d[l],o));for(var u in a=a.replace(/{pageVariable\.([^}]+)}/g,function(n,a){for(var r,i=t,d=a.split("."),l=0;l<d.length;l++)l===d.length-1?r=i[d[l]]:i=i[d[l]];var u=typeof r;return null===r?"null":void 0===r?s["{pageVariable."+a+"}"]?s["{pageVariable."+a+"}"]:(e.log.warn('Page variable "'+a+'" not found'),""):"string"!==u&&"number"!==u&&"boolean"!==u?(e.log.warn('Page variable "'+a+'" is not a supported type'),""):c(String(r),o)}),s)a=a.replace(u,s[u]);return a}.bind(r),function(e){e.ads.contentSrc=e.currentSrc(),e.ads._seenInitialLoadstart=!1,e.on("loadstart",function(){if(!e.ads.inAdBreak()){var t=e.currentSrc();t!==e.ads.contentSrc&&(e.ads._seenInitialLoadstart&&e.trigger({type:"contentchanged"}),e.trigger({type:"contentupdate",oldValue:e.ads.contentSrc,newValue:t}),e.ads.contentSrc=t),e.ads._seenInitialLoadstart=!0}})}(r),r.on("contentchanged",r.ads.reset);var d=function(){var t=r.textTracks();if(!r.ads.shouldPlayContentBehindAd(r)&&r.ads.inAdBreak()&&r.tech_.featuresNativeTextTracks&&e.browser.IS_IOS&&!Array.isArray(r.textTracks()))for(var n=0;n<t.length;n++){var a=t[n];"showing"===a.mode&&(a.mode="disabled")}};r.ready(function(){r.textTracks().addEventListener("change",d)}),r.on(["play","playing","ended","adsready","adscanceled","adskip","adserror","adtimeout","adended","ads-ad-started","contentchanged","dispose","contentresumed","readyforpostroll","nopreroll","nopostroll"],function(e){r.ads._state.handleEvent(e.type)}),r.on("dispose",function(){r.ads.reset(),r.textTracks().removeEventListener("change",d)})};return U.VERSION=a,function(t){!_(e)&&((e.registerPlugin||e.plugin)("ads",t),S()&&!e.usingContribAdsMiddleware_&&(e.use("*",A),e.usingContribAdsMiddleware_=!0,e.log.debug("Play middleware has been registered with videojs")))}(U),U});(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('video.js')) :
	typeof define === 'function' && define.amd ? define(['video.js'], factory) :
	(global.videojsIma = factory(global.videojs));
}(this, (function (videojs) { 'use strict';

videojs = videojs && videojs.hasOwnProperty('default') ? videojs['default'] : videojs;

/**
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * IMA SDK integration plugin for Video.js. For more information see
 * https://www.github.com/googleads/videojs-ima
 */

/**
 * Wraps the video.js player for the plugin.
 *
 * @param {Object} player Video.js player instance.
 * @param {Object} adsPluginSettings Settings for the contrib-ads plugin.
 * @param {Controller} controller Reference to the parent controller.
 */
var PlayerWrapper = function PlayerWrapper(player, adsPluginSettings, controller) {
  /**
   * Instance of the video.js player.
   */
  this.vjsPlayer = player;

  /**
   * Plugin controller.
   */
  this.controller = controller;

  /**
   * Timer used to track content progress.
   */
  this.contentTrackingTimer = null;

  /**
   * True if our content video has completed, false otherwise.
   */
  this.contentComplete = false;

  /**
   * Handle to interval that repeatedly updates current time.
   */
  this.updateTimeIntervalHandle = null;

  /**
   * Interval (ms) to check for player resize for fluid support.
   */
  this.updateTimeInterval = 1000;

  /**
   * Handle to interval that repeatedly checks for seeking.
   */
  this.seekCheckIntervalHandle = null;

  /**
   * Interval (ms) on which to check if the user is seeking through the
   * content.
   */
  this.seekCheckInterval = 1000;

  /**
   * Handle to interval that repeatedly checks for player resize.
   */
  this.resizeCheckIntervalHandle = null;

  /**
   * Interval (ms) to check for player resize for fluid support.
   */
  this.resizeCheckInterval = 250;

  /**
   * Threshold by which to judge user seeking. We check every 1000 ms to see
   * if the user is seeking. In order for us to decide that they are *not*
   * seeking, the content video playhead must only change by 900-1100 ms
   * between checks. Any greater change and we assume the user is seeking
   * through the video.
   */
  this.seekThreshold = 100;

  /**
   * Content ended listeners passed by the publisher to the plugin. Publishers
   * should allow the plugin to handle content ended to ensure proper support
   * of custom ad playback.
   */
  this.contentEndedListeners = [];

  /**
   * Stores the content source so we can re-populate it manually after a
   * post-roll on iOS.
   */
  this.contentSource = '';

  /**
   * Stores the content source type so we can re-populate it manually after a
   * post-roll.
   */
  this.contentSourceType = '';

  /**
   * Stores data for the content playhead tracker.
   */
  this.contentPlayheadTracker = {
    currentTime: 0,
    previousTime: 0,
    seeking: false,
    duration: 0
  };

  /**
   * Player dimensions. Used in our resize check.
   */
  this.vjsPlayerDimensions = {
    width: this.getPlayerWidth(),
    height: this.getPlayerHeight()
  };

  /**
   * Video.js control bar.
   */
  this.vjsControls = this.vjsPlayer.getChild('controlBar');

  /**
   * Vanilla HTML5 video player underneath the video.js player.
   */
  this.h5Player = null;

  this.vjsPlayer.one('play', this.setUpPlayerIntervals.bind(this));
  this.boundContentEndedListener = this.localContentEndedListener.bind(this);
  this.vjsPlayer.on('contentended', this.boundContentEndedListener);
  this.vjsPlayer.on('dispose', this.playerDisposedListener.bind(this));
  this.vjsPlayer.on('readyforpreroll', this.onReadyForPreroll.bind(this));
  this.vjsPlayer.on('adtimeout', this.onAdTimeout.bind(this));
  this.vjsPlayer.ready(this.onPlayerReady.bind(this));

  if (this.controller.getSettings().requestMode === 'onPlay') {
    this.vjsPlayer.one('play', this.controller.requestAds.bind(this.controller));
  }

  this.vjsPlayer.ads(adsPluginSettings);
};

/**
 * Set up the intervals we use on the player.
 */
PlayerWrapper.prototype.setUpPlayerIntervals = function () {
  this.updateTimeIntervalHandle = setInterval(this.updateCurrentTime.bind(this), this.updateTimeInterval);
  this.seekCheckIntervalHandle = setInterval(this.checkForSeeking.bind(this), this.seekCheckInterval);
  this.resizeCheckIntervalHandle = setInterval(this.checkForResize.bind(this), this.resizeCheckInterval);
};

/**
 * Updates the current time of the video
 */
PlayerWrapper.prototype.updateCurrentTime = function () {
  if (!this.contentPlayheadTracker.seeking) {
    this.contentPlayheadTracker.currentTime = this.vjsPlayer.currentTime();
  }
};

/**
 * Detects when the user is seeking through a video.
 * This is used to prevent mid-rolls from playing while a user is seeking.
 *
 * There *is* a seeking property of the HTML5 video element, but it's not
 * properly implemented on all platforms (e.g. mobile safari), so we have to
 * check ourselves to be sure.
 */
PlayerWrapper.prototype.checkForSeeking = function () {
  var tempCurrentTime = this.vjsPlayer.currentTime();
  var diff = (tempCurrentTime - this.contentPlayheadTracker.previousTime) * 1000;
  if (Math.abs(diff) > this.seekCheckInterval + this.seekThreshold) {
    this.contentPlayheadTracker.seeking = true;
  } else {
    this.contentPlayheadTracker.seeking = false;
  }
  this.contentPlayheadTracker.previousTime = this.vjsPlayer.currentTime();
};

/**
 * Detects when the player is resized (for fluid support) and resizes the
 * ads manager to match.
 */
PlayerWrapper.prototype.checkForResize = function () {
  var currentWidth = this.getPlayerWidth();
  var currentHeight = this.getPlayerHeight();

  if (currentWidth != this.vjsPlayerDimensions.width || currentHeight != this.vjsPlayerDimensions.height) {
    this.vjsPlayerDimensions.width = currentWidth;
    this.vjsPlayerDimensions.height = currentHeight;
    this.controller.onPlayerResize(currentWidth, currentHeight);
  }
};

/**
 * Local content ended listener for contentComplete.
 */
PlayerWrapper.prototype.localContentEndedListener = function () {
  if (!this.contentComplete) {
    this.contentComplete = true;
    this.controller.onContentComplete();
  }

  for (var index in this.contentEndedListeners) {
    if (typeof this.contentEndedListeners[index] === 'function') {
      this.contentEndedListeners[index]();
    }
  }

  clearInterval(this.updateTimeIntervalHandle);
  clearInterval(this.seekCheckIntervalHandle);
  clearInterval(this.resizeCheckIntervalHandle);
  if (this.vjsPlayer.el()) {
    this.vjsPlayer.one('play', this.setUpPlayerIntervals.bind(this));
  }
};

/**
 * Called when it's time to play a post-roll but we don't have one to play.
 */
PlayerWrapper.prototype.onNoPostroll = function () {
  this.vjsPlayer.trigger('nopostroll');
};

/**
 * Detects when the video.js player has been disposed.
 */
PlayerWrapper.prototype.playerDisposedListener = function () {
  this.contentEndedListeners = [];
  this.controller.onPlayerDisposed();

  this.contentComplete = true;
  this.vjsPlayer.off('contentended', this.boundContentEndedListener);

  // Bug fix: https://github.com/googleads/videojs-ima/issues/306
  if (this.vjsPlayer.ads.adTimeoutTimeout) {
    clearTimeout(this.vjsPlayer.ads.adTimeoutTimeout);
  }

  var intervalsToClear = [this.updateTimeIntervalHandle, this.seekCheckIntervalHandle, this.resizeCheckIntervalHandle];
  for (var index in intervalsToClear) {
    if (intervalsToClear[index]) {
      clearInterval(intervalsToClear[index]);
    }
  }
};

/**
 * Start ad playback, or content video playback in the absence of a
 * pre-roll.
 */
PlayerWrapper.prototype.onReadyForPreroll = function () {
  this.controller.onPlayerReadyForPreroll();
};

/**
 * Detects if the ad has timed out.
 */
PlayerWrapper.prototype.onAdTimeout = function () {
  this.controller.onAdTimeout();
};

/**
 * Called when the player fires its 'ready' event.
 */
PlayerWrapper.prototype.onPlayerReady = function () {
  this.h5Player = document.getElementById(this.getPlayerId()).getElementsByClassName('vjs-tech')[0];

  // Detect inline options
  if (this.h5Player.hasAttribute('autoplay')) {
    this.controller.setSetting('adWillAutoPlay', true);
  }

  // Sync ad volume with player volume.
  this.onVolumeChange();
  this.vjsPlayer.on('fullscreenchange', this.onFullscreenChange.bind(this));
  this.vjsPlayer.on('volumechange', this.onVolumeChange.bind(this));

  this.controller.onPlayerReady();
};

/**
 * Listens for the video.js player to change its fullscreen status. This
 * keeps the fullscreen-ness of the AdContainer in sync with the player.
 */
PlayerWrapper.prototype.onFullscreenChange = function () {
  if (this.vjsPlayer.isFullscreen()) {
    this.controller.onPlayerEnterFullscreen();
  } else {
    this.controller.onPlayerExitFullscreen();
  }
};

/**
 * Listens for the video.js player to change its volume. This keeps the ad
 * volume in sync with the content volume if the volume of the player is
 * changed while content is playing.
 */
PlayerWrapper.prototype.onVolumeChange = function () {
  var newVolume = this.vjsPlayer.muted() ? 0 : this.vjsPlayer.volume();
  this.controller.onPlayerVolumeChanged(newVolume);
};

/**
 * Inject the ad container div into the DOM.
 *
 * @param{HTMLElement} adContainerDiv The ad container div.
 */
PlayerWrapper.prototype.injectAdContainerDiv = function (adContainerDiv) {
  this.vjsControls.el().parentNode.appendChild(adContainerDiv);
};

/**
 * @return {Object} The content player.
 */
PlayerWrapper.prototype.getContentPlayer = function () {
  return this.h5Player;
};

/**
 * @return {number} The volume, 0-1.
 */
PlayerWrapper.prototype.getVolume = function () {
  return this.vjsPlayer.muted() ? 0 : this.vjsPlayer.volume();
};

/**
 * Set the volume of the player. 0-1.
 *
 * @param {number} volume The new volume.
 */
PlayerWrapper.prototype.setVolume = function (volume) {
  this.vjsPlayer.volume(volume);
  if (volume == 0) {
    this.vjsPlayer.muted(true);
  } else {
    this.vjsPlayer.muted(false);
  }
};

/**
 * Ummute the player.
 */
PlayerWrapper.prototype.unmute = function () {
  this.vjsPlayer.muted(false);
};

/**
 * Mute the player.
 */
PlayerWrapper.prototype.mute = function () {
  this.vjsPlayer.muted(true);
};

/**
 * Play the video.
 */
PlayerWrapper.prototype.play = function () {
  this.vjsPlayer.play();
};

/**
 * Toggles playback of the video.
 */
PlayerWrapper.prototype.togglePlayback = function () {
  if (this.vjsPlayer.paused()) {
    this.vjsPlayer.play();
  } else {
    this.vjsPlayer.pause();
  }
};

/**
 * Get the player width.
 *
 * @return {number} The player's width.
 */
PlayerWrapper.prototype.getPlayerWidth = function () {
  var width = (getComputedStyle(this.vjsPlayer.el()) || {}).width;

  if (!width || parseFloat(width) === 0) {
    width = (this.vjsPlayer.el().getBoundingClientRect() || {}).width;
  }

  return parseFloat(width) || this.vjsPlayer.width();
};

/**
 * Get the player height.
 *
 * @return {number} The player's height.
 */
PlayerWrapper.prototype.getPlayerHeight = function () {
  var height = (getComputedStyle(this.vjsPlayer.el()) || {}).height;

  if (!height || parseFloat(height) === 0) {
    height = (this.vjsPlayer.el().getBoundingClientRect() || {}).height;
  }

  return parseFloat(height) || this.vjsPlayer.height();
};

/**
 * @return {Object} The vjs player's options object.
 */
PlayerWrapper.prototype.getPlayerOptions = function () {
  return this.vjsPlayer.options_;
};

/**
 * Returns the instance of the player id.
 * @return {string} The player id.
 */
PlayerWrapper.prototype.getPlayerId = function () {
  return this.vjsPlayer.id();
};

/**
 * Toggle fullscreen state.
 */
PlayerWrapper.prototype.toggleFullscreen = function () {
  if (this.vjsPlayer.isFullscreen()) {
    this.vjsPlayer.exitFullscreen();
  } else {
    this.vjsPlayer.requestFullscreen();
  }
};

/**
 * Returns the content playhead tracker.
 *
 * @return {Object} The content playhead tracker.
 */
PlayerWrapper.prototype.getContentPlayheadTracker = function () {
  return this.contentPlayheadTracker;
};

/**
 * Handles ad errors.
 *
 * @param {Object} adErrorEvent The ad error event thrown by the IMA SDK.
 */
PlayerWrapper.prototype.onAdError = function (adErrorEvent) {
  this.vjsControls.show();
  var errorMessage = adErrorEvent.getError !== undefined ? adErrorEvent.getError() : adErrorEvent.stack;
  this.vjsPlayer.trigger({ type: 'adserror', data: {
      AdError: errorMessage,
      AdErrorEvent: adErrorEvent
    } });
};

/**
 * Handles ad log messages.
 * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the IMA SDK.
 */
PlayerWrapper.prototype.onAdLog = function (adEvent) {
  var adData = adEvent.getAdData();
  var errorMessage = adData['adError'] !== undefined ? adData['adError'].getMessage() : undefined;
  this.vjsPlayer.trigger({ type: 'adslog', data: {
      AdError: errorMessage,
      AdEvent: adEvent
    } });
};

/**
 * Handles ad break starting.
 */
PlayerWrapper.prototype.onAdBreakStart = function () {
  this.contentSource = this.vjsPlayer.currentSrc();
  this.contentSourceType = this.vjsPlayer.currentType();
  this.vjsPlayer.off('contentended', this.boundContentEndedListener);
  this.vjsPlayer.ads.startLinearAdMode();
  this.vjsControls.hide();
  this.vjsPlayer.pause();
};

/**
 * Handles ad break ending.
 */
PlayerWrapper.prototype.onAdBreakEnd = function () {
  this.vjsPlayer.on('contentended', this.boundContentEndedListener);
  if (this.vjsPlayer.ads.inAdBreak()) {
    this.vjsPlayer.ads.endLinearAdMode();
  }
  this.vjsControls.show();
};

/**
 * Handles an individual ad start.
 */
PlayerWrapper.prototype.onAdStart = function () {
  this.vjsPlayer.trigger('ads-ad-started');
};

/**
 * Handles when all ads have finished playing.
 */
PlayerWrapper.prototype.onAllAdsCompleted = function () {
  if (this.contentComplete == true) {
    // The null check on this.contentSource was added to fix
    // an error when the post-roll was an empty VAST tag.
    if (this.contentSource && this.vjsPlayer.currentSrc() != this.contentSource) {
      this.vjsPlayer.src({
        src: this.contentSource,
        type: this.contentSourceType
      });
    }
    this.controller.onContentAndAdsCompleted();
  }
};

/**
 * Triggers adsready for contrib-ads.
 */
PlayerWrapper.prototype.onAdsReady = function () {
  this.vjsPlayer.trigger('adsready');
};

/**
 * Changes the player source.
 * @param {?string} contentSrc The URI for the content to be played. Leave
 *     blank to use the existing content.
 */
PlayerWrapper.prototype.changeSource = function (contentSrc) {
  // Only try to pause the player when initialised with a source already
  if (this.vjsPlayer.currentSrc()) {
    this.vjsPlayer.currentTime(0);
    this.vjsPlayer.pause();
  }
  if (contentSrc) {
    this.vjsPlayer.src(contentSrc);
  }
  this.vjsPlayer.one('loadedmetadata', this.seekContentToZero.bind(this));
};

/**
 * Seeks content to 00:00:00. This is used as an event handler for the
 * loadedmetadata event, since seeking is not possible until that event has
 * fired.
 */
PlayerWrapper.prototype.seekContentToZero = function () {
  this.vjsPlayer.currentTime(0);
};

/**
 * Triggers an event on the VJS player
 * @param  {string} name The event name.
 * @param  {Object} data The event data.
 */
PlayerWrapper.prototype.triggerPlayerEvent = function (name, data) {
  this.vjsPlayer.trigger(name, data);
};

/**
 * Listener JSDoc for ESLint. This listener can be passed to
 * addContentEndedListener.
 * @callback listener
 */

/**
 * Adds a listener for the 'contentended' event of the video player. This should
 * be used instead of setting an 'contentended' listener directly to ensure that
 * the ima can do proper cleanup of the SDK before other event listeners are
 * called.
 * @param {listener} listener The listener to be called when content
 *     completes.
 */
PlayerWrapper.prototype.addContentEndedListener = function (listener) {
  this.contentEndedListeners.push(listener);
};

/**
 * Reset the player.
 */
PlayerWrapper.prototype.reset = function () {
  // Attempts to remove the contentEndedListener before adding it.
  // This is to prevent an error where an erroring video caused multiple
  // contentEndedListeners to be added.
  this.vjsPlayer.off('contentended', this.boundContentEndedListener);

  this.vjsPlayer.on('contentended', this.boundContentEndedListener);
  this.vjsControls.show();
  if (this.vjsPlayer.ads.inAdBreak()) {
    this.vjsPlayer.ads.endLinearAdMode();
  }
  // Reset the content time we give the SDK. Fixes an issue where requesting
  // VMAP followed by VMAP would play the second mid-rolls as pre-rolls if
  // the first playthrough of the video passed the second response's
  // mid-roll time.
  this.contentPlayheadTracker.currentTime = 0;
  this.contentComplete = false;
};

/**
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * IMA SDK integration plugin for Video.js. For more information see
 * https://www.github.com/googleads/videojs-ima
 */

/**
 * Ad UI implementation.
 *
 * @param {Controller} controller Plugin controller.
 * @constructor
 * @struct
 * @final
 */
var AdUi = function AdUi(controller) {
  /**
   * Plugin controller.
   */
  this.controller = controller;

  /**
   * Div used as an ad container.
   */
  this.adContainerDiv = document.createElement('div');

  /**
   * Div used to display ad controls.
   */
  this.controlsDiv = document.createElement('div');

  /**
   * Div used to display ad countdown timer.
   */
  this.countdownDiv = document.createElement('div');

  /**
   * Div used to display add seek bar.
   */
  this.seekBarDiv = document.createElement('div');

  /**
   * Div used to display ad progress (in seek bar).
   */
  this.progressDiv = document.createElement('div');

  /**
   * Div used to display ad play/pause button.
   */
  this.playPauseDiv = document.createElement('div');

  /**
   * Div used to display ad mute button.
   */
  this.muteDiv = document.createElement('div');

  /**
   * Div used by the volume slider.
   */
  this.sliderDiv = document.createElement('div');

  /**
   * Volume slider level visuals
   */
  this.sliderLevelDiv = document.createElement('div');

  /**
   * Div used to display ad fullscreen button.
   */
  this.fullscreenDiv = document.createElement('div');

  /**
   * Bound event handler for onMouseUp.
   */
  this.boundOnMouseUp = this.onMouseUp.bind(this);

  /**
   * Bound event handler for onMouseMove.
   */
  this.boundOnMouseMove = this.onMouseMove.bind(this);

  /**
   * Stores data for the ad playhead tracker.
   */
  this.adPlayheadTracker = {
    'currentTime': 0,
    'duration': 0,
    'isPod': false,
    'adPosition': 0,
    'totalAds': 0
  };

  /**
   * Used to prefix videojs ima controls.
   */
  this.controlPrefix = this.controller.getPlayerId() + '_';

  /**
   * Boolean flag to show or hide the ad countdown timer.
   */
  this.showCountdown = true;
  if (this.controller.getSettings().showCountdown === false) {
    this.showCountdown = false;
  }

  /**
   * Boolean flag if the current ad is nonlinear.
   */
  this.isAdNonlinear = false;

  this.createAdContainer();
};

/**
 * Creates the ad container.
 */
AdUi.prototype.createAdContainer = function () {
  this.assignControlAttributes(this.adContainerDiv, 'ima-ad-container');
  this.adContainerDiv.style.position = 'absolute';
  this.adContainerDiv.style.zIndex = 1111;
  this.adContainerDiv.addEventListener('mouseenter', this.showAdControls.bind(this), false);
  this.adContainerDiv.addEventListener('mouseleave', this.hideAdControls.bind(this), false);
  this.adContainerDiv.addEventListener('click', this.onAdContainerClick.bind(this), false);
  this.createControls();
  this.controller.injectAdContainerDiv(this.adContainerDiv);
};

/**
 * Create the controls.
 */
AdUi.prototype.createControls = function () {
  this.assignControlAttributes(this.controlsDiv, 'ima-controls-div');
  this.controlsDiv.style.width = '100%';

  if (!this.controller.getIsMobile()) {
    this.assignControlAttributes(this.countdownDiv, 'ima-countdown-div');
    this.countdownDiv.innerHTML = this.controller.getSettings().adLabel;
    this.countdownDiv.style.display = this.showCountdown ? 'block' : 'none';
  } else {
    this.countdownDiv.style.display = 'none';
  }

  this.assignControlAttributes(this.seekBarDiv, 'ima-seek-bar-div');
  this.seekBarDiv.style.width = '100%';

  this.assignControlAttributes(this.progressDiv, 'ima-progress-div');

  this.assignControlAttributes(this.playPauseDiv, 'ima-play-pause-div');
  this.addClass(this.playPauseDiv, 'ima-playing');
  this.playPauseDiv.addEventListener('click', this.onAdPlayPauseClick.bind(this), false);

  this.assignControlAttributes(this.muteDiv, 'ima-mute-div');
  this.addClass(this.muteDiv, 'ima-non-muted');
  this.muteDiv.addEventListener('click', this.onAdMuteClick.bind(this), false);

  this.assignControlAttributes(this.sliderDiv, 'ima-slider-div');
  this.sliderDiv.addEventListener('mousedown', this.onAdVolumeSliderMouseDown.bind(this), false);

  // Hide volume slider controls on iOS as they aren't supported.
  if (this.controller.getIsIos()) {
    this.sliderDiv.style.display = 'none';
  }

  this.assignControlAttributes(this.sliderLevelDiv, 'ima-slider-level-div');

  this.assignControlAttributes(this.fullscreenDiv, 'ima-fullscreen-div');
  this.addClass(this.fullscreenDiv, 'ima-non-fullscreen');
  this.fullscreenDiv.addEventListener('click', this.onAdFullscreenClick.bind(this), false);

  this.adContainerDiv.appendChild(this.controlsDiv);
  this.controlsDiv.appendChild(this.countdownDiv);
  this.controlsDiv.appendChild(this.seekBarDiv);
  this.controlsDiv.appendChild(this.playPauseDiv);
  this.controlsDiv.appendChild(this.muteDiv);
  this.controlsDiv.appendChild(this.sliderDiv);
  this.controlsDiv.appendChild(this.fullscreenDiv);
  this.seekBarDiv.appendChild(this.progressDiv);
  this.sliderDiv.appendChild(this.sliderLevelDiv);
};

/**
 * Listener for clicks on the play/pause button during ad playback.
 */
AdUi.prototype.onAdPlayPauseClick = function () {
  this.controller.onAdPlayPauseClick();
};

/**
 * Listener for clicks on the play/pause button during ad playback.
 */
AdUi.prototype.onAdMuteClick = function () {
  this.controller.onAdMuteClick();
};

/**
 * Listener for clicks on the fullscreen button during ad playback.
 */
AdUi.prototype.onAdFullscreenClick = function () {
  this.controller.toggleFullscreen();
};

/**
 * Show pause and hide play button
 */
AdUi.prototype.onAdsPaused = function () {
  this.controller.sdkImpl.adPlaying = false;
  this.addClass(this.playPauseDiv, 'ima-paused');
  this.removeClass(this.playPauseDiv, 'ima-playing');
  this.showAdControls();
};

/**
 * Show pause and hide play button
 */
AdUi.prototype.onAdsResumed = function () {
  this.onAdsPlaying();
  this.showAdControls();
};

/**
 * Show play and hide pause button
 */
AdUi.prototype.onAdsPlaying = function () {
  this.controller.sdkImpl.adPlaying = true;
  this.addClass(this.playPauseDiv, 'ima-playing');
  this.removeClass(this.playPauseDiv, 'ima-paused');
};

/**
 * Takes data from the controller to update the UI.
 *
 * @param {number} currentTime Current time of the ad.
 * @param {number} remainingTime Remaining time of the ad.
 * @param {number} duration Duration of the ad.
 * @param {number} adPosition Index of the ad in the pod.
 * @param {number} totalAds Total number of ads in the pod.
 */
AdUi.prototype.updateAdUi = function (currentTime, remainingTime, duration, adPosition, totalAds) {
  // Update countdown timer data
  var remainingMinutes = Math.floor(remainingTime / 60);
  var remainingSeconds = Math.floor(remainingTime % 60);
  if (remainingSeconds.toString().length < 2) {
    remainingSeconds = '0' + remainingSeconds;
  }
  var podCount = ': ';
  if (totalAds > 1) {
    podCount = ' (' + adPosition + ' ' + this.controller.getSettings().adLabelNofN + ' ' + totalAds + '): ';
  }
  this.countdownDiv.innerHTML = this.controller.getSettings().adLabel + podCount + remainingMinutes + ':' + remainingSeconds;

  // Update UI
  var playProgressRatio = currentTime / duration;
  var playProgressPercent = playProgressRatio * 100;
  this.progressDiv.style.width = playProgressPercent + '%';
};

/**
 * Handles UI changes when the ad is unmuted.
 */
AdUi.prototype.unmute = function () {
  this.addClass(this.muteDiv, 'ima-non-muted');
  this.removeClass(this.muteDiv, 'ima-muted');
  this.sliderLevelDiv.style.width = this.controller.getPlayerVolume() * 100 + '%';
};

/**
 * Handles UI changes when the ad is muted.
 */
AdUi.prototype.mute = function () {
  this.addClass(this.muteDiv, 'ima-muted');
  this.removeClass(this.muteDiv, 'ima-non-muted');
  this.sliderLevelDiv.style.width = '0%';
};

/*
 * Listener for mouse down events during ad playback. Used for volume.
 */
AdUi.prototype.onAdVolumeSliderMouseDown = function () {
  document.addEventListener('mouseup', this.boundOnMouseUp, false);
  document.addEventListener('mousemove', this.boundOnMouseMove, false);
};

/*
 * Mouse movement listener used for volume slider.
 */
AdUi.prototype.onMouseMove = function (event) {
  this.changeVolume(event);
};

/*
 * Mouse release listener used for volume slider.
 */
AdUi.prototype.onMouseUp = function (event) {
  this.changeVolume(event);
  document.removeEventListener('mouseup', this.boundOnMouseUp);
  document.removeEventListener('mousemove', this.boundOnMouseMove);
};

/*
 * Utility function to set volume and associated UI
 */
AdUi.prototype.changeVolume = function (event) {
  var percent = (event.clientX - this.sliderDiv.getBoundingClientRect().left) / this.sliderDiv.offsetWidth;
  percent *= 100;
  // Bounds value 0-100 if mouse is outside slider region.
  percent = Math.min(Math.max(percent, 0), 100);
  this.sliderLevelDiv.style.width = percent + '%';
  if (this.percent == 0) {
    this.addClass(this.muteDiv, 'ima-muted');
    this.removeClass(this.muteDiv, 'ima-non-muted');
  } else {
    this.addClass(this.muteDiv, 'ima-non-muted');
    this.removeClass(this.muteDiv, 'ima-muted');
  }
  this.controller.setVolume(percent / 100); // 0-1
};

/**
 * Show the ad container.
 */
AdUi.prototype.showAdContainer = function () {
  this.adContainerDiv.style.display = 'block';
};

/**
 * Hide the ad container
 */
AdUi.prototype.hideAdContainer = function () {
  this.adContainerDiv.style.display = 'none';
};

/**
 * Handles clicks on the ad container
 */
AdUi.prototype.onAdContainerClick = function () {
  if (this.isAdNonlinear) {
    this.controller.togglePlayback();
  }
};

/**
 * Resets the state of the ad ui.
 */
AdUi.prototype.reset = function () {
  this.hideAdContainer();
};

/**
 * Handles ad errors.
 */
AdUi.prototype.onAdError = function () {
  this.hideAdContainer();
};

/**
 * Handles ad break starting.
 *
 * @param {Object} adEvent The event fired by the IMA SDK.
 */
AdUi.prototype.onAdBreakStart = function (adEvent) {
  this.showAdContainer();

  var contentType = adEvent.getAd().getContentType();
  if (contentType === 'application/javascript' && !this.controller.getSettings().showControlsForJSAds) {
    this.controlsDiv.style.display = 'none';
  } else {
    this.controlsDiv.style.display = 'block';
  }
  this.onAdsPlaying();
  // Start with the ad controls minimized.
  this.hideAdControls();
};

/**
 * Handles ad break ending.
 */
AdUi.prototype.onAdBreakEnd = function () {
  var currentAd = this.controller.getCurrentAd();
  if (currentAd == null || // hide for post-roll only playlist
  currentAd.isLinear()) {
    // don't hide for non-linear ads
    this.hideAdContainer();
  }
  this.controlsDiv.style.display = 'none';
  this.countdownDiv.innerHTML = '';
};

/**
 * Handles when all ads have finished playing.
 */
AdUi.prototype.onAllAdsCompleted = function () {
  this.hideAdContainer();
};

/**
 * Handles when a linear ad starts.
 */
AdUi.prototype.onLinearAdStart = function () {
  // Don't bump container when controls are shown
  this.removeClass(this.adContainerDiv, 'bumpable-ima-ad-container');
  this.isAdNonlinear = false;
};

/**
 * Handles when a non-linear ad starts.
 */
AdUi.prototype.onNonLinearAdLoad = function () {
  // For non-linear ads that show after a linear ad. For linear ads, we show the
  // ad container in onAdBreakStart to prevent blinking in pods.
  this.adContainerDiv.style.display = 'block';
  // Bump container when controls are shown
  this.addClass(this.adContainerDiv, 'bumpable-ima-ad-container');
  this.isAdNonlinear = true;
};

AdUi.prototype.onPlayerEnterFullscreen = function () {
  this.addClass(this.fullscreenDiv, 'ima-fullscreen');
  this.removeClass(this.fullscreenDiv, 'ima-non-fullscreen');
};

AdUi.prototype.onPlayerExitFullscreen = function () {
  this.addClass(this.fullscreenDiv, 'ima-non-fullscreen');
  this.removeClass(this.fullscreenDiv, 'ima-fullscreen');
};

/**
 * Called when the player volume changes.
 *
 * @param {number} volume The new player volume.
 */
AdUi.prototype.onPlayerVolumeChanged = function (volume) {
  if (volume == 0) {
    this.addClass(this.muteDiv, 'ima-muted');
    this.removeClass(this.muteDiv, 'ima-non-muted');
    this.sliderLevelDiv.style.width = '0%';
  } else {
    this.addClass(this.muteDiv, 'ima-non-muted');
    this.removeClass(this.muteDiv, 'ima-muted');
    this.sliderLevelDiv.style.width = volume * 100 + '%';
  }
};

/**
 * Shows ad controls on mouseover.
 */
AdUi.prototype.showAdControls = function () {
  var _controller$getSettin = this.controller.getSettings(),
      disableAdControls = _controller$getSettin.disableAdControls;

  if (!disableAdControls) {
    this.addClass(this.controlsDiv, 'ima-controls-div-showing');
  }
};

/**
 * Hide the ad controls.
 */
AdUi.prototype.hideAdControls = function () {
  this.removeClass(this.controlsDiv, 'ima-controls-div-showing');
};

/**
 * Assigns the unique id and class names to the given element as well as the
 * style class.
 * @param {HTMLElement} element Element that needs the controlName assigned.
 * @param {string} controlName Control name to assign.
 */
AdUi.prototype.assignControlAttributes = function (element, controlName) {
  element.id = this.controlPrefix + controlName;
  element.className = this.controlPrefix + controlName + ' ' + controlName;
};

/**
 * Returns a regular expression to test a string for the given className.
 *
 * @param {string} className The name of the class.
 * @return {RegExp} The regular expression used to test for that class.
 */
AdUi.prototype.getClassRegexp = function (className) {
  // Matches on
  // (beginning of string OR NOT word char)
  // classname
  // (negative lookahead word char OR end of string)
  return new RegExp('(^|[^A-Za-z-])' + className + '((?![A-Za-z-])|$)', 'gi');
};

/**
 * Returns whether or not the provided element has the provied class in its
 * className.
 * @param {HTMLElement} element Element to tes.t
 * @param {string} className Class to look for.
 * @return {boolean} True if element has className in class list. False
 *     otherwise.
 */
AdUi.prototype.elementHasClass = function (element, className) {
  var classRegexp = this.getClassRegexp(className);
  return classRegexp.test(element.className);
};

/**
 * Adds a class to the given element if it doesn't already have the class
 * @param {HTMLElement} element Element to which the class will be added.
 * @param {string} classToAdd Class to add.
 */
AdUi.prototype.addClass = function (element, classToAdd) {
  element.className = element.className.trim() + ' ' + classToAdd;
};

/**
 * Removes a class from the given element if it has the given class
 *
 * @param {HTMLElement} element Element from which the class will be removed.
 * @param {string} classToRemove Class to remove.
 */
AdUi.prototype.removeClass = function (element, classToRemove) {
  var classRegexp = this.getClassRegexp(classToRemove);
  element.className = element.className.trim().replace(classRegexp, '');
};

/**
 * @return {HTMLElement} The div for the ad container.
 */
AdUi.prototype.getAdContainerDiv = function () {
  return this.adContainerDiv;
};

/**
 * Changes the flag to show or hide the ad countdown timer.
 *
 * @param {boolean} showCountdownIn Show or hide the countdown timer.
 */
AdUi.prototype.setShowCountdown = function (showCountdownIn) {
  this.showCountdown = showCountdownIn;
  this.countdownDiv.style.display = this.showCountdown ? 'block' : 'none';
};

var name = "videojs-ima";
var version = "1.11.0";
var license = "Apache-2.0";
var main = "./dist/videojs.ima.js";
var module$1 = "./dist/videojs.ima.es.js";
var author = { "name": "Google Inc." };
var engines = { "node": ">=0.8.0" };
var scripts = { "contBuild": "watch 'npm run rollup:max' src", "predevServer": "echo \"Starting up server on localhost:8000.\"", "devServer": "npm-run-all -p testServer contBuild", "lint": "eslint \"src/*.js\"", "rollup": "npm-run-all rollup:*", "rollup:max": "rollup -c configs/rollup.config.js", "rollup:es": "rollup -c configs/rollup.config.es.js", "rollup:min": "rollup -c configs/rollup.config.min.js", "pretest": "npm run rollup", "start": "npm run devServer", "test": "npm-run-all test:*", "test:vjs5": "npm install video.js@5.19.2 --no-save && npm-run-all -p -r testServer webdriver", "test:vjs6": "npm install video.js@6 --no-save && npm-run-all -p -r testServer webdriver", "test:vjs7": "npm install video.js@7 --no-save && npm-run-all -p -r testServer webdriver", "testServer": "http-server --cors -p 8000 --silent", "preversion": "node scripts/preversion.js && npm run lint && npm test", "version": "node scripts/version.js", "postversion": "node scripts/postversion.js", "webdriver": "mocha test/webdriver/*.js --no-timeouts" };
var repository = { "type": "git", "url": "https://github.com/googleads/videojs-ima" };
var files = ["CHANGELOG.md", "LICENSE", "README.md", "dist/", "src/"];
var peerDependencies = { "video.js": "^5.19.2 || ^6 || ^7" };
var dependencies = { "can-autoplay": "^3.0.0", "@hapi/cryptiles": "^5.1.0", "extend": ">=3.0.2", "lodash": ">=4.17.19", "lodash.template": ">=4.5.0", "videojs-contrib-ads": "^6.6.5" };
var devDependencies = { "axios": ">=0.21.1", "babel-core": "^6.26.3", "babel-preset-env": "^1.7.0", "child_process": "^1.0.2", "chromedriver": "^89.0.0", "conventional-changelog-cli": "^2.0.31", "conventional-changelog-videojs": "^3.0.1", "ecstatic": ">=4.1.3", "eslint": "^4.19.1", "eslint-config-google": "^0.9.1", "eslint-plugin-jsdoc": "^3.15.1", "geckodriver": "^1.19.1", "http-server": "^0.12.3", "ini": ">=1.3.7", "mocha": "^7.1.2", "npm-run-all": "^4.1.5", "path": "^0.12.7", "protractor": "^7.0.0", "rimraf": "^2.7.1", "rollup": "^0.51.8", "rollup-plugin-babel": "^3.0.7", "rollup-plugin-copy": "^0.2.3", "rollup-plugin-json": "^2.3.1", "rollup-plugin-uglify": "^2.0.1", "selenium-webdriver": "^3.6.0", "uglify-es": "^3.3.9", "video.js": "^5.19.2 || ^6 || ^7", "watch": "^1.0.2", "webdriver-manager": "^12.1.7", "xmldom": ">=0.5.0" };
var keywords = ["videojs", "videojs-plugin"];
var pkg = {
	name: name,
	version: version,
	license: license,
	main: main,
	module: module$1,
	author: author,
	engines: engines,
	scripts: scripts,
	repository: repository,
	files: files,
	peerDependencies: peerDependencies,
	dependencies: dependencies,
	devDependencies: devDependencies,
	keywords: keywords
};

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

/**
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * IMA SDK integration plugin for Video.js. For more information see
 * https://www.github.com/googleads/videojs-ima
 */

/**
 * Implementation of the IMA SDK for the plugin.
 *
 * @param {Object} controller Reference to the parent controller.
 *
 * @constructor
 * @struct
 * @final
 */
var SdkImpl = function SdkImpl(controller) {
  /**
   * Plugin controller.
   */
  this.controller = controller;

  /**
   * IMA SDK AdDisplayContainer.
   */
  this.adDisplayContainer = null;

  /**
   * True if the AdDisplayContainer has been initialized. False otherwise.
   */
  this.adDisplayContainerInitialized = false;

  /**
   * IMA SDK AdsLoader
   */
  this.adsLoader = null;

  /**
   * IMA SDK AdsManager
   */
  this.adsManager = null;

  /**
   * IMA SDK AdsRenderingSettings.
   */
  this.adsRenderingSettings = null;

  /**
   * VAST, VMAP, or ad rules response. Used in lieu of fetching a response
   * from an ad tag URL.
   */
  this.adsResponse = null;

  /**
   * Current IMA SDK Ad.
   */
  this.currentAd = null;

  /**
   * Timer used to track ad progress.
   */
  this.adTrackingTimer = null;

  /**
   * True if ALL_ADS_COMPLETED has fired, false until then.
   */
  this.allAdsCompleted = false;

  /**
   * True if ads are currently displayed, false otherwise.
   * True regardless of ad pause state if an ad is currently being displayed.
   */
  this.adsActive = false;

  /**
   * True if ad is currently playing, false if ad is paused or ads are not
   * currently displayed.
   */
  this.adPlaying = false;

  /**
   * True if the ad is muted, false otherwise.
   */
  this.adMuted = false;

  /**
   * Listener to be called to trigger manual ad break playback.
   */
  this.adBreakReadyListener = undefined;

  /**
   * Tracks whether or not we have already called adsLoader.contentComplete().
   */
  this.contentCompleteCalled = false;

  /**
   * True if the ad has timed out.
   */
  this.isAdTimedOut = false;

  /**
   * Stores the dimensions for the ads manager.
   */
  this.adsManagerDimensions = {
    width: 0,
    height: 0
  };

  /**
   * Boolean flag to enable manual ad break playback.
   */
  this.autoPlayAdBreaks = true;
  if (this.controller.getSettings().autoPlayAdBreaks === false) {
    this.autoPlayAdBreaks = false;
  }

  // Set SDK settings from plugin settings.
  if (this.controller.getSettings().locale) {
    /* eslint no-undef: 'error' */
    /* global google */
    google.ima.settings.setLocale(this.controller.getSettings().locale);
  }
  if (this.controller.getSettings().disableFlashAds) {
    google.ima.settings.setDisableFlashAds(this.controller.getSettings().disableFlashAds);
  }
  if (this.controller.getSettings().disableCustomPlaybackForIOS10Plus) {
    google.ima.settings.setDisableCustomPlaybackForIOS10Plus(this.controller.getSettings().disableCustomPlaybackForIOS10Plus);
  }

  if (this.controller.getSettings().ppid) {
    google.ima.settings.setPpid(this.controller.getSettings().ppid);
  }

  if (this.controller.getSettings().featureFlags) {
    google.ima.settings.setFeatureFlags(this.controller.getSettings().featureFlags);
  }
};

/**
 * Creates and initializes the IMA SDK objects.
 */
SdkImpl.prototype.initAdObjects = function () {
  this.adDisplayContainer = new google.ima.AdDisplayContainer(this.controller.getAdContainerDiv(), this.controller.getContentPlayer());

  this.adsLoader = new google.ima.AdsLoader(this.adDisplayContainer);

  this.adsLoader.getSettings().setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);
  if (this.controller.getSettings().vpaidAllowed == false) {
    this.adsLoader.getSettings().setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.DISABLED);
  }
  if (this.controller.getSettings().vpaidMode !== undefined) {
    this.adsLoader.getSettings().setVpaidMode(this.controller.getSettings().vpaidMode);
  }

  if (this.controller.getSettings().locale) {
    this.adsLoader.getSettings().setLocale(this.controller.getSettings().locale);
  }

  if (this.controller.getSettings().numRedirects) {
    this.adsLoader.getSettings().setNumRedirects(this.controller.getSettings().numRedirects);
  }

  if (this.controller.getSettings().sessionId) {
    this.adsLoader.getSettings().setSessionId(this.controller.getSettings().sessionId);
  }

  this.adsLoader.getSettings().setPlayerType('videojs-ima');
  this.adsLoader.getSettings().setPlayerVersion(pkg.version);
  this.adsLoader.getSettings().setAutoPlayAdBreaks(this.autoPlayAdBreaks);

  this.adsLoader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, this.onAdsManagerLoaded.bind(this), false);
  this.adsLoader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, this.onAdsLoaderError.bind(this), false);

  this.controller.playerWrapper.vjsPlayer.trigger({
    type: 'ads-loader',
    adsLoader: this.adsLoader
  });
};

/**
 * Creates the AdsRequest and request ads through the AdsLoader.
 */
SdkImpl.prototype.requestAds = function () {
  var adsRequest = new google.ima.AdsRequest();
  if (this.controller.getSettings().adTagUrl) {
    adsRequest.adTagUrl = this.controller.getSettings().adTagUrl;
  } else {
    adsRequest.adsResponse = this.controller.getSettings().adsResponse;
  }
  if (this.controller.getSettings().forceNonLinearFullSlot) {
    adsRequest.forceNonLinearFullSlot = true;
  }

  if (this.controller.getSettings().vastLoadTimeout) {
    adsRequest.vastLoadTimeout = this.controller.getSettings().vastLoadTimeout;
  }

  if (this.controller.getSettings().omidMode) {
    adsRequest.omidAccessModeRules = {};
    var omidValues = this.controller.getSettings().omidMode;

    if (omidValues.FULL) {
      adsRequest.omidAccessModeRules[google.ima.OmidAccessMode.FULL] = omidValues.FULL;
    }
    if (omidValues.DOMAIN) {
      adsRequest.omidAccessModeRules[google.ima.OmidAccessMode.DOMAIN] = omidValues.DOMAIN;
    }
    if (omidValues.LIMITED) {
      adsRequest.omidAccessModeRules[google.ima.OmidAccessMode.LIMITED] = omidValues.LIMITED;
    }
  }

  adsRequest.linearAdSlotWidth = this.controller.getPlayerWidth();
  adsRequest.linearAdSlotHeight = this.controller.getPlayerHeight();
  adsRequest.nonLinearAdSlotWidth = this.controller.getSettings().nonLinearWidth || this.controller.getPlayerWidth();
  adsRequest.nonLinearAdSlotHeight = this.controller.getSettings().nonLinearHeight || this.controller.getPlayerHeight();
  adsRequest.setAdWillAutoPlay(this.controller.adsWillAutoplay());
  adsRequest.setAdWillPlayMuted(this.controller.adsWillPlayMuted());

  // Populate the adsRequestproperties with those provided in the AdsRequest
  // object in the settings.
  var providedAdsRequest = this.controller.getSettings().adsRequest;
  if (providedAdsRequest && (typeof providedAdsRequest === 'undefined' ? 'undefined' : _typeof(providedAdsRequest)) === 'object') {
    Object.keys(providedAdsRequest).forEach(function (key) {
      adsRequest[key] = providedAdsRequest[key];
    });
  }

  this.adsLoader.requestAds(adsRequest);
  this.controller.playerWrapper.vjsPlayer.trigger({
    type: 'ads-request',
    AdsRequest: adsRequest
  });
};

/**
 * Listener for the ADS_MANAGER_LOADED event. Creates the AdsManager,
 * sets up event listeners, and triggers the 'adsready' event for
 * videojs-ads-contrib.
 *
 * @param {google.ima.AdsManagerLoadedEvent} adsManagerLoadedEvent Fired when
 *     the AdsManager loads.
 */
SdkImpl.prototype.onAdsManagerLoaded = function (adsManagerLoadedEvent) {
  this.createAdsRenderingSettings();

  this.adsManager = adsManagerLoadedEvent.getAdsManager(this.controller.getContentPlayheadTracker(), this.adsRenderingSettings);

  this.adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, this.onAdError.bind(this));
  this.adsManager.addEventListener(google.ima.AdEvent.Type.AD_BREAK_READY, this.onAdBreakReady.bind(this));
  this.adsManager.addEventListener(google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, this.onContentPauseRequested.bind(this));
  this.adsManager.addEventListener(google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, this.onContentResumeRequested.bind(this));
  this.adsManager.addEventListener(google.ima.AdEvent.Type.ALL_ADS_COMPLETED, this.onAllAdsCompleted.bind(this));

  this.adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, this.onAdLoaded.bind(this));
  this.adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, this.onAdStarted.bind(this));
  this.adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, this.onAdComplete.bind(this));
  this.adsManager.addEventListener(google.ima.AdEvent.Type.SKIPPED, this.onAdComplete.bind(this));
  this.adsManager.addEventListener(google.ima.AdEvent.Type.LOG, this.onAdLog.bind(this));
  this.adsManager.addEventListener(google.ima.AdEvent.Type.PAUSED, this.onAdPaused.bind(this));
  this.adsManager.addEventListener(google.ima.AdEvent.Type.RESUMED, this.onAdResumed.bind(this));

  this.controller.playerWrapper.vjsPlayer.trigger({
    type: 'ads-manager',
    adsManager: this.adsManager
  });

  if (!this.autoPlayAdBreaks) {
    this.initAdsManager();
  }

  var _controller$getSettin = this.controller.getSettings(),
      preventLateAdStart = _controller$getSettin.preventLateAdStart;

  if (!preventLateAdStart) {
    this.controller.onAdsReady();
  } else if (preventLateAdStart && !this.isAdTimedOut) {
    this.controller.onAdsReady();
  }

  if (this.controller.getSettings().adsManagerLoadedCallback) {
    this.controller.getSettings().adsManagerLoadedCallback();
  }
};

/**
 * Listener for errors fired by the AdsLoader.
 * @param {google.ima.AdErrorEvent} event The error event thrown by the
 *     AdsLoader. See
 *     https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/js/google.ima.AdError#.Type
 */
SdkImpl.prototype.onAdsLoaderError = function (event) {
  window.console.warn('AdsLoader error: ' + event.getError());
  this.controller.onErrorLoadingAds(event);
  if (this.adsManager) {
    this.adsManager.destroy();
  }
};

/**
 * Initialize the ads manager.
 */
SdkImpl.prototype.initAdsManager = function () {
  try {
    var initWidth = this.controller.getPlayerWidth();
    var initHeight = this.controller.getPlayerHeight();
    this.adsManagerDimensions.width = initWidth;
    this.adsManagerDimensions.height = initHeight;
    this.adsManager.init(initWidth, initHeight, google.ima.ViewMode.NORMAL);
    this.adsManager.setVolume(this.controller.getPlayerVolume());
    this.initializeAdDisplayContainer();
  } catch (adError) {
    this.onAdError(adError);
  }
};

/**
 * Create AdsRenderingSettings for the IMA SDK.
 */
SdkImpl.prototype.createAdsRenderingSettings = function () {
  this.adsRenderingSettings = new google.ima.AdsRenderingSettings();
  this.adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true;
  if (this.controller.getSettings().adsRenderingSettings) {
    for (var setting in this.controller.getSettings().adsRenderingSettings) {
      if (setting !== '') {
        this.adsRenderingSettings[setting] = this.controller.getSettings().adsRenderingSettings[setting];
      }
    }
  }
};

/**
 * Listener for errors thrown by the AdsManager.
 * @param {google.ima.AdErrorEvent} adErrorEvent The error event thrown by
 *     the AdsManager.
 */
SdkImpl.prototype.onAdError = function (adErrorEvent) {
  var errorMessage = adErrorEvent.getError !== undefined ? adErrorEvent.getError() : adErrorEvent.stack;
  window.console.warn('Ad error: ' + errorMessage);

  this.adsManager.destroy();
  this.controller.onAdError(adErrorEvent);

  // reset these so consumers don't think we are still in an ad break,
  // but reset them after any prior cleanup happens
  this.adsActive = false;
  this.adPlaying = false;
};

/**
 * Listener for AD_BREAK_READY. Passes event on to publisher's listener.
 * @param {google.ima.AdEvent} adEvent AdEvent thrown by the AdsManager.
 */
SdkImpl.prototype.onAdBreakReady = function (adEvent) {
  this.adBreakReadyListener(adEvent);
};

/**
 * Pauses the content video and displays the ad container so ads can play.
 * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.
 */
SdkImpl.prototype.onContentPauseRequested = function (adEvent) {
  this.adsActive = true;
  this.adPlaying = true;
  this.controller.onAdBreakStart(adEvent);
};

/**
 * Resumes content video and hides the ad container.
 * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.
 */
SdkImpl.prototype.onContentResumeRequested = function (adEvent) {
  this.adsActive = false;
  this.adPlaying = false;
  this.controller.onAdBreakEnd();
  // Hide controls in case of future non-linear ads. They'll be unhidden in
  // content_pause_requested.
};

/**
 * Records that ads have completed and calls contentAndAdsEndedListeners
 * if content is also complete.
 * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.
 */
SdkImpl.prototype.onAllAdsCompleted = function (adEvent) {
  this.allAdsCompleted = true;
  this.controller.onAllAdsCompleted();
};

/**
 * Starts the content video when a non-linear ad is loaded.
 * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.
 */
SdkImpl.prototype.onAdLoaded = function (adEvent) {
  if (!adEvent.getAd().isLinear()) {
    this.controller.onNonLinearAdLoad();
    this.controller.playContent();
  }
};

/**
 * Starts the interval timer to check the current ad time when an ad starts
 * playing.
 * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.
 */
SdkImpl.prototype.onAdStarted = function (adEvent) {
  this.currentAd = adEvent.getAd();
  if (this.currentAd.isLinear()) {
    this.adTrackingTimer = setInterval(this.onAdPlayheadTrackerInterval.bind(this), 250);
    this.controller.onLinearAdStart();
  } else {
    this.controller.onNonLinearAdStart();
  }
};

/**
 * Handles an ad click. Puts the player UI in a paused state.
 */
SdkImpl.prototype.onAdPaused = function () {
  this.controller.onAdsPaused();
};

/**
 * Syncs controls when an ad resumes.
 * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.
 */
SdkImpl.prototype.onAdResumed = function (adEvent) {
  this.controller.onAdsResumed();
};

/**
 * Clears the interval timer for current ad time when an ad completes.
 */
SdkImpl.prototype.onAdComplete = function () {
  if (this.currentAd.isLinear()) {
    clearInterval(this.adTrackingTimer);
  }
};

/**
 * Handles ad log messages.
 * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the AdsManager.
 */
SdkImpl.prototype.onAdLog = function (adEvent) {
  this.controller.onAdLog(adEvent);
};

/**
 * Gets the current time and duration of the ad and calls the method to
 * update the ad UI.
 */
SdkImpl.prototype.onAdPlayheadTrackerInterval = function () {
  if (this.adsManager === null) return;
  var remainingTime = this.adsManager.getRemainingTime();
  var duration = this.currentAd.getDuration();
  var currentTime = duration - remainingTime;
  currentTime = currentTime > 0 ? currentTime : 0;
  var totalAds = 0;
  var adPosition = void 0;
  if (this.currentAd.getAdPodInfo()) {
    adPosition = this.currentAd.getAdPodInfo().getAdPosition();
    totalAds = this.currentAd.getAdPodInfo().getTotalAds();
  }

  this.controller.onAdPlayheadUpdated(currentTime, remainingTime, duration, adPosition, totalAds);
};

/**
 * Called by the player wrapper when content completes.
 */
SdkImpl.prototype.onContentComplete = function () {
  if (this.adsLoader) {
    this.adsLoader.contentComplete();
    this.contentCompleteCalled = true;
  }

  if (this.adsManager && this.adsManager.getCuePoints() && !this.adsManager.getCuePoints().includes(-1) || !this.adsManager) {
    this.controller.onNoPostroll();
  }

  if (this.allAdsCompleted) {
    this.controller.onContentAndAdsCompleted();
  }
};

/**
 * Called when the player is disposed.
 */
SdkImpl.prototype.onPlayerDisposed = function () {
  if (this.adTrackingTimer) {
    clearInterval(this.adTrackingTimer);
  }
  if (this.adsManager) {
    this.adsManager.destroy();
    this.adsManager = null;
  }
};

SdkImpl.prototype.onPlayerReadyForPreroll = function () {
  if (this.autoPlayAdBreaks) {
    this.initAdsManager();
    try {
      this.controller.showAdContainer();
      // Sync ad volume with content volume.
      this.adsManager.setVolume(this.controller.getPlayerVolume());
      this.adsManager.start();
    } catch (adError) {
      this.onAdError(adError);
    }
  }
};

SdkImpl.prototype.onAdTimeout = function () {
  this.isAdTimedOut = true;
};

SdkImpl.prototype.onPlayerReady = function () {
  this.initAdObjects();

  if ((this.controller.getSettings().adTagUrl || this.controller.getSettings().adsResponse) && this.controller.getSettings().requestMode === 'onLoad') {
    this.requestAds();
  }
};

SdkImpl.prototype.onPlayerEnterFullscreen = function () {
  if (this.adsManager) {
    this.adsManager.resize(window.screen.width, window.screen.height, google.ima.ViewMode.FULLSCREEN);
  }
};

SdkImpl.prototype.onPlayerExitFullscreen = function () {
  if (this.adsManager) {
    this.adsManager.resize(this.controller.getPlayerWidth(), this.controller.getPlayerHeight(), google.ima.ViewMode.NORMAL);
  }
};

/**
 * Called when the player volume changes.
 *
 * @param {number} volume The new player volume.
 */
SdkImpl.prototype.onPlayerVolumeChanged = function (volume) {
  if (this.adsManager) {
    this.adsManager.setVolume(volume);
  }

  if (volume == 0) {
    this.adMuted = true;
  } else {
    this.adMuted = false;
  }
};

/**
 * Called when the player wrapper detects that the player has been resized.
 *
 * @param {number} width The post-resize width of the player.
 * @param {number} height The post-resize height of the player.
 */
SdkImpl.prototype.onPlayerResize = function (width, height) {
  if (this.adsManager) {
    this.adsManagerDimensions.width = width;
    this.adsManagerDimensions.height = height;
    /* global google */
    /* eslint no-undef: 'error' */
    this.adsManager.resize(width, height, google.ima.ViewMode.NORMAL);
  }
};

/**
 * @return {Object} The current ad.
 */
SdkImpl.prototype.getCurrentAd = function () {
  return this.currentAd;
};

/**
 * Listener JSDoc for ESLint. This listener can be passed to
 * setAdBreakReadyListener.
 * @callback listener
 */

/**
 * Sets the listener to be called to trigger manual ad break playback.
 * @param {listener} listener The listener to be called to trigger manual ad
 *     break playback.
 */
SdkImpl.prototype.setAdBreakReadyListener = function (listener) {
  this.adBreakReadyListener = listener;
};

/**
 * @return {boolean} True if an ad is currently playing. False otherwise.
 */
SdkImpl.prototype.isAdPlaying = function () {
  return this.adPlaying;
};

/**
 * @return {boolean} True if an ad is currently playing. False otherwise.
 */
SdkImpl.prototype.isAdMuted = function () {
  return this.adMuted;
};

/**
 * Pause ads.
 */
SdkImpl.prototype.pauseAds = function () {
  this.adsManager.pause();
  this.adPlaying = false;
};

/**
 * Resume ads.
 */
SdkImpl.prototype.resumeAds = function () {
  this.adsManager.resume();
  this.adPlaying = true;
};

/**
 * Unmute ads.
 */
SdkImpl.prototype.unmute = function () {
  this.adsManager.setVolume(1);
  this.adMuted = false;
};

/**
 * Mute ads.
 */
SdkImpl.prototype.mute = function () {
  this.adsManager.setVolume(0);
  this.adMuted = true;
};

/**
 * Set the volume of the ads. 0-1.
 *
 * @param {number} volume The new volume.
 */
SdkImpl.prototype.setVolume = function (volume) {
  this.adsManager.setVolume(volume);
  if (volume == 0) {
    this.adMuted = true;
  } else {
    this.adMuted = false;
  }
};

/**
 * Initializes the AdDisplayContainer. On mobile, this must be done as a
 * result of user action.
 */
SdkImpl.prototype.initializeAdDisplayContainer = function () {
  if (this.adDisplayContainer) {
    if (!this.adDisplayContainerInitialized) {
      this.adDisplayContainer.initialize();
      this.adDisplayContainerInitialized = true;
    }
  }
};

/**
 * Called by publishers in manual ad break playback mode to start an ad
 * break.
 */
SdkImpl.prototype.playAdBreak = function () {
  if (!this.autoPlayAdBreaks) {
    this.controller.showAdContainer();
    // Sync ad volume with content volume.
    this.adsManager.setVolume(this.controller.getPlayerVolume());
    this.adsManager.start();
  }
};

/**
 * Callback JSDoc for ESLint. This callback can be passed to addEventListener.
 * @callback callback
 */

/**
 * Ads an EventListener to the AdsManager. For a list of available events,
 * see
 * https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/js/google.ima.AdEvent#.Type
 * @param {google.ima.AdEvent.Type} event The AdEvent.Type for which to
 *     listen.
 * @param {callback} callback The method to call when the event is fired.
 */
SdkImpl.prototype.addEventListener = function (event, callback) {
  if (this.adsManager) {
    this.adsManager.addEventListener(event, callback);
  }
};

/**
 * Returns the instance of the AdsManager.
 * @return {google.ima.AdsManager} The AdsManager being used by the plugin.
 */
SdkImpl.prototype.getAdsManager = function () {
  return this.adsManager;
};

/**
 * Reset the SDK implementation.
 */
SdkImpl.prototype.reset = function () {
  this.adsActive = false;
  this.adPlaying = false;
  if (this.adTrackingTimer) {
    // If this is called while an ad is playing, stop trying to get that
    // ad's current time.
    clearInterval(this.adTrackingTimer);
  }
  if (this.adsManager) {
    this.adsManager.destroy();
    this.adsManager = null;
  }
  if (this.adsLoader && !this.contentCompleteCalled) {
    this.adsLoader.contentComplete();
  }
  this.contentCompleteCalled = false;
  this.allAdsCompleted = false;
};

/**
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * IMA SDK integration plugin for Video.js. For more information see
 * https://www.github.com/googleads/videojs-ima
 */
/**
 * The grand coordinator of the plugin. Facilitates communication between all
 * other plugin classes.
 *
 * @param {Object} player Instance of the video.js player.
 * @param {Object} options Options provided by the implementation.
 * @constructor
 * @struct
 * @final
 */
var Controller = function Controller(player, options) {
  /**
   * Stores user-provided settings.
   * @type {Object}
   */
  this.settings = {};

  /**
   * Content and ads ended listeners passed by the publisher to the plugin.
   * These will be called when the plugin detects that content *and all
   * ads* have completed. This differs from the contentEndedListeners in that
   * contentEndedListeners will fire between content ending and a post-roll
   * playing, whereas the contentAndAdsEndedListeners will fire after the
   * post-roll completes.
   */
  this.contentAndAdsEndedListeners = [];

  /**
   * Whether or not we are running on a mobile platform.
   */
  this.isMobile = navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i) || navigator.userAgent.match(/Android/i);

  /**
   * Whether or not we are running on an iOS platform.
   */
  this.isIos = navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i);

  this.initWithSettings(options);

  /**
   * Stores contrib-ads default settings.
   */
  var contribAdsDefaults = {
    debug: this.settings.debug,
    timeout: this.settings.timeout,
    prerollTimeout: this.settings.prerollTimeout
  };
  var adsPluginSettings = this.extend({}, contribAdsDefaults, options.contribAdsSettings || {});

  this.playerWrapper = new PlayerWrapper(player, adsPluginSettings, this);
  this.adUi = new AdUi(this);
  this.sdkImpl = new SdkImpl(this);
};

Controller.IMA_DEFAULTS = {
  adLabel: 'Advertisement',
  adLabelNofN: 'of',
  debug: false,
  disableAdControls: false,
  prerollTimeout: 1000,
  preventLateAdStart: false,
  requestMode: 'onLoad',
  showControlsForJSAds: true,
  timeout: 5000
};

/**
 * Extends the settings to include user-provided settings.
 *
 * @param {Object} options Options to be used in initialization.
 */
Controller.prototype.initWithSettings = function (options) {
  this.settings = this.extend({}, Controller.IMA_DEFAULTS, options || {});

  this.warnAboutDeprecatedSettings();

  // Default showing countdown timer to true.
  this.showCountdown = true;
  if (this.settings.showCountdown === false) {
    this.showCountdown = false;
  }
};

/**
 * Logs console warnings when deprecated settings are used.
 */
Controller.prototype.warnAboutDeprecatedSettings = function () {
  var _this = this;

  var deprecatedSettings = ['adWillAutoplay', 'adsWillAutoplay', 'adWillPlayMuted', 'adsWillPlayMuted'];
  deprecatedSettings.forEach(function (setting) {
    if (_this.settings[setting] !== undefined) {
      console.warn('WARNING: videojs.ima setting ' + setting + ' is deprecated');
    }
  });
};

/**
 * Return the settings object.
 *
 * @return {Object} The settings object.
 */
Controller.prototype.getSettings = function () {
  return this.settings;
};

/**
 * Return whether or not we're in a mobile environment.
 *
 * @return {boolean} True if running on mobile, false otherwise.
 */
Controller.prototype.getIsMobile = function () {
  return this.isMobile;
};

/**
 * Return whether or not we're in an iOS environment.
 *
 * @return {boolean} True if running on iOS, false otherwise.
 */
Controller.prototype.getIsIos = function () {
  return this.isIos;
};

/**
 * Inject the ad container div into the DOM.
 *
 * @param{HTMLElement} adContainerDiv The ad container div.
 */
Controller.prototype.injectAdContainerDiv = function (adContainerDiv) {
  this.playerWrapper.injectAdContainerDiv(adContainerDiv);
};

/**
 * @return {HTMLElement} The div for the ad container.
 */
Controller.prototype.getAdContainerDiv = function () {
  return this.adUi.getAdContainerDiv();
};

/**
 * @return {Object} The content player.
 */
Controller.prototype.getContentPlayer = function () {
  return this.playerWrapper.getContentPlayer();
};

/**
 * Returns the content playhead tracker.
 *
 * @return {Object} The content playhead tracker.
 */
Controller.prototype.getContentPlayheadTracker = function () {
  return this.playerWrapper.getContentPlayheadTracker();
};

/**
 * Requests ads.
 */
Controller.prototype.requestAds = function () {
  this.sdkImpl.requestAds();
};

/**
 * Add or modify a setting.
 *
 * @param {string} key Key to modify
 * @param {Object} value Value to set at key.
 */
Controller.prototype.setSetting = function (key, value) {
  this.settings[key] = value;
};

/**
 * Called when there is an error loading ads.
 *
 * @param {Object} adErrorEvent The ad error event thrown by the IMA SDK.
 */
Controller.prototype.onErrorLoadingAds = function (adErrorEvent) {
  this.adUi.onAdError();
  this.playerWrapper.onAdError(adErrorEvent);
};

/**
 * Called by the ad UI when the play/pause button is clicked.
 */
Controller.prototype.onAdPlayPauseClick = function () {
  if (this.sdkImpl.isAdPlaying()) {
    this.adUi.onAdsPaused();
    this.sdkImpl.pauseAds();
  } else {
    this.adUi.onAdsPlaying();
    this.sdkImpl.resumeAds();
  }
};

/**
 * Called by the ad UI when the mute button is clicked.
 *
 */
Controller.prototype.onAdMuteClick = function () {
  if (this.sdkImpl.isAdMuted()) {
    this.playerWrapper.unmute();
    this.adUi.unmute();
    this.sdkImpl.unmute();
  } else {
    this.playerWrapper.mute();
    this.adUi.mute();
    this.sdkImpl.mute();
  }
};

/**
 * Set the volume of the player and ads. 0-1.
 *
 * @param {number} volume The new volume.
 */
Controller.prototype.setVolume = function (volume) {
  this.playerWrapper.setVolume(volume);
  this.sdkImpl.setVolume(volume);
};

/**
 * @return {number} The volume of the content player.
 */
Controller.prototype.getPlayerVolume = function () {
  return this.playerWrapper.getVolume();
};

/**
 * Toggle fullscreen state.
 */
Controller.prototype.toggleFullscreen = function () {
  this.playerWrapper.toggleFullscreen();
};

/**
 * Relays ad errors to the player wrapper.
 *
 * @param {Object} adErrorEvent The ad error event thrown by the IMA SDK.
 */
Controller.prototype.onAdError = function (adErrorEvent) {
  this.adUi.onAdError();
  this.playerWrapper.onAdError(adErrorEvent);
};

/**
 * Handles ad break starting.
 *
 * @param {Object} adEvent The event fired by the IMA SDK.
 */
Controller.prototype.onAdBreakStart = function (adEvent) {
  this.playerWrapper.onAdBreakStart();
  this.adUi.onAdBreakStart(adEvent);
};

/**
 * Show the ad container.
 */
Controller.prototype.showAdContainer = function () {
  this.adUi.showAdContainer();
};

/**
 * Handles ad break ending.
 */
Controller.prototype.onAdBreakEnd = function () {
  this.playerWrapper.onAdBreakEnd();
  this.adUi.onAdBreakEnd();
};

/**
 * Handles when all ads have finished playing.
 */
Controller.prototype.onAllAdsCompleted = function () {
  this.adUi.onAllAdsCompleted();
  this.playerWrapper.onAllAdsCompleted();
};

/**
 * Handles the SDK firing an ad paused event.
 */
Controller.prototype.onAdsPaused = function () {
  this.adUi.onAdsPaused();
};

/**
 * Handles the SDK firing an ad resumed event.
 */
Controller.prototype.onAdsResumed = function () {
  this.adUi.onAdsResumed();
};

/**
 * Takes data from the sdk impl and passes it to the ad UI to update the UI.
 *
 * @param {number} currentTime Current time of the ad.
 * @param {number} remainingTime Remaining time of the ad.
 * @param {number} duration Duration of the ad.
 * @param {number} adPosition Index of the ad in the pod.
 * @param {number} totalAds Total number of ads in the pod.
 */
Controller.prototype.onAdPlayheadUpdated = function (currentTime, remainingTime, duration, adPosition, totalAds) {
  this.adUi.updateAdUi(currentTime, remainingTime, duration, adPosition, totalAds);
};

/**
 * Handles ad log messages.
 * @param {google.ima.AdEvent} adEvent The AdEvent thrown by the IMA SDK.
 */
Controller.prototype.onAdLog = function (adEvent) {
  this.playerWrapper.onAdLog(adEvent);
};

/**
 * @return {Object} The current ad.
 */
Controller.prototype.getCurrentAd = function () {
  return this.sdkImpl.getCurrentAd();
};

/**
 * Play content.
 */
Controller.prototype.playContent = function () {
  this.playerWrapper.play();
};

/**
 * Handles when a linear ad starts.
 */
Controller.prototype.onLinearAdStart = function () {
  this.adUi.onLinearAdStart();
  this.playerWrapper.onAdStart();
};

/**
 * Handles when a non-linear ad loads.
 */
Controller.prototype.onNonLinearAdLoad = function () {
  this.adUi.onNonLinearAdLoad();
};

/**
 * Handles when a non-linear ad starts.
 */
Controller.prototype.onNonLinearAdStart = function () {
  this.adUi.onNonLinearAdLoad();
  this.playerWrapper.onAdStart();
};

/**
 * Get the player width.
 *
 * @return {number} The width of the player.
 */
Controller.prototype.getPlayerWidth = function () {
  return this.playerWrapper.getPlayerWidth();
};

/**
 * Get the player height.
 *
 * @return {number} The height of the player.
 */
Controller.prototype.getPlayerHeight = function () {
  return this.playerWrapper.getPlayerHeight();
};

/**
 * Tells the player wrapper that ads are ready.
 */
Controller.prototype.onAdsReady = function () {
  this.playerWrapper.onAdsReady();
};

/**
 * Called when the player wrapper detects that the player has been resized.
 *
 * @param {number} width The post-resize width of the player.
 * @param {number} height The post-resize height of the player.
 */
Controller.prototype.onPlayerResize = function (width, height) {
  this.sdkImpl.onPlayerResize(width, height);
};

/**
 * Called by the player wrapper when content completes.
 */
Controller.prototype.onContentComplete = function () {
  this.sdkImpl.onContentComplete();
};

/**
 * Called by the player wrapper when it's time to play a post-roll but we don't
 * have one to play.
 */
Controller.prototype.onNoPostroll = function () {
  this.playerWrapper.onNoPostroll();
};

/**
 * Called when content and all ads have completed.
 */
Controller.prototype.onContentAndAdsCompleted = function () {
  for (var index in this.contentAndAdsEndedListeners) {
    if (typeof this.contentAndAdsEndedListeners[index] === 'function') {
      this.contentAndAdsEndedListeners[index]();
    }
  }
};

/**
 * Called when the player is disposed.
 */
Controller.prototype.onPlayerDisposed = function () {
  this.contentAndAdsEndedListeners = [];
  this.sdkImpl.onPlayerDisposed();
};

/**
 * Called when the player is ready to play a pre-roll.
 */
Controller.prototype.onPlayerReadyForPreroll = function () {
  this.sdkImpl.onPlayerReadyForPreroll();
};

/**
 * Called if the ad times out.
 */
Controller.prototype.onAdTimeout = function () {
  this.sdkImpl.onAdTimeout();
};

/**
 * Called when the player is ready.
 */
Controller.prototype.onPlayerReady = function () {
  this.sdkImpl.onPlayerReady();
};

/**
 * Called when the player enters fullscreen.
 */
Controller.prototype.onPlayerEnterFullscreen = function () {
  this.adUi.onPlayerEnterFullscreen();
  this.sdkImpl.onPlayerEnterFullscreen();
};

/**
 * Called when the player exits fullscreen.
 */
Controller.prototype.onPlayerExitFullscreen = function () {
  this.adUi.onPlayerExitFullscreen();
  this.sdkImpl.onPlayerExitFullscreen();
};

/**
 * Called when the player volume changes.
 *
 * @param {number} volume The new player volume.
 */
Controller.prototype.onPlayerVolumeChanged = function (volume) {
  this.adUi.onPlayerVolumeChanged(volume);
  this.sdkImpl.onPlayerVolumeChanged(volume);
};

/**
 * Sets the content of the video player. You should use this method instead
 * of setting the content src directly to ensure the proper ad tag is
 * requested when the video content is loaded.
 * @param {?string} contentSrc The URI for the content to be played. Leave
 *     blank to use the existing content.
 * @param {?string} adTag The ad tag to be requested when the content loads.
 *     Leave blank to use the existing ad tag.
 */
Controller.prototype.setContentWithAdTag = function (contentSrc, adTag) {
  this.reset();
  this.settings.adTagUrl = adTag ? adTag : this.settings.adTagUrl;
  this.playerWrapper.changeSource(contentSrc);
};

/**
 * Sets the content of the video player. You should use this method instead
 * of setting the content src directly to ensure the proper ads response is
 * used when the video content is loaded.
 * @param {?string} contentSrc The URI for the content to be played. Leave
 *     blank to use the existing content.
 * @param {?string} adsResponse The ads response to be requested when the
 *     content loads. Leave blank to use the existing ads response.
 */
Controller.prototype.setContentWithAdsResponse = function (contentSrc, adsResponse) {
  this.reset();
  this.settings.adsResponse = adsResponse ? adsResponse : this.settings.adsResponse;
  this.playerWrapper.changeSource(contentSrc);
};

/**
 * Sets the content of the video player. You should use this method instead
 * of setting the content src directly to ensure the proper ads request is
 * used when the video content is loaded.
 * @param {?string} contentSrc The URI for the content to be played. Leave
 *     blank to use the existing content.
 * @param {?Object} adsRequest The ads request to be requested when the
 *     content loads. Leave blank to use the existing ads request.
 */
Controller.prototype.setContentWithAdsRequest = function (contentSrc, adsRequest) {
  this.reset();
  this.settings.adsRequest = adsRequest ? adsRequest : this.settings.adsRequest;
  this.playerWrapper.changeSource(contentSrc);
};

/**
 * Resets the state of the plugin.
 */
Controller.prototype.reset = function () {
  this.sdkImpl.reset();
  this.playerWrapper.reset();
  this.adUi.reset();
};

/**
 * Listener JSDoc for ESLint. This listener can be passed to
 * (add|remove)ContentEndedListener.
 * @callback listener
 */

/**
 * Adds a listener for the 'contentended' event of the video player. This should
 * be used instead of setting an 'contentended' listener directly to ensure that
 * the ima can do proper cleanup of the SDK before other event listeners are
 * called.
 * @param {listener} listener The listener to be called when content
 *     completes.
 */
Controller.prototype.addContentEndedListener = function (listener) {
  this.playerWrapper.addContentEndedListener(listener);
};

/**
 * Adds a listener that will be called when content and all ads have
 * finished playing.
 * @param {listener} listener The listener to be called when content and ads
 *     complete.
 */
Controller.prototype.addContentAndAdsEndedListener = function (listener) {
  this.contentAndAdsEndedListeners.push(listener);
};

/**
 * Sets the listener to be called to trigger manual ad break playback.
 * @param {listener} listener The listener to be called to trigger manual ad
 *     break playback.
 */
Controller.prototype.setAdBreakReadyListener = function (listener) {
  this.sdkImpl.setAdBreakReadyListener(listener);
};

/**
 * Changes the flag to show or hide the ad countdown timer.
 *
 * @param {boolean} showCountdownIn Show or hide the countdown timer.
 */
Controller.prototype.setShowCountdown = function (showCountdownIn) {
  this.adUi.setShowCountdown(showCountdownIn);
  this.showCountdown = showCountdownIn;
  this.adUi.countdownDiv.style.display = this.showCountdown ? 'block' : 'none';
};

/**
 * Initializes the AdDisplayContainer. On mobile, this must be done as a
 * result of user action.
 */
Controller.prototype.initializeAdDisplayContainer = function () {
  this.sdkImpl.initializeAdDisplayContainer();
};

/**
 * Called by publishers in manual ad break playback mode to start an ad
 * break.
 */
Controller.prototype.playAdBreak = function () {
  this.sdkImpl.playAdBreak();
};

/**
 * Callback JSDoc for ESLint. This callback can be passed to addEventListener.
 * @callback callback
 */

/**
 * Ads an EventListener to the AdsManager. For a list of available events,
 * see
 * https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/js/google.ima.AdEvent#.Type
 * @param {google.ima.AdEvent.Type} event The AdEvent.Type for which to
 *     listen.
 * @param {callback} callback The method to call when the event is fired.
 */
Controller.prototype.addEventListener = function (event, callback) {
  this.sdkImpl.addEventListener(event, callback);
};

/**
 * Returns the instance of the AdsManager.
 * @return {google.ima.AdsManager} The AdsManager being used by the plugin.
 */
Controller.prototype.getAdsManager = function () {
  return this.sdkImpl.getAdsManager();
};

/**
 * Returns the instance of the player id.
 * @return {string} The player id.
 */
Controller.prototype.getPlayerId = function () {
  return this.playerWrapper.getPlayerId();
};

/**
 * Changes the ad tag. You will need to call requestAds after this method
 * for the new ads to be requested.
 * @param {?string} adTag The ad tag to be requested the next time
 *     requestAds is called.
 */
Controller.prototype.changeAdTag = function (adTag) {
  this.reset();
  this.settings.adTagUrl = adTag;
};

/**
 * Pauses the ad.
 */
Controller.prototype.pauseAd = function () {
  this.adUi.onAdsPaused();
  this.sdkImpl.pauseAds();
};

/**
 * Resumes the ad.
 */
Controller.prototype.resumeAd = function () {
  this.adUi.onAdsPlaying();
  this.sdkImpl.resumeAds();
};

/**
 * Toggles video/ad playback.
 */
Controller.prototype.togglePlayback = function () {
  this.playerWrapper.togglePlayback();
};

/**
 * @return {boolean} true if we expect that ads will autoplay. false otherwise.
 */
Controller.prototype.adsWillAutoplay = function () {
  if (this.settings.adsWillAutoplay !== undefined) {
    return this.settings.adsWillAutoplay;
  } else if (this.settings.adWillAutoplay !== undefined) {
    return this.settings.adWillAutoplay;
  } else {
    return !!this.playerWrapper.getPlayerOptions().autoplay;
  }
};

/**
 * @return {boolean} true if we expect that ads will autoplay. false otherwise.
 */
Controller.prototype.adsWillPlayMuted = function () {
  if (this.settings.adsWillPlayMuted !== undefined) {
    return this.settings.adsWillPlayMuted;
  } else if (this.settings.adWillPlayMuted !== undefined) {
    return this.settings.adWillPlayMuted;
  } else if (this.playerWrapper.getPlayerOptions().muted !== undefined) {
    return this.playerWrapper.getPlayerOptions().muted;
  } else {
    return this.playerWrapper.getVolume() == 0;
  }
};

/**
 * Triggers an event on the VJS player
 * @param  {string} name The event name.
 * @param  {Object} data The event data.
 */
Controller.prototype.triggerPlayerEvent = function (name, data) {
  this.playerWrapper.triggerPlayerEvent(name, data);
};

/**
 * Extends an object to include the contents of objects at parameters 2 onward.
 *
 * @param {Object} obj The object onto which the subsequent objects' parameters
 *     will be extended. This object will be modified.
 * @param {...Object} var_args The objects whose properties are to be extended
 *     onto obj.
 * @return {Object} The extended object.
 */
Controller.prototype.extend = function (obj) {
  var arg = void 0;
  var index = void 0;
  var key = void 0;

  for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
    args[_key - 1] = arguments[_key];
  }

  for (index = 0; index < args.length; index++) {
    arg = args[index];
    for (key in arg) {
      if (arg.hasOwnProperty(key)) {
        obj[key] = arg[key];
      }
    }
  }
  return obj;
};

/**
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * IMA SDK integration plugin for Video.js. For more information see
 * https://www.github.com/googleads/videojs-ima
 */

/**
 * Exposes the ImaPlugin to a publisher implementation.
 *
 * @param {Object} player Instance of the video.js player to which this plugin
 *     will be added.
 * @param {Object} options Options provided by the implementation.
 * @constructor
 * @struct
 * @final
 */
var ImaPlugin = function ImaPlugin(player, options) {
  this.controller = new Controller(player, options);

  /**
   * Listener JSDoc for ESLint. This listener can be passed to
   * addContent(AndAds)EndedListener.
   * @callback listener
   */

  /**
   * Adds a listener that will be called when content and all ads have
   * finished playing.
   * @param {listener} listener The listener to be called when content and ads
   *     complete.
   */
  this.addContentAndAdsEndedListener = function (listener) {
    this.controller.addContentAndAdsEndedListener(listener);
  }.bind(this);

  /**
   * Adds a listener for the 'contentended' event of the video player. This
   * should be used instead of setting an 'contentended' listener directly to
   * ensure that the ima can do proper cleanup of the SDK before other event
   * listeners are called.
   * @param {listener} listener The listener to be called when content
   *     completes.
   */
  this.addContentEndedListener = function (listener) {
    this.controller.addContentEndedListener(listener);
  }.bind(this);

  /**
   * Callback JSDoc for ESLint. This callback can be passed to addEventListener.
   * @callback callback
   */

  /**
   * Ads an EventListener to the AdsManager. For a list of available events,
   * see
   * https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/js/google.ima.AdEvent#.Type
   * @param {google.ima.AdEvent.Type} event The AdEvent.Type for which to
   *     listen.
   * @param {callback} callback The method to call when the event is fired.
   */
  this.addEventListener = function (event, callback) {
    this.controller.addEventListener(event, callback);
  }.bind(this);

  /**
   * Changes the ad tag. You will need to call requestAds after this method
   * for the new ads to be requested.
   * @param {?string} adTag The ad tag to be requested the next time requestAds
   *     is called.
   */
  this.changeAdTag = function (adTag) {
    this.controller.changeAdTag(adTag);
  }.bind(this);

  /**
   * Returns the instance of the AdsManager.
   * @return {google.ima.AdsManager} The AdsManager being used by the plugin.
   */
  this.getAdsManager = function () {
    return this.controller.getAdsManager();
  }.bind(this);

  /**
   * Initializes the AdDisplayContainer. On mobile, this must be done as a
   * result of user action.
   */
  this.initializeAdDisplayContainer = function () {
    this.controller.initializeAdDisplayContainer();
  }.bind(this);

  /**
   * Pauses the ad.
   */
  this.pauseAd = function () {
    this.controller.pauseAd();
  }.bind(this);

  /**
   * Called by publishers in manual ad break playback mode to start an ad
   * break.
   */
  this.playAdBreak = function () {
    this.controller.playAdBreak();
  }.bind(this);

  /**
   * Creates the AdsRequest and request ads through the AdsLoader.
   */
  this.requestAds = function () {
    this.controller.requestAds();
  }.bind(this);

  /**
   * Resumes the ad.
   */
  this.resumeAd = function () {
    this.controller.resumeAd();
  }.bind(this);

  /**
   * Sets the listener to be called to trigger manual ad break playback.
   * @param {listener} listener The listener to be called to trigger manual ad
   *     break playback.
   */
  this.setAdBreakReadyListener = function (listener) {
    this.controller.setAdBreakReadyListener(listener);
  }.bind(this);

  /**
   * Sets the content of the video player. You should use this method instead
   * of setting the content src directly to ensure the proper ad tag is
   * requested when the video content is loaded.
   * @param {?string} contentSrc The URI for the content to be played. Leave
   *     blank to use the existing content.
   * @param {?string} adTag The ad tag to be requested when the content loads.
   *     Leave blank to use the existing ad tag.
   */
  this.setContentWithAdTag = function (contentSrc, adTag) {
    this.controller.setContentWithAdTag(contentSrc, adTag);
  }.bind(this);

  /**
   * Sets the content of the video player. You should use this method instead
   * of setting the content src directly to ensure the proper ads response is
   * used when the video content is loaded.
   * @param {?string} contentSrc The URI for the content to be played. Leave
   *     blank to use the existing content.
   * @param {?string} adsResponse The ads response to be requested when the
   *     content loads. Leave blank to use the existing ads response.
   */
  this.setContentWithAdsResponse = function (contentSrc, adsResponse) {
    this.controller.setContentWithAdsResponse(contentSrc, adsResponse);
  }.bind(this);

  /**
   * Sets the content of the video player. You should use this method instead
   * of setting the content src directly to ensure the proper ads request is
   * used when the video content is loaded.
   * @param {?string} contentSrc The URI for the content to be played. Leave
   *     blank to use the existing content.
   * @param {?Object} adsRequest The ads request to be requested when the
   *     content loads. Leave blank to use the existing ads request.
   */
  this.setContentWithAdsRequest = function (contentSrc, adsRequest) {
    this.controller.setContentWithAdsRequest(contentSrc, adsRequest);
  }.bind(this);

  /**
   * Changes the flag to show or hide the ad countdown timer.
   *
   * @param {boolean} showCountdownIn Show or hide the countdown timer.
   */
  this.setShowCountdown = function (showCountdownIn) {
    this.controller.setShowCountdown(showCountdownIn);
  }.bind(this);
};

var init = function init(options) {
  /* eslint no-invalid-this: 'off' */
  this.ima = new ImaPlugin(this, options);
};

var registerPlugin = videojs.registerPlugin || videojs.plugin;
registerPlugin('ima', init);

return ImaPlugin;

})));var oe24_jwplayer_setup_type = 'WEB'; // for webpages use „type“ = 'WEB' - for app 'APP'

var appDet = new Array(
    /\(Linux; Android [\.0-9]+; .+?(wv)?\) AppleWebKit\/[\.0-9]+ \(KHTML, like Gecko\) Version\/.+?Chrome\/.+? Mobile Safari\/[\.0-9]+/i,
    /Mozilla\/5.0 \(Linux; U; Android [\.0-9]+; en-gb; Build\/KLP\) AppleWebKit\/[\.0-9]+ \(KHTML, like Gecko\) Version\/4.0 Safari\/[\.0-9]+/i,
    /Mozilla\/5.0 \(Linux; Android [\.0-9]+; Nexus 5 Build\/_BuildID_\) AppleWebKit\/[\.0-9]+ \(KHTML, like Gecko\) Version\/4.0 Chrome\/.+? Mobile Safari\/[\.0-9]+/i,
    /Mozilla\/5.0 \(Linux; Android [\.0-9]+; Nexus 5 Build\/LMY48B; wv\) AppleWebKit\/[\.0-9]+ \(KHTML, like Gecko\) Version\/4.0 Chrome\/.+? Mobile Safari\/[\.0-9]+/i,
    /oe24\.at\/[\.0-9]+ \(com.iphone-wizard.OE24; build:[\.0-9]+; iOS [\.0-9]+\) Alamofire\/[\.0-9]+/i
);

var appDetDevice = new Array(
    'Android_oe24', 'Android_oe24', 'Android_oe24', 'Android_oe24', 'iOS_oe24'
);
var oe24_jwplayer_app_device = 'web';
var oe24consentLoadedtcString = '';

for (var reg in appDet) {
    if (navigator.userAgent.match(appDet[reg])) {
        oe24_jwplayer_setup_type = 'APP';
        oe24_jwplayer_app_device = appDetDevice[reg];
        break;
    }
}

if (window.location.href.indexOf('dev') > -1 || window.location.href.indexOf('.local') > -1) {
    // for preproduction
    var oe24_jwplayer_setup_media = 'oe24test';
    var oe24_jwplayer_setup_url = '//at-config-preproduction.sensic.net/s2s-web.js';
} else {
    // for production
    var oe24_jwplayer_setup_media = 'oe24';
    var oe24_jwplayer_setup_url = '//at-config.sensic.net/s2s-web.js';
}

if (oe24_jwplayer_setup_type == 'APP') {

    var oe24_jwplayer_isMobile = {
        Android: function() {
            return navigator.userAgent.match(/Android/i);
        },
        BlackBerry: function() {
            return navigator.userAgent.match(/BlackBerry/i);
        },
        iOS: function() {
            return navigator.userAgent.match(/iPhone|iPod/i);
        },
        Opera: function() {
            return navigator.userAgent.match(/Opera Mini/i);
        },
        Windows: function() {
            return navigator.userAgent.match(/IEMobile/i);
        },
        any: function() {
            return ((oe24_jwplayer_isMobile.Android() || oe24_jwplayer_isMobile.BlackBerry() || oe24_jwplayer_isMobile.iOS() || oe24_jwplayer_isMobile.Opera() || oe24_jwplayer_isMobile.Windows()));
        }
    };

    var oe24_jwplayer_setup_device = (oe24_jwplayer_isMobile.any()) ? "SMARTPHONE" : "TABLET";

    var gfkS2sConf = {
        media: oe24_jwplayer_setup_media,
        url: oe24_jwplayer_setup_url,
        type: oe24_jwplayer_setup_type, // for webpages use „type“ = WEB
        device: oe24_jwplayer_setup_device, // use either TABLET or SMARTPHONE or UNKNOWN
        ai: "[AdvertisingId/IDFA]" // providing this value is mandatory

    };
} else {
    var gfkS2sConf = {
        media: oe24_jwplayer_setup_media,
        url: oe24_jwplayer_setup_url,
        type: oe24_jwplayer_setup_type // for webpages use „type“ = WEB
    };

}

;(function($) {
    "use strict";

    var oe24jwplayerAdTime = undefined;
    var player, tab;
    
        
        function videoJsGfk(el) {
            this.$el = $(el);
            // this.$relatedWrapper = this.$el.nextAll('.videoPlayerRelatedWrapper');
            // this.$replayBtn = this.$relatedWrapper.find('.videoPlayerReplay');
            // this.$relatedItems = this.$relatedWrapper.find('.videoPlayerRelatedItems');
            // this.countRelatedItems = this.$relatedItems.find('.videoPlayerRelatedItem').length;

            // this.ga = undefined;
            // this.trackingName = undefined;

            this.jwplayerId = this.$el.attr('id');
            this.videoId = (this.jwplayerId == 'mobileTeaserOe24TvCustom') ? '251215975' : this.jwplayerId.split('_')[1];

            // AGTT Teletest Tracking START
            this.adTime = undefined;
            this.adDuration = undefined;

            this.gfkInitAd = false;
            this.gfkAdPosition = '';
            this.gfkInitVideo = false;
            this.oe24PreDone = false;

            this.isLivestream = false;
            this.oe24LiveStreamPaused = 0;
            this.oe24LiveStreamPausedSum = 0;
            
            // helper to remind the current playing-state
            this.oe24Playing = false;
            // AGTT Teletest Tracking END

            // helper for naming
            this.gfkAdPosition = '';
            this.oe24LastPlayedId = '';

            var defaults = {
                // primary: 'flash', // zum austesten, ob flash funktioniert.
                flashplayer: '/8.17.1/jwplayer.flash.swf', // wird ueber die page-datei _shared/page/jwplayer/jwplayer.page aufgeloest
                // key: 'QcCdgx3inM94dJ9izldPrT3TuCMlZ+e+QhYdRg==',
                key: '2FsrTep9OcXBJctufEe413UqWJsrr4d5rUgyi06J8Ki97VJ/',
                displaytitle: false,
                displaydescription: false,
                hlshtml: true,
                androidhls: true,
                aspectratio: '16:9',
                width: '100%',
                stretching: 'uniform',
                preload: 'auto',
                ga: {}
            };
            var defaultsEvent = {
                ready: true,
                error: true,
                adPlay: true,
                adRequest: true,
                play: true,
                firstFrame: true,
                beforeComplete: true,
                complete: true
            };

            // (ws) 2017-10-17 DAILY-897
            // Im Falle eines Video-Fehlers soll nur einmal ein "custom" Element mit der Fehlermeldung erzeugt werden
            this.customMessageBoxDone = false;
            // (ws) 2017-10-17 DAILY-897 end

            var elOpts = this.$el.data('video-setup');
            if (typeof elOpts == 'undefined') {
                // Backend Problematik
                elOpts = JSON.parse(this.$el.attr('data-video-setup'));
            }
            
            // handle cookie-consent
            // if(oe24consentLoadedtcString.length){
            //     if(typeof elOpts.advertising != 'undefined'){
            //         for (var s in elOpts.advertising.schedule) {
            //             elOpts.advertising.schedule[s].tag += '&gdpr=1&gdpr_pd=1&gdpr_consent=' + oe24consentLoadedtcString;
            //         }
            //     }
            // }
            
            this.playerOptions = $.extend(defaults, elOpts);

            var elOptsEvent = this.$el.data('video-opts-event');
            if (typeof elOptsEvent == 'undefined') {
                // Backend Problematik
                elOptsEvent = JSON.parse(this.$el.attr('data-video-opts-event'));
            }
            this.playerOptionsEvent = $.extend(defaultsEvent, elOptsEvent);

            this.elAgttData = this.$el.data('video-data');
            if (typeof elAgttData == 'undefined') {
                // Backend Problematik
                this.elAgttData = JSON.parse(this.$el.attr('data-video-data'));
            }

            if ((this.elAgttData.cliptype.toLowerCase() == 'live' || this.elAgttData.cliptype.toLowerCase() == 'auto_live' || this.elAgttData.cliptype.toLowerCase() == 'audio_live')) {
                this.isLivestream = true;
            }

            // additional elAgttData
            this.elAgttData.channel = 'oe24';
            this.elAgttData.deviceid = 'web';
            this.elAgttData.deviceid = (oe24_jwplayer_setup_type == 'APP') ? oe24_jwplayer_app_device : this.elAgttData.deviceid;
            this.elAgttData.videopartid = '1_1';

            this.elAgttData.playerid = (isMobileDevice()) ? 'oe24.mobile.agtt' : 'oe24.video.agtt';
            this.elAgttData.playerid = (oe24_jwplayer_setup_type == 'APP') ? 'oe24.app.agtt' : this.elAgttData.playerid;

            this.elAgttData.airdate = getOe24IsoDate(this.elAgttData.airdate);
            this.elAgttData.clipreleasetime = getOe24IsoDate(this.elAgttData.clipreleasetime);

            this.handleVisibility();
            var rc = this.initVideo();
            
            if (false === rc) {
                return false;
            }

            this.initGfkJsTracking();
            
            // this.initGoogleAnalytics();
            // this.oe24TrackingEvent();
            this.addEventListeners();

            return;
        }

        
            
           
        videoJsGfk.prototype.addEventListeners = function(calledBy) {

            var self = this;
            // AGTT Teletest Tracking START
            function gfkSetIsPlaying(isPlaying, playerPosition) {
                
                var state = self.oe24Playing;

                var contentId = 'default';


                // var videoId = (self.playerOptions.playlist[0].title) ? self.playerOptions.playlist[0].title : self.videoId;
                // var originalVideoId = videoId;

                // // advertisments must have another videoId
                // var videoId = (self.gfkInitAd) ? videoId + '_Ad_' + self.gfkAdPosition : videoId;


                // video-id - should be an unique-id, can be the same as episode-id (according to gfk), but should be another one, when in an advertisement
                var videoId = (self.videoId) ? self.videoId : self.elAgttData.episodeid;

                // advertisments must have another videoId
                var videoId = (self.gfkInitAd) ? videoId + '_Ad_' + self.gfkAdPosition : videoId;
                var originalVideoId = videoId;
                var videoId = String(videoId);
                
                var volume = self.player.volume().toString();

                var fullscreen = (self.player.isFullscreen()) ? '1' : '0';

                var cliptype = self.elAgttData.cliptype; // "[ContentId]"
                // cliptype = (self.gfkInitAd && playerPosition<=0) ? 'preroll' : cliptype;
                // cliptype = (self.gfkInitAd && playerPosition>0) ? 'midroll' : cliptype;
                cliptype = (self.gfkInitAd && self.gfkAdPosition != '') ? self.gfkAdPosition : cliptype;
                cliptype = gfkGetPosition(cliptype);

                var liveStreamPaused = 0;
                // if ((self.elAgttData.cliptype.toLowerCase() == 'live' || self.elAgttData.cliptype.toLowerCase() == 'auto_live' || self.elAgttData.cliptype.toLowerCase() == 'audio_live') && !self.gfkInitAd) {
                //     var now = new Date().getTime();
                //     liveStreamPaused = (self.oe24LiveStreamPaused != 0) ? (now - self.oe24LiveStreamPaused) : 0;
                //     liveStreamPaused += self.oe24LiveStreamPausedSum;
                //     self.oe24LiveStreamPaused = 0;
                //     // remember cumulative sum of paused-time during livestream if users pauses again during the stream
                //     self.oe24LiveStreamPausedSum = liveStreamPaused;
                // }

                var videoduration = (self.gfkInitAd && self.adDuration) ? self.adDuration : self.elAgttData.videoduration;

                var customobject = {
                    "cliptype": cliptype,
                    "videotitle": self.elAgttData.videotitle,
                    "episodeid": self.elAgttData.episodeid,
                    "videopartid": self.elAgttData.videopartid,
                    "airdate": self.elAgttData.airdate,
                    "playerid": self.elAgttData.playerid,
                    "channel": self.elAgttData.channel,
                    "deviceid": self.elAgttData.deviceid,
                    "playerduration": videoduration,
                    "videoduration": videoduration,
                    "episodeduration": videoduration,
                    "programname": self.elAgttData.programname,
                    "clipreleasetime": self.elAgttData.clipreleasetime,
                    "videoid": originalVideoId
                };
                
                var videoOptions = {
                    "screen": fullscreen,
                    "volume": volume
                    // "deviceType": 
                };
                
                if (isPlaying) {
                    // set state only if its currently not 'playing'
                    if (!state) {
                        if ((self.elAgttData.cliptype == 'Live' || self.elAgttData.cliptype == 'Auto_live' || self.elAgttData.cliptype.toLowerCase() == 'audio_live') && self.gfkAdPosition.length <= 0) {
                            // Livestream
                            self.gfkAgent.playStreamLive(contentId, '', liveStreamPaused, videoId, videoOptions, customobject);
                        } else {
                            // Video on Demand
                            self.gfkAgent.playStreamOnDemand(contentId, videoId, playerPosition, videoOptions, customobject);
                        }
                        self.oe24Playing = true;
                    }
                } else {
                    // set state only if its currently not 'paused'
                    if (state) {
                        if ((self.elAgttData.cliptype == 'Live' || self.elAgttData.cliptype == 'Auto_live' || self.elAgttData.cliptype.toLowerCase() == 'audio_live') && self.gfkAdPosition.length <= 0) {
                            self.gfkAgent.stop();
                        }
                        else{
                            self.gfkAgent.stop(playerPosition);
                        }
                        self.oe24Playing = false;
                        self.oe24LiveStreamPaused = new Date().getTime();
                    }
                }
            }

            function gfkGetPosition(adPosition) {
                if(typeof adPosition == 'undefined'){
                    return 'Preroll';
                }
                var returnAdPosition = (adPosition.toLowerCase() == 'pre') ? 'Preroll' : adPosition;
                returnAdPosition = (adPosition.toLowerCase() == 'mid') ? 'Midroll' : returnAdPosition;
                returnAdPosition = (adPosition.toLowerCase() == 'post') ? 'Postroll' : returnAdPosition;
    
                return returnAdPosition;
            }

            function gfkPlayEvent(event) {
                
                if (self.gfkInitVideo === false) {
                    return;
                }               

                // stopOtherPlayer();

                self.adTime = 0;
                oe24jwplayerAdTime = 0;
                var playerPos = Math.round(self.player.currentTime() * 1000);
                gfkSetIsPlaying(true, playerPos);
            }            
            function gfkPauseEvent(event) {
                var playerPos = Math.round(self.player.currentTime() * 1000);
                gfkSetIsPlaying(false, playerPos);
            }
            function gfkStopEvent(event) {
                var playerPos = Math.round(self.player.currentTime() * 1000);
                gfkSetIsPlaying(false, playerPos);
            }
            function gfkEndedEvent(event) {
                var playerPos = Math.round(self.player.currentTime() * 1000);
                gfkSetIsPlaying(false, playerPos);
                // self.gfkInitVideo = false;
                
            }
            function gfkVolumeChangeEvent(event) {
                var volume = self.player.volume();
                self.gfkAgent.volume(volume.toString());
            }

            function gfkAdStarted(event) {
                self.adDuration = Math.round(event.l.g.duration);
                
                if (self.gfkInitAd === true) {
                    return;
                }

                self.adTime = 0;
                // var adPosition = event.adposition;
                // adPosition = ('mid' === adPosition && 'nonlinear' === event.linear) ? 'overlay' : adPosition;
                // self.gfkAdPosition = gfkGetPosition(adPosition);
                var offset = event.l.g.adPodInfo.timeOffset;
                var adPosition = 'pre';
                adPosition = (typeof offset !== 'undefined' && offset > 0) ? 'mid' : adPosition;
                self.gfkAdPosition = gfkGetPosition(adPosition);

                if (self.gfkAdPosition === 'overlay') {
                    return;
                }

                self.gfkInitAd = true;
                self.adTime = Math.round(self.player.currentTime() * 1000);
                oe24jwplayerAdTime = Math.round(self.player.currentTime() * 1000);

                gfkSetIsPlaying(true, 0);
            }
            function gfkAdPaused(event) {
                gfkSetIsPlaying(false, self.adTime);
            }
            function gfkAdResumed(event) {
                // oe24Tracking();

                if (self.gfkInitAd === false) {
                    return;
                }
                stopOtherPlayer();
                gfkSetIsPlaying(true, self.adTime);
            }
            
            function gfkAdCompleted(event) {
                if (self.gfkAdPosition == 'overlay') {
                    return;
                }
    
                self.oe24PreDone = true;
    
                gfkSetIsPlaying(false, self.adTime);
    
                self.gfkInitAd = false;
    
                self.adTime = undefined;
                self.adDuration = undefined;
                oe24jwplayerAdTime = 0;
                gfkSetIsPlaying(false, 0);
    
                self.gfkAdPosition = '';
            }
            
            function gfkAdBreakReady(event) {
                
            }
            function gfkAdContentPaused(event) {
                gfkPauseEvent(event);
            }
            function gfkAdContentResumed(event) {
                self.player.play();
                // stopOtherPlayer();
                gfkPlayEvent(event);
            }

            function gfkAdError(event) {
                
            }

            function gfkAdProgress(event) {
                var adProgressData= event.getAdData();
                oe24jwplayerAdTime = parseInt(adProgressData.currentTime * 1000); // time in milliseconds                
            }

            function stopOtherPlayer(){
                //pause other video
                $(".video-js").each(function (index) {
                    if ( typeof this.id != 'undefined' && typeof self.jwplayerId != 'undefined') {
                        if ( this.id != self.jwplayerId) {
                            if(typeof this.player !== 'undefined'){
                                if(typeof this.player.pause === 'function'){
                                    this.player.pause();
                                    if(typeof this.player.ima !== 'undefined'){
                                        if(typeof this.player.ima.pauseAd === 'function'){
                                            this.player.ima.pauseAd();
                                        }
                                    }
                                }
                            }
                        }
                    }
                });
                // self.player.play();
            }
            function gfkLoadStart(){
                // self.player.play();
            }
            window.onbeforeunload = function() {
                gfkStopEvent();
            };
            if (typeof this.gfkAgent !== 'undefined') {
                this.player.on('play',gfkPlayEvent);
                this.player.on('pause',gfkPauseEvent);
                this.player.on('stop',gfkStopEvent);
                this.player.on('ended',gfkEndedEvent);
                this.player.on('volumechange',gfkVolumeChangeEvent);
                this.player.on('loadstart',gfkLoadStart);
                
                // this.player.adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, gfkAdStarted);
                // this.player.adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, gfkAdError);

                this.player.on('adsready', function(){
                    self.player.ima.addEventListener(
                        google.ima.AdEvent.Type.STARTED,gfkAdStarted
                    );
                    self.player.ima.addEventListener(
                        google.ima.AdErrorEvent.Type.AD_ERROR,gfkAdError
                    );
                    self.player.ima.addEventListener(
                        google.ima.AdEvent.Type.PAUSED,gfkAdPaused
                    );
                    self.player.ima.addEventListener(
                        google.ima.AdEvent.Type.COMPLETE,gfkAdCompleted
                    );
                    self.player.ima.addEventListener(
                        google.ima.AdEvent.Type.RESUMED,gfkAdResumed
                    );

                    self.player.ima.addEventListener(
                        google.ima.AdEvent.Type.AD_BREAK_READY,gfkAdBreakReady
                    );
                    self.player.ima.addEventListener(
                        google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED,gfkAdContentPaused
                    );
                    self.player.ima.addEventListener(
                        google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED,gfkAdContentResumed
                    );
                    
                    self.player.ima.addEventListener(
                        google.ima.AdEvent.Type.AD_PROGRESS,gfkAdProgress
                    );
                    
                });


                
            }
        }

        videoJsGfk.prototype.initGfkJsTracking = function() {
            // old gfk-Tag 
            // (function(w, d, c, s, id, v) {
            //     if (d.getElementById(id)) {
            //         return;
            //     }
    
            //     w[id] = {};
            //     w[id].agents = [];
            //     var api = ["playLive", "playVOD", "stop", "skip", "screen", "volume", "impression"];
            //     w.s = (function() {
            //         function s(c, pId, cb) {
            //             var sA = { queue: [], config: c, cb: cb, pId: pId };
            //             api.forEach(function(e) {
            //                 sA[e] = function() {
            //                     sA.p = cb();
            //                     sA.queue.push({ f: e, a: arguments })
            //                 };
            //             });
            //             return sA;
            //         }
            //         return s;
            //     }());
    
            //     w[id].getAgent = function(cb, pId) {
            //         var a = {
            //             a: new w.s(c, pId || "", cb || function() {
            //                 return 0;
            //             })
            //         };
            //         api.forEach(function(e) {
            //             a[e] = function() {
            //                 return this.a[e].apply(this.a, arguments);
            //             }
            //         });
            //         w[id].agents.push(a);
            //         return a;
            //     };
    
            //     var lJS = function(eId, url) {
            //         var tag = d.createElement(s);
            //         var el = d.getElementsByTagName(s)[0];
            //         tag.id = eId;
            //         tag.async = true;
            //         tag.type = 'text/javascript';
            //         tag.src = url;
            //         el.parentNode.insertBefore(tag, el);
            //     };
    
            //     lJS(id, c.url);
    
            // })(window, document, gfkS2sConf, 'script', 'gfkS2s');

            // new gfk-Tag with new functions playStreamLive, playStreamOnDemand
            (function (w, d, c, s, id, v) {
                if (d.getElementById(id)) {
                    return;
                }
              
                w.gfkS2sConf = c;
                w[id] = {};
                w[id].agents = [];
                var api = ["playStreamLive", "playLive", "playStreamOnDemand", "playVOD", "stop", "skip", "screen", "volume", "impression"];
                w.gfks = (function () {
                    function f(sA, e, cb) {
                        return function () {
                            sA.p = cb();
                            sA.queue.push({f: e, a: arguments});
                        };
                    }
                    function s(c, pId, cb) {
                        var sA = {queue: [], config: c, cb: cb, pId: pId};
                        for (var i = 0; i < api.length; i++) {
                            var e = api[i];
                            sA[e] = f(sA, e, cb);
                        }
                        return sA;
                    }
                    return s;
                }());
                w[id].getAgent = function (cb, pId) {
                    var a = {
                        a: new w.gfks(c, pId || "", cb || function () {
                            return 0;
                        })
                    };
                    function g(a, e) {
                        return function () {
                            return a.a[e].apply(a.a, arguments);
                        }
                    }
                    for (var i = 0; i < api.length; i++) {
                        var e = api[i];
                        a[e] = g(a, e);
                    }
                    w[id].agents.push(a);
                    return a;
                };
              
                var lJS = function (eId, url) {
                    var tag = d.createElement(s);
                    var el = d.getElementsByTagName(s)[0];
                    tag.id = eId;
                    tag.async = true;
                    tag.type = 'text/javascript';
                    tag.src = url;
                    el.parentNode.insertBefore(tag, el);
                };
              
                if (c.hasOwnProperty(v)) {lJS(id + v, c[v]);}
                lJS(id, c.url);
            })(window, document, gfkS2sConf, 'script', 'gfkS2s', 'visUrl');
    
    
            var player = this.player;
            // VOD: Callback method must return the current video position in milliseconds.
            function videoPositionCallback() {
    
                if (oe24jwplayerAdTime != undefined && oe24jwplayerAdTime > 0) {
                    var position = oe24jwplayerAdTime;
                } else {
                    var position = Math.round(player.currentTime() * 1000); //must return milliseconds!
                }
    
                return position;
            }
            // playerId is the id of the <video> element
            var playerId = this.jwplayerId;
            this.gfkAgent = gfkS2s.getAgent(videoPositionCallback, playerId);
    
        }

        
        function isMobileDevice() {
            // www.detectmobilebrowsers.com
            // Regex updated: 1 August 2014
            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;
            }
            return false;
        }

        function getOe24IsoDate(date2change) {
            if (date2change == null) return date2change;

            if (date2change.length < 16) {
                return date2change;
            }

            var day = date2change.substring(0, 2);
            var month = parseInt(date2change.substring(3, 5)) - 1;
            var year = date2change.substring(6, 10);
            var hour = date2change.substring(11, 13);
            var minute = date2change.substring(14, 16);

            var d = new Date(year, month, day, hour, minute, 0, 0);
            var nd = d.toISOString();

            return nd.toString();
        }

        
        // If the page is hidden, pause the video;
        // if the page is shown, play the video
        function handleVisibilityChange() {
            if (document[hidden]) {
                tab = 0;
            } else {
                tab = 1;
            }
        }

        videoJsGfk.prototype.handleVisibility = function() {
        
            if(typeof window.document.visibilityState !== 'undefined'){
                if(window.document.visibilityState == 'visible'){
                    tab = 1;
                }
                else {
                    tab = 0;
                }
                return;
            }

            if(typeof window.document.hasFocus !== "undefined"){
                if (window.document.hasFocus()){
                    tab = 1;
                }
                else {
                    tab = 0;
                }

                return;
            }

            if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
                hidden = "hidden";
                visibilityChange = "visibilitychange";
            } else if (typeof document.msHidden !== "undefined") {
                hidden = "msHidden";
                visibilityChange = "msvisibilitychange";
            } else if (typeof document.webkitHidden !== "undefined") {
                hidden = "webkitHidden";
                visibilityChange = "webkitvisibilitychange";
            }

            // Warn if the browser doesn't support addEventListener or the Page Visibility API
            if (typeof document.addEventListener === "undefined" || hidden === undefined) { tab = 1; } else {
                // Handle page visibility change
                document.addEventListener(visibilityChange, handleVisibilityChange, false);
                handleVisibilityChange();
            }
        }

        
        videoJsGfk.prototype.initVideo = function() {
            if (typeof this.jwplayerId === 'undefined') {
                return false;
            }
            // flappe
            var flap = ($(this.$el).hasClass('flap')) ? true : false;
            // autoplay only if in active browser
            if (!tab) {
                this.playerOptions.autoplay = false;
            }

            if (oe24_jwplayer_app_device == 'Android_oe24'){
                this.playerOptions.autoplay = false;
            }

            var playerSetup = $(this.$el).attr("data-video-setup");
            playerSetup = JSON.parse(playerSetup);

            var duration = this.elAgttData.videoduration;
            var adOptionDuration = (duration<=600) ? 'L3' : 'L4';
            adOptionDuration = (duration<=300) ? 'L2' : adOptionDuration;
            adOptionDuration = (duration<=120) ? 'L1' : adOptionDuration;
            adOptionDuration = (this.isLivestream) ? '' : adOptionDuration;

            var plattform = (isMobileDevice()) ? 'mweb' : '';
            plattform = (oe24_jwplayer_setup_type == 'APP') ? 'app' : plattform;

            var uStatus = 0; // todo: 0 - kein Login / 1 - Login / 2 - Subscriber
            
            var advideoType = '1'; // fallback channel?
            if(typeof this.elAgttData.advideoType !== 'undefined'){
                advideoType = (this.elAgttData.advideoType == 'article') ? '0' : advideoType;
                advideoType = (this.elAgttData.advideoType == 'channel') ? '1' : advideoType;
            }

            var videoShow = this.elAgttData.videotitle;
            videoShow = videoShow.replace(/[^a-zA-Z]/g, "");
            
            var videoName = 'Sonstiges';
            if(typeof this.elAgttData.videoAdCategory !== 'undefined'){
                videoName = this.elAgttData.videoAdCategory;
            }

            var correlator = Math.round(Math.random()*10000);
            
            // var videoAdserverCode = '/1011024/oe24.at/Instream/Livestream/Instream';
            var videoAdserverCode = '/1011024';
            
            // Domain
            var host = window.location.hostname;
            switch(host){
                case 'www.wetter.local':
                case 'dev.wetter.at':
                case 'www.wetter.at':
                case 'www.wetter-deutschland.com':
                    videoAdserverCode += (isMobileDevice()) ? '/mobile.wetter.at' : '/wetter.at';
                    break;

                case 'www.oe24.at':
                default:
                    videoAdserverCode += (isMobileDevice()) ? '/mobile.oe24.at' : '/oe24.at';
                    break;
            }
                        
            videoAdserverCode += ((this.elAgttData.cliptype == 'Live' || this.elAgttData.cliptype == 'Auto_live' || this.elAgttData.cliptype.toLowerCase() == 'audio_live') && this.gfkAdPosition.length <= 0) ? '/Instream/Livestream/Instream' : '/Instream/VOD/Instream';
                        

            // Test
            //https://pubads.g.doubleclick.net/gampad/ads?iu=/1011024/oe24.at-Test/Video/Video-Test1&description_url=https%3A%2F%2Fwww.oe24.at&tfcd=0&npa=0&sz=640x360&cust_params=adVideoLength%3D[VALUE]%26adVideoName%3D[VALUE]%26adVideoShow%3D[VALUE]%26adVideoType%3D[VALUE]%26plattform%3D[VALUE]%26uStatus%3D[VALUE]&vpa=click&gdfp_req=1&output=vast&unviewed_position_start=1&adrule=1&&vid_d=[VALUE]&allcues=[VALUE]&env=vp&impl=s&correlator=[VALUE]
            
            // Test-Prod1
            // var adTagUrl = 'https://pubads.g.doubleclick.net/gampad/ads?iu=/1011024/oe24.at-Test/Video/Video-Test1&description_url=https%3A%2F%2Fwww.oe24.at&tfcd=0&npa=0&sz=640x360&cust_params=';
            // Prod-Final
            var adTagUrl = 'https://pubads.g.doubleclick.net/gampad/ads?iu='+videoAdserverCode+'&description_url=https%3A%2F%2Fwww.oe24.at&tfcd=0&npa=0&sz=640x360&cust_params=';
            
            adTagUrl += 'adVideoLength%3D'+adOptionDuration+'%26';
            adTagUrl += 'adVideoName%3D'+videoName+'%26';
            adTagUrl += 'adVideoShow%3D'+videoShow+'%26';
            adTagUrl += 'adVideoType%3D'+advideoType+'%26';
            if(plattform) {
                adTagUrl += 'plattform%3D'+plattform+'%26';
            }
            adTagUrl += 'uStatus%3D'+uStatus;
            adTagUrl += '&vpa=click&gdfp_req=1&output=vast&unviewed_position_start=1&ad_rule=1';
            adTagUrl += '&vid_d='+duration;
            if(!this.isLivestream){
                adTagUrl += '&allcues=150000';
            }
            adTagUrl += '&env=vp&impl=s';
            adTagUrl += '&correlator='+correlator+'&gdpr=1&gdpr_consent='+oe24consentLoadedtcString;
            
            var adOptions = {
                // adTagUrl: 'https://pubads.g.doubleclick.net/gampad/ads?iu=/1011024/oe24.at-Test/Video/Video-Test1&description_url=http%3A%2F%2Fadverserve.net&tfcd=0&npa=0&sz=640x360&cust_params=adpageName%3Dtestpage%26adpageShow%3DTestshow%26adpageType%3D1&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator=&ad_rule=1&vid_d=20000&allcues=7000,14000&gdpr=1&gdpr_consent=CPLZZl7PLZZl7AcABBENBpCsAP_AAH_AAChQHjtX_T5eb2vj-3Z9N_tkeYwP99y3o2wzhhaIse8NwIeH7BoGI2MwvBX4JiQCGBAEsiKBAQdlHGBcCUAAgIgRiTKMYk2MjzNKJLJAilMbO0NYCD9mnsHTmZCY70-su__zv3eAAgIEAEAAIAAAAAAAAAAAAAAAAAMABAAIHjgEmCpeQANiWGBJtGlEKIAYVhAVACACggCAoGsIAAQE7AoCPUEAABCYAAQAAAAgogIBAAIBAEhEAEABgIBAARAIAAQAiQEIACJAAFgBYEAQACgGhIARQBCAIQYGAUcpgQEAAAAAAEAAEAAAAAAAAAAAAAAAAAAAAAAIAQoACAvMYABAXmAA.f_gAD_gAAAAA
                adTagUrl: adTagUrl
            };
            
            this.player = videojs(this.jwplayerId,playerSetup);
            this.player.ima(adOptions);
            // if(typeof playerSetup.playlist !== 'undefined'){
            //     if(playerSetup.playlist.length>1){
            //         this.player.playlist(playerSetup.playlist);
            //         this.player.playlist.autoadvance(0);
            //     }
            // }
            
            player=this.player;
            //pause other video
            // $(".video-js").each(function (index) {
            //     if ( typeof this.id != 'undefined') {
            //         if ( this.id != player.id) {
            //             this.player.pause();
            //         }
            //     }
            // });
            // self.player.play();

            if(flap){
               handleFlap(this.player);
            }

            this.gfkInitVideo = true;

            return true;

            
            
           
                
        }

        // Video in Flappe
        function handleFlap(player){
            var flap = document.querySelector('.oe24tvTopVideoLayer');
            
            if (flap != null) {
                var startMin = $('.oe24tvTopVideoLayer').hasClass('startMin') ? true : false;
                var startInitTime = (startMin) ? 2500 : 100;

                setTimeout(function() {
                    // bottom video-layer

                    if ($(".oe24tvTopVideoLayer").length) {
                        
                        // close layer
                        $('.oe24tvTopVideoLayer .videoLayerClose').click(function(e) {
                            $('.oe24tvTopVideoLayer').removeClass('tvLayerStart').addClass('tvLayerEnd');
                            // var player = document.querySelector('.oe24tvTopVideoLayer video');
                            if(player.ads.isInAdMode()){
                                player.ima.pauseAd();
                            }
                            else{
                                player.pause();
                            }                            
                        });
                        // open layer
                        $('.oe24tvTopVideoLayer .videoLayerUp').click(function(e) {
                            $('.oe24tvTopVideoLayer').removeClass('tvLayerEnd').addClass('tvLayerStart');
                            // var player = document.querySelector('.oe24tvTopVideoLayer video');
                                
                            if(player.ads.isInAdMode()){
                                player.ima.resumeAd();
                            }
                            else{
                                player.play();
                            }
                        });

                        if(startMin){
                            $('.oe24tvTopVideoLayer').removeClass('tvLayerStart').addClass('tvLayerEnd');
                        }
                        else {
                            $('.oe24tvTopVideoLayer').removeClass('tvLayerEnd').addClass('tvLayerStart');
                        }
                    }

                }, startInitTime);

            }
        }

    
    

        var __instances = {};
        $.fn.videoJsPlayer = function() {
            const selInstances = [];
            this.each(function() {
                const $this = $(this);
                var id = $this.attr('id');
                if (!__instances[id]) {
                    __instances[id] = new videoJsGfk(this);
                }
                selInstances.push(__instances[id]);
            });
            return selInstances.length === 1 ? selInstances[0] : selInstances;
        }

})(jQuery);

window.addEventListener("tcfConsentLoaded", function (e) {
    oe24consentLoadedtcString = e.tcString;

    $('.video-js').videoJsPlayer();
    
});

;(function($) {
    "use strict";

    console.log('youtube.js-');

    var oe24_jwplayer_setup_type = 'WEB'; // for webpages use „type“ = 'WEB' - for app 'APP'

    var appDet = new Array(
        /\(Linux; Android [\.0-9]+; .+?(wv)?\) AppleWebKit\/[\.0-9]+ \(KHTML, like Gecko\) Version\/.+?Chrome\/.+? Mobile Safari\/[\.0-9]+/i,
        /Mozilla\/5.0 \(Linux; U; Android [\.0-9]+; en-gb; Build\/KLP\) AppleWebKit\/[\.0-9]+ \(KHTML, like Gecko\) Version\/4.0 Safari\/[\.0-9]+/i,
        /Mozilla\/5.0 \(Linux; Android [\.0-9]+; Nexus 5 Build\/_BuildID_\) AppleWebKit\/[\.0-9]+ \(KHTML, like Gecko\) Version\/4.0 Chrome\/.+? Mobile Safari\/[\.0-9]+/i,
        /Mozilla\/5.0 \(Linux; Android [\.0-9]+; Nexus 5 Build\/LMY48B; wv\) AppleWebKit\/[\.0-9]+ \(KHTML, like Gecko\) Version\/4.0 Chrome\/.+? Mobile Safari\/[\.0-9]+/i,
        /oe24\.at\/[\.0-9]+ \(com.iphone-wizard.OE24; build:[\.0-9]+; iOS [\.0-9]+\) Alamofire\/[\.0-9]+/i
    );

    var appDetDevice = new Array(
        'Android_oe24', 'Android_oe24', 'Android_oe24', 'Android_oe24', 'iOS_oe24'
    );
    var oe24_jwplayer_app_device = 'web';
    var tcString = '';

    for (var reg in appDet) {
        if (navigator.userAgent.match(appDet[reg])) {
            oe24_jwplayer_setup_type = 'APP';
            oe24_jwplayer_app_device = appDetDevice[reg];
            break;
        }
    }

    if (window.location.href.indexOf('dev') > -1 || window.location.href.indexOf('.local') > -1) {
        // for preproduction
        var oe24_jwplayer_setup_media = 'oe24test';
        var oe24_jwplayer_setup_url = '//at-config-preproduction.sensic.net/s2s-web.js';
    } else {
        // for production
        var oe24_jwplayer_setup_media = 'oe24';
        var oe24_jwplayer_setup_url = '//at-config.sensic.net/s2s-web.js';
    }

    console.log('oe24_jwplayer_setup_media',oe24_jwplayer_setup_media);

    if (oe24_jwplayer_setup_type == 'APP') {

        var oe24_jwplayer_isMobile = {
            Android: function() {
                return navigator.userAgent.match(/Android/i);
            },
            BlackBerry: function() {
                return navigator.userAgent.match(/BlackBerry/i);
            },
            iOS: function() {
                return navigator.userAgent.match(/iPhone|iPod/i);
            },
            Opera: function() {
                return navigator.userAgent.match(/Opera Mini/i);
            },
            Windows: function() {
                return navigator.userAgent.match(/IEMobile/i);
            },
            any: function() {
                return ((oe24_jwplayer_isMobile.Android() || oe24_jwplayer_isMobile.BlackBerry() || oe24_jwplayer_isMobile.iOS() || oe24_jwplayer_isMobile.Opera() || oe24_jwplayer_isMobile.Windows()));
            }
        };

        var oe24_jwplayer_setup_device = (oe24_jwplayer_isMobile.any()) ? "SMARTPHONE" : "TABLET";

        var gfkS2sConf = {
            media: oe24_jwplayer_setup_media,
            url: oe24_jwplayer_setup_url,
            type: oe24_jwplayer_setup_type, // for webpages use „type“ = WEB
            device: oe24_jwplayer_setup_device, // use either TABLET or SMARTPHONE or UNKNOWN
            ai: "[AdvertisingId/IDFA]" // providing this value is mandatory

        };
    } else {
        var gfkS2sConf = {
            media: oe24_jwplayer_setup_media,
            url: oe24_jwplayer_setup_url,
            type: oe24_jwplayer_setup_type // for webpages use „type“ = WEB
        };

    }

    console.log('gfkS2sConf',gfkS2sConf);

    var oe24jwplayerAdTime = undefined;
    var player, tcString, tab;

    


    
        
        function youtubeJsGfk(el) {
            console.log('youtubeJsGfk');
            console.log(el);
            this.$el = $(el);
            console.log(this.$el);
            // this.$relatedWrapper = this.$el.nextAll('.videoPlayerRelatedWrapper');
            // this.$replayBtn = this.$relatedWrapper.find('.videoPlayerReplay');
            // this.$relatedItems = this.$relatedWrapper.find('.videoPlayerRelatedItems');
            // this.countRelatedItems = this.$relatedItems.find('.videoPlayerRelatedItem').length;

            // this.ga = undefined;
            // this.trackingName = undefined;

            this.playerId = this.$el.attr('id');
            console.log('jwplayerId',this.playerId)
            this.videoId = (this.playerId == 'mobileTeaserOe24TvCustom') ? '251215975' : this.playerId.split('_')[1];

            // AGTT Teletest Tracking START
            this.adTime = undefined;
            this.adDuration = undefined;

            this.gfkInitAd = false;
            this.gfkAdPosition = '';
            this.gfkInitVideo = false;
            this.oe24PreDone = false;

            this.oe24LiveStreamPaused = 0;
            this.oe24LiveStreamPausedSum = 0;

            // helper to remind the current playing-state
            this.oe24Playing = false;
            // AGTT Teletest Tracking END

            // helper for naming
            this.gfkAdPosition = '';
            this.oe24LastPlayedId = '';

            var defaults = {
                // primary: 'flash', // zum austesten, ob flash funktioniert.
                flashplayer: '/8.17.1/jwplayer.flash.swf', // wird ueber die page-datei _shared/page/jwplayer/jwplayer.page aufgeloest
                // key: 'QcCdgx3inM94dJ9izldPrT3TuCMlZ+e+QhYdRg==',
                key: '2FsrTep9OcXBJctufEe413UqWJsrr4d5rUgyi06J8Ki97VJ/',
                displaytitle: false,
                displaydescription: false,
                hlshtml: true,
                androidhls: true,
                aspectratio: '16:9',
                width: '100%',
                stretching: 'uniform',
                preload: 'auto',
                ga: {}
            };
            var defaultsEvent = {
                ready: true,
                error: true,
                adPlay: true,
                adRequest: true,
                play: true,
                firstFrame: true,
                beforeComplete: true,
                complete: true
            };

            // (ws) 2017-10-17 DAILY-897
            // Im Falle eines Video-Fehlers soll nur einmal ein "custom" Element mit der Fehlermeldung erzeugt werden
            this.customMessageBoxDone = false;
            // (ws) 2017-10-17 DAILY-897 end

            var elOpts = this.$el.data('video-setup');
            if (typeof elOpts == 'undefined') {
                // Backend Problematik
                elOpts = JSON.parse(this.$el.attr('data-video-setup'));
            }
            
            // handle cookie-consent
            // if(tcString.length){
            //     if(typeof elOpts.advertising != 'undefined'){
            //         for (var s in elOpts.advertising.schedule) {
            //             elOpts.advertising.schedule[s].tag += '&gdpr=1&gdpr_pd=1&gdpr_consent=' + tcString;
            //         }
            //     }
            // }
            
            if(typeof elOpts.advertising != 'undefined'){
                console.log(elOpts.advertising);
            }

            this.playerOptions = $.extend(defaults, elOpts);

            var elOptsEvent = this.$el.data('video-opts-event');
            if (typeof elOptsEvent == 'undefined') {
                // Backend Problematik
                elOptsEvent = JSON.parse(this.$el.attr('data-video-opts-event'));
            }
            this.playerOptionsEvent = $.extend(defaultsEvent, elOptsEvent);

            this.elAgttData = this.$el.data('video-data');
            if (typeof elAgttData == 'undefined') {
                // Backend Problematik
                this.elAgttData = JSON.parse(this.$el.attr('data-video-data'));
            }

            // additional elAgttData
            this.elAgttData.channel = 'oe24';
            this.elAgttData.deviceid = 'web';
            this.elAgttData.deviceid = (oe24_jwplayer_setup_type == 'APP') ? oe24_jwplayer_app_device : this.elAgttData.deviceid;
            this.elAgttData.videopartid = '1_1';

            this.elAgttData.playerid = (isMobileDevice()) ? 'oe24.mobile.agtt' : 'oe24.video.agtt';
            this.elAgttData.playerid = (oe24_jwplayer_setup_type == 'APP') ? 'oe24.app.agtt' : this.elAgttData.playerid;

            this.elAgttData.airdate = getOe24IsoDate(this.elAgttData.airdate);
            this.elAgttData.clipreleasetime = getOe24IsoDate(this.elAgttData.clipreleasetime);

            console.log('elAgttData',this.elAgttData);

            
            this.handleVisibility();
            var rc = this.initVideo();
            console.log('after init');
            
            if (false === rc) {
                return false;
            }

            // if (typeof this.playlistObject !== 'undefined') {
            //     this.initPlaylists();
            // }

            this.initGfkJsTracking();
            
            // this.initGoogleAnalytics();
            // this.oe24TrackingEvent();
            
            // jwPlayerObject = this;

            return;
        }

        
        youtubeJsGfk.prototype.initGfkJsTracking = function() {

            (function(w, d, c, s, id, v) {
                if (d.getElementById(id)) {
                    return;
                }
    
                w[id] = {};
                w[id].agents = [];
                var api = ["playLive", "playVOD", "stop", "skip", "screen", "volume", "impression"];
                w.s = (function() {
                    function s(c, pId, cb) {
                        var sA = { queue: [], config: c, cb: cb, pId: pId };
                        api.forEach(function(e) {
                            sA[e] = function() {
                                sA.p = cb();
                                sA.queue.push({ f: e, a: arguments })
                            };
                        });
                        return sA;
                    }
                    return s;
                }());
    
                w[id].getAgent = function(cb, pId) {
                    var a = {
                        a: new w.s(c, pId || "", cb || function() {
                            return 0;
                        })
                    };
                    api.forEach(function(e) {
                        a[e] = function() {
                            return this.a[e].apply(this.a, arguments);
                        }
                    });
                    w[id].agents.push(a);
                    return a;
                };
    
                var lJS = function(eId, url) {
                    var tag = d.createElement(s);
                    var el = d.getElementsByTagName(s)[0];
                    tag.id = eId;
                    tag.async = true;
                    tag.type = 'text/javascript';
                    tag.src = url;
                    el.parentNode.insertBefore(tag, el);
                };
    
                lJS(id, c.url);
    
            })(window, document, gfkS2sConf, 'script', 'gfkS2s');
    
    
            var player = this.player;
            // VOD: Callback method must return the current video position in milliseconds.
            function videoPositionCallback() {
    
                if (oe24jwplayerAdTime != undefined && oe24jwplayerAdTime > 0) {
                    var position = oe24jwplayerAdTime;
                } else {
                    // var position = Math.round(player.getCurrentTime() * 1000); //must return milliseconds!
                    var position = Math.round(0); //must return milliseconds!
                }
    
                return position;
            }
            // playerId is the id of the <video> element
            var playerId = this.playerId;
            console.log('videoPositionCallback',videoPositionCallback());
            this.gfkAgent = gfkS2s.getAgent(videoPositionCallback, playerId);
    
        }

        
        function isMobileDevice() {
            // www.detectmobilebrowsers.com
            // Regex updated: 1 August 2014
            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;
            }
            return false;
        }

        function getOe24IsoDate(date2change) {
            if (date2change == null) return date2change;

            if (date2change.length < 16) {
                return date2change;
            }

            var day = date2change.substring(0, 2);
            var month = parseInt(date2change.substring(3, 5)) - 1;
            var year = date2change.substring(6, 10);
            var hour = date2change.substring(11, 13);
            var minute = date2change.substring(14, 16);

            var d = new Date(year, month, day, hour, minute, 0, 0);
            var nd = d.toISOString();

            return nd.toString();
        }

        
        // If the page is hidden, pause the video;
        // if the page is shown, play the video
        function handleVisibilityChange() {
            if (document[hidden]) {
                tab = 0;
            } else {
                tab = 1;
            }
        }

        youtubeJsGfk.prototype.handleVisibility = function() {
        
            console.log('handleVisibility');
            if(typeof window.document.visibilityState !== 'undefined'){
                if(window.document.visibilityState == 'visible'){
                    tab = 1;
                }
                else {
                    tab = 0;
                }
                return;
            }

            if(typeof window.document.hasFocus !== "undefined"){
                if (window.document.hasFocus()){
                    tab = 1;
                }
                else {
                    tab = 0;
                }

                return;
            }

            if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
                hidden = "hidden";
                visibilityChange = "visibilitychange";
            } else if (typeof document.msHidden !== "undefined") {
                hidden = "msHidden";
                visibilityChange = "msvisibilitychange";
            } else if (typeof document.webkitHidden !== "undefined") {
                hidden = "webkitHidden";
                visibilityChange = "webkitvisibilitychange";
            }

            // Warn if the browser doesn't support addEventListener or the Page Visibility API
            if (typeof document.addEventListener === "undefined" || hidden === undefined) { tab = 1; } else {
                // Handle page visibility change
                document.addEventListener(visibilityChange, handleVisibilityChange, false);
                handleVisibilityChange();
            }
        }

        
        youtubeJsGfk.prototype.initVideo = function() {
            
            var self = this;
            // AGTT Teletest Tracking START
            function gfkSetIsPlaying(isPlaying, playerPosition) {
                console.log('gfkSetIsPlaying',isPlaying,playerPosition);
                
                var state = self.oe24Playing;

                var contentId = 'default';


                // var videoId = (self.playerOptions.playlist[0].title) ? self.playerOptions.playlist[0].title : self.videoId;
                // var originalVideoId = videoId;

                // // advertisments must have another videoId
                // var videoId = (self.gfkInitAd) ? videoId + '_Ad_' + self.gfkAdPosition : videoId;


                // video-id - should be an unique-id, can be the same as episode-id (according to gfk), but should be another one, when in an advertisement
                var videoId = (self.videoId) ? self.videoId : self.elAgttData.episodeid;

                // advertisments must have another videoId
                var videoId = (self.gfkInitAd) ? videoId + '_Ad_' + self.gfkAdPosition : videoId;
                var videoId = String(videoId);
                var originalVideoId = videoId;


                var volume = self.player.getVolume().toString();
                console.log('fullscreen');
                console.log(self.player);
                // console.log('fullscreen',self.player.isFullscreen());
                // var fullscreen = (self.player.isFullscreen()) ? '1' : '0';
                var fullscreen = '0';
                

                var cliptype = self.elAgttData.cliptype; // "[ContentId]"
                // cliptype = (self.gfkInitAd && playerPosition<=0) ? 'preroll' : cliptype;
                // cliptype = (self.gfkInitAd && playerPosition>0) ? 'midroll' : cliptype;
                cliptype = (self.gfkInitAd && self.gfkAdPosition != '') ? self.gfkAdPosition : cliptype;
                cliptype = gfkGetPosition(cliptype);

                var liveStreamPaused = 0;
                if ((self.elAgttData.cliptype.toLowerCase() == 'live' || self.elAgttData.cliptype.toLowerCase() == 'auto_live' || self.elAgttData.cliptype.toLowerCase() == 'audio_live') && !self.gfkInitAd) {
                    var now = new Date().getTime();
                    liveStreamPaused = (self.oe24LiveStreamPaused != 0) ? (now - self.oe24LiveStreamPaused) : 0;
                    liveStreamPaused += self.oe24LiveStreamPausedSum;
                    self.oe24LiveStreamPaused = 0;
                    // remember cumulative sum of paused-time during livestream if users pauses again during the stream
                    self.oe24LiveStreamPausedSum = liveStreamPaused;
                }

                var videoduration = (self.gfkInitAd && self.adDuration) ? self.adDuration : self.elAgttData.videoduration;

                var customobject = {
                    "cliptype": cliptype,
                    "videotitle": self.elAgttData.videotitle,
                    "episodeid": self.elAgttData.episodeid,
                    "videopartid": self.elAgttData.videopartid,
                    "airdate": self.elAgttData.airdate,
                    "playerid": self.elAgttData.playerid,
                    "channel": self.elAgttData.channel,
                    "deviceid": self.elAgttData.deviceid,
                    "playerduration": videoduration,
                    "videoduration": videoduration,
                    "episodeduration": videoduration,
                    "programname": self.elAgttData.programname,
                    "clipreleasetime": self.elAgttData.clipreleasetime,
                    "videoid": originalVideoId
                };
                console.log('customobject',customobject);

                if (isPlaying) {
                    // set state only if its currently not 'playing'
                    if (!state) {
                        if ((self.elAgttData.cliptype == 'Live' || self.elAgttData.cliptype == 'Auto_live' || self.elAgttData.cliptype.toLowerCase() == 'audio_live') && self.gfkAdPosition.length <= 0) {
                            // Livestream
                            console.log('gfkAgent.playLive');
                            self.gfkAgent.playLive(contentId, '', liveStreamPaused, videoId, fullscreen, volume, customobject);
                        } else {
                            // Video on Demand
                            console.log('gfkAgent.playVOD');
                            self.gfkAgent.playVOD(contentId, videoId, fullscreen, volume, customobject);
                        }
                        self.oe24Playing = true;

                        // self.gfkAgent.play(contentId, liveStreamPaused, videoId, fullscreen, volume, customobject);
                        // self.oe24Playing = true;
                    }
                } else {
                    // set state only if its currently not 'paused'
                    if (state) {
                        console.log('gfkAgent.stop');
                        self.gfkAgent.stop();
                        self.oe24Playing = false;
                        self.oe24LiveStreamPaused = new Date().getTime();
                    }
                }
            }

            function gfkGetPosition(adPosition) {
                if(typeof adPosition == 'undefined'){
                    return 'Preroll';
                }
                var returnAdPosition = (adPosition.toLowerCase() == 'pre') ? 'Preroll' : adPosition;
                returnAdPosition = (adPosition.toLowerCase() == 'mid') ? 'Midroll' : returnAdPosition;
                returnAdPosition = (adPosition.toLowerCase() == 'post') ? 'Postroll' : returnAdPosition;
    
                return returnAdPosition;
            }

            function gfkPlayEvent(event) {
                
                console.log('playEvent',event);
                if (self.gfkInitVideo === false) {
                    console.log('gfkInitVideo',self.gfkInitVideo);
                    return;
                }
                self.adTime = 0;
                oe24jwplayerAdTime = 0;
                console.log('player',self.player);
                var playerPos = Math.round(self.player.getCurrentTime() * 1000);
                console.log('playerPos',playerPos);
                gfkSetIsPlaying(true, playerPos);
            }            
            function gfkPauseEvent(event) {
                console.log('pauseEvent',event);
                var playerPos = Math.round(self.player.getCurrentTime() * 1000);
                gfkSetIsPlaying(false, playerPos);
            }
            function gfkStopEvent(event) {
                console.log('stopEvent',event);
                var playerPos = Math.round(self.player.getCurrentTime() * 1000);
                gfkSetIsPlaying(false, playerPos);
            }
            function gfkEndedEvent(event) {
                console.log('endedEvent',event);
                var playerPos = Math.round(self.player.getCurrentTime() * 1000);
                gfkSetIsPlaying(false, playerPos);
                self.gfkInitVideo = false;
            }
            function gfkVolumeChangeEvent(event) {
                console.log('volumeChangeEvent',event);
                // var volume = self.player.getVolume();
                // self.gfkAgent.volume(volume.toString());
            }

            function gfkAdStarted(event) {
                console.log('gfkAdStarted',event);
                // self.adDuration = Math.round(event.l.g.duration);
                // console.log('duration',self.adDuration);

                // if (self.gfkInitAd === true) {
                //     return;
                // }

                // self.adTime = 0;
                // // var adPosition = event.adposition;
                // // adPosition = ('mid' === adPosition && 'nonlinear' === event.linear) ? 'overlay' : adPosition;
                // // self.gfkAdPosition = gfkGetPosition(adPosition);
                // var offset = event.l.g.adPodInfo.timeOffset;
                // console.log('offset',offset);
                // var adPosition = 'pre';
                // adPosition = (typeof offset !== 'undefined' && offset > 0) ? 'mid' : adPosition;
                // self.gfkAdPosition = gfkGetPosition(adPosition);

                // if (self.gfkAdPosition === 'overlay') {
                //     return;
                // }

                // self.gfkInitAd = true;

                // gfkSetIsPlaying(true, 0);
            }
            function gfkAdPaused(event) {
                console.log('gfkAdPaused',event);
                // gfkSetIsPlaying(false, self.adTime);
            }
            function gfkAdResumed(event) {
                console.log('gfkAdResumed',event);
                // oe24Tracking();

                // if (self.gfkInitAd === false) {
                //     return;
                // }
                // gfkSetIsPlaying(true, self.adTime);
            }
            
            function gfkAdCompleted(event) {
                console.log('gfkAdCompleted');
                if (self.gfkAdPosition == 'overlay') {
                    return;
                }
    
                // self.oe24PreDone = true;
    
                // gfkSetIsPlaying(false, self.adTime);
    
                // self.gfkInitAd = false;
    
                // self.adTime = undefined;
                // self.adDuration = undefined;
                // gfkSetIsPlaying(false, 0);
    
                // self.gfkAdPosition = '';
            }
            
            function gfkAdBreakReady(event) {
                console.log('gfkAdBreakReady');
            }
            function gfkAdContentPaused(event) {
                console.log('gfkAdContentPaused');
            }
            function gfkAdContentResumed(event) {
                console.log('gfkAdContentResumed');
            }
            
            



            function gfkAdError(event) {
                console.log('gfkAdError');
            }

            
            window.onbeforeunload = function() {
                gfkStopEvent();
            };
            if (typeof this.gfkAgent !== 'undefined') {
                // this.player.on('play',gfkPlayEvent);
                // this.player.on('pause',gfkPauseEvent);
                // this.player.on('stop',gfkStopEvent);
                // this.player.on('ended',gfkEndedEvent);
                // this.player.on('volumechange',gfkVolumeChangeEvent);

                // // this.player.adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, gfkAdStarted);
                // // this.player.adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, gfkAdError);

                // console.log(this.player);
                // this.player.on('adsready', function(){
                //     self.player.ima.addEventListener(
                //         google.ima.AdEvent.Type.STARTED,gfkAdStarted
                //     );
                //     self.player.ima.addEventListener(
                //         google.ima.AdErrorEvent.Type.AD_ERROR,gfkAdError
                //     );
                //     self.player.ima.addEventListener(
                //         google.ima.AdEvent.Type.PAUSED,gfkAdPaused
                //     );
                //     self.player.ima.addEventListener(
                //         google.ima.AdEvent.Type.COMPLETE,gfkAdCompleted
                //     );
                //     self.player.ima.addEventListener(
                //         google.ima.AdEvent.Type.RESUMED,gfkAdResumed
                //     );

                //     self.player.ima.addEventListener(
                //         google.ima.AdEvent.Type.AD_BREAK_READY,gfkAdBreakReady
                //     );
                //     self.player.ima.addEventListener(
                //         google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED,gfkAdContentPaused
                //     );
                //     self.player.ima.addEventListener(
                //         google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED,gfkAdContentResumed
                //     );
                    
                    
                    
                // });


                
            }
            
            console.log('initVideo');
            if (typeof this.playerId === 'undefined') {
                return false;
            }
            // flappe
            var flap = ($(this.$el).hasClass('flap')) ? true : false;
            console.log('flap',flap);
            // autostart only if in active browser
            if (!tab) {
                this.playerOptions.autostart = false;
            }

            if (oe24_jwplayer_app_device == 'Android_oe24'){
                this.playerOptions.autostart = false;
            }

            var playerSetup = $(this.$el).attr("data-video-setup");
            playerSetup = JSON.parse(playerSetup);
            if(typeof playerSetup.youtubeId === 'undefined'){
                return;
            }

            // var adOptions = {
            //     adTagUrl: 'https://pubads.g.doubleclick.net/gampad/ads?iu=/1011024/oe24.at-Test/Video/Video-Test1&description_url=http%3A%2F%2Fadverserve.net&tfcd=0&npa=0&sz=640x360&cust_params=adpageName%3Dtestpage%26adpageShow%3DTestshow%26adpageType%3D1&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator=&ad_rule=1&vid_d=20000&allcues=7000,14000&gdpr=1&gdpr_consent='+tcString
            // };
            
            console.log('onYouTubeIframeAPIReady 2');
            this.player = new YT.Player(this.playerId, {
                height: '100%',
                width: '100%',
                videoId: playerSetup.youtubeId,
                playerVars: { 'autoplay': 1, 'controls': 1, 'mute': 1, 'playsinline': 1 },
                events: {
                    'onReady': onPlayerReady,
                    'onStateChange': onPlayerStateChange
                }
            });
            player=this.player;

            // 4. The API will call this function when the video player is ready.
            function onPlayerReady(event) {
                console.log('onPlayerReady');
                event.target.mute();
                event.target.playVideo();
            }

            // 5. The API calls this function when the player's state changes.
            //    The function indicates that when playing a video (state=1),
            //    the player should play for six seconds and then stop.
            // var done = false;
            function onPlayerStateChange(event) {
                console.log('onPlayerStateChange',event.data);
                if (event.data == YT.PlayerState.PLAYING) {
                    gfkPlayEvent(event);                    
                }
                if (event.data == YT.PlayerState.PAUSED) {
                    gfkPauseEvent(event);
                }

                if (event.data == YT.PlayerState.ENDED) {
                    gfkEndedEvent(event);
                }
            }
            

            if(flap){
                console.log('start handleflap');
                handleFlap(this.player);
            }

            this.gfkInitVideo = true;

            return true;
                
        }

        // Video in Flappe
        function stopFlapVideo(player){
            player.pause();
        }
        function playFlapVideo(player){
            player.play();
        }

        function handleFlap(player){
            var flap = document.querySelector('.oe24tvTopVideoLayer');
            
            if (flap != null) {
                
                var startMin = $('.oe24tvTopVideoLayer').hasClass('startMin') ? true : false;
                var startInitTime = (startMin) ? 2500 : 100;
                setTimeout(function() {
                    // bottom video-layer
                    if ($(".oe24tvTopVideoLayer").length) {
                        
                        // close layer
                        $('.oe24tvTopVideoLayer .videoLayerClose').click(function(e) {
                            $('.oe24tvTopVideoLayer').removeClass('tvLayerStart').addClass('tvLayerEnd');
                            stopFlapVideo(player);
                        });
                        // open layer
                        $('.oe24tvTopVideoLayer .videoLayerUp').click(function(e) {
                            $('.oe24tvTopVideoLayer').removeClass('tvLayerEnd').addClass('tvLayerStart');
                            playFlapVideo(player);
                        });

                        if(startMin){
                            $('.oe24tvTopVideoLayer').removeClass('tvLayerStart').addClass('tvLayerEnd');
                        }
                        else {
                            $('.oe24tvTopVideoLayer').removeClass('tvLayerEnd').addClass('tvLayerStart');
                        }
                    }

                }, startInitTime);

            }
        }

        var __instances = {};
        $.fn.youtubeJsPlayer = function() {
            const selInstances = [];
            this.each(function() {
                const $this = $(this);
                var id = $this.attr('id');
                if (!__instances[id]) {
                    __instances[id] = new youtubeJsGfk(this);
                }
                selInstances.push(__instances[id]);
            });
            return selInstances.length === 1 ? selInstances[0] : selInstances;
        }

})(jQuery);

function onYouTubeIframeAPIReady() {
    console.log('onYouTubeIframeAPIReady');
    $('.oe24youtubeplayer').youtubeJsPlayer();
}

console.log('in youtube.js');
window.addEventListener("tcfConsentLoaded", function (e) {
    console.log('in youtube tcfConsentLoaded',e);
    tcString = e.tcString;   

    // This code loads the IFrame Player API code asynchronously.
    var tag = document.createElement('script');

    tag.src = "https://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
    
});

;$(document).ready(function () {
    function oewaCall(e) {
        try {

            iom.c(oewa_data,1);

        } catch (e) {
            console && console.info && console.info(e);
        }
    }

    $('.js-oewaLink').on('click', function(e) {
        oewaCall(e);
    });

    $('.js-oewaLink').on('touchstart', function(e) {
        oewaCall(e);
    });

    $('.js-oewaContainer').on('click', '.js-oewaDynLink', function(e) {
        oewaCall(e);
    });

});
var nst={NSTBaseAPI:function(t,e,i){this.inputTextfield=i,0!==e&&1!==e&&2!==e&&3!==e&&4!==e&&(e=4),this.logger=new nst.Logger(e,this.inputTextfield),this.isBoolean(t)?this.local=t:this.local=!0,this.logger.info("INSTANCE CREATED NSTBaseAPI VER: "+nst.NSTBaseAPI.API_VERSION),this.logger.info("Tracking mode local:.\n: "+t),this.logger.info("Logger created.\nloglevel: "+nst.Logger.LEVEL_LIST[e]),this.tPreHeartbeat=new nst.Timer(nst.NSTBaseAPI.HEARTBEAT_PRE_INTERVAL,this.tickPreHeartbeat,this),this.tHeartbeat=new nst.Timer(nst.NSTBaseAPI.HEARTBEAT_INTERVAL,this.tickHeartbeat,this),this.tDuration=new nst.Timer(nst.NSTBaseAPI.DURATION_INTERVAL,this.tickDuration,this),this.urlFactory=new nst.UrlFactory(nst.NSTBaseAPI.HTTP_SERVICE_BASE_URL,nst.NSTBaseAPI.HTTP_SERVICE_ENDPOINT),this.logger.info(this.urlFactory.getUrl())}};nst.NSTBaseAPI.API_VERSION="1.9.19",nst.NSTBaseAPI.FLASH_API_GET_POS_METHOD_NAME="getVideoPos",nst.NSTBaseAPI.FLASH_API_ON_INIT_SUCCESS_METHOD_NAME="onInitSuccess",nst.NSTBaseAPI.FLASH_API_ON_INIT_ERROR_METHOD_NAME="onInitError",nst.NSTBaseAPI.HEARTBEAT_INTERVAL=2e4,nst.NSTBaseAPI.HEARTBEAT_PRE_INTERVAL=1e4,nst.NSTBaseAPI.USE_HEARTBEAT_PRE_INTERVAL=!1,nst.NSTBaseAPI.DURATION_INTERVAL=100,nst.NSTBaseAPI.PLAYBACK_SUB_EVENT_ID_PLAY="play",nst.NSTBaseAPI.PLAYBACK_SUB_EVENT_ID_STOP="stop",nst.NSTBaseAPI.PLAYBACK_SUB_EVENT_ID_MUTE="mute",nst.NSTBaseAPI.PLAYBACK_SUB_EVENT_ID_FULLSCREEN="fullscreen",nst.NSTBaseAPI.PLAYBACK_SUB_EVENT_ID_VISIBLE="visible",nst.NSTBaseAPI.PLAYBACK_SUB_EVENT_ID_HEARTBEAT="heartbeat",nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR="\n",nst.NSTBaseAPI.EVENT_TYPE_START="start",nst.NSTBaseAPI.EVENT_TYPE_PLAYBACK="playback",nst.NSTBaseAPI.EVENT_TYPE_CLICK="click",nst.NSTBaseAPI.EVENT_TYPE_CUSTOM="custom",nst.NSTBaseAPI.HTTP_SERVICE_BASE_URL="https://log.streamagent.sensic.net/",nst.NSTBaseAPI.HTTP_SERVICE_ENDPOINT="SCT-NST-Server/NST_DB_Logger",nst.NSTBaseAPI.CHECK_PLAYER_INTERVAL=400,nst.NSTBaseAPI.CHECK_VISIBILITY_TRY_COUNT=15,nst.NSTBaseAPI.CHECK_VISIBILITY_TIMEOUT=200,nst.NSTBaseAPI.prototype.initDataSet=!1,nst.NSTBaseAPI.prototype.preHeartbeatDone=!1,nst.NSTBaseAPI.prototype.inputTextfield=!1,nst.NSTBaseAPI.prototype.isTrackerInit=!1,nst.NSTBaseAPI.prototype.duration=0,nst.NSTBaseAPI.prototype.lPos=0,nst.NSTBaseAPI.prototype.videoPos=0,nst.NSTBaseAPI.prototype.isPlaying=!1,nst.NSTBaseAPI.prototype.mute=0,nst.NSTBaseAPI.prototype.fullscreen=0,nst.NSTBaseAPI.prototype.countTrackingEvent=0,nst.NSTBaseAPI.prototype.visibility=0,nst.NSTBaseAPI.prototype.visibilityRunningConfirmed=!1,nst.NSTBaseAPI.prototype.htmlPlayerId="",nst.NSTBaseAPI.prototype.getVisibility=function(){return this.visibility},nst.NSTBaseAPI.prototype.setVisibility=function(t){this.visibility=t,this.visibilityRunningConfirmed=!0},nst.NSTBaseAPI.prototype.NSTMeetricsVisibility=function(t,e,i,s){var a=(new Date).getDate()/1e3,n=i.createElement("script");n.type="text/javascript",n.src="https://s407.mxcdn.net/bb-mx/serve/mtrcs_943913.js#pjid=943913&place="+e+"&cb="+a+"&method=nodeId&node="+t+"&visreport="+s,n.async=!0,i.head.appendChild(n)},nst.NSTBaseAPI.prototype.initJS=function(t,e,i,s,a,n){n=void 0===n||n,this.logger.warn("playheadCheckerEnabled "+n),t!==this.playerId?(this.onInitErrorCallback=a,this.onInitSuccessCallback=s,void 0!==i?(this.getPosJSCallback=i,this.getPos=this.getPosJS,n&&(this.playheadChecker=new nst.NSTPlayheadChecker(this,this.playheadCheckerOnPlay,this.playheadCheckerOnStop,this.playheadCheckerOnSeekFW,this.playheadCheckerOnSeekBW),this.playheadCheckerTimer=new nst.Timer(nst.NSTBaseAPI.CHECK_PLAYER_INTERVAL,this.checkPlayerStatus,this)),void 0!==s?(this.htmlPlayerId=e,this.apiType="pureJS",this.baseInit(t)):this.onInitError("onInitSuccess is undefined. please define a onInitSuccess function when you call the 'initJS' method (third parameter).")):this.onInitError("getPos is undefined. please define a getPos function when you call the 'initJS' method (second parameter).")):this.logger.warn("player with the id: "+t+"is already initialized.\ncall will be ignored.")},nst.NSTBaseAPI.prototype.release=function(){this.playheadCheckerTimer&&this.playheadCheckerTimer.stop(),this.isPlaying&&this.setIsPlaying(!1,this.getPos())},nst.NSTBaseAPI.prototype.initFlash=function(t,e){t!==this.playerId?void 0!==e?(this.swfObjectTagId=e,this.getPos=this.getPosFlash,this.apiType="jsWithFlash",this.baseInit(t)):this.onInitError("swfObjectTagId is undefined. please define a swfObjectTagId when you call the 'initFlash' method (second parameter)"):this.logger.warn("player with the id: "+t+"is already initialized.\ncall will be ignored.")},nst.NSTBaseAPI.prototype.baseInit=function(t){void 0!==t?(this.playerId=t,this.checkServiceAvailable=function(){switch(this.local){case!0:return!0;case!1:if(this.webService=new nst.WebService,this.webService.checkAvailability())return!0;this.logger.error("could not determine web service status.")}},this.getClientId=function(){switch(this.local){case!0:return"localClient";case!1:this.cookieName="cid",this.cookieValue="",this.nameEQ=this.cookieName+"=";for(var t=document.cookie.split(";"),e=0;e<t.length;e++){for(var i=t[e];" "===i.charAt(0);)i=i.substring(1,i.length);0===i.indexOf(this.nameEQ)&&(this.cookieValue=i.substring(this.nameEQ.length,i.length))}return this.cookieValue}},this.checkServiceAvailable()?(this.clientId=this.getClientId(),void 0!==this.clientId&&"undefined"!==this.clientId&&"null"!==this.clientId||this.logger.error("no clientId could be requested. tracking will not work in the live mode (local = false)."),this.onInitSuccess()):this.logger.error("no http service available. tracking will not work in the live mode (local = false).")):this.onInitError("playerId is undefined. please define when you call any init method (first parameter).")},nst.NSTBaseAPI.prototype.onInitSuccess=function(){this.isTrackerInit=!0,void 0!==this.onInitSuccessCallback&&this.onInitSuccessCallback(),this.swfObjectTagId&&this.getSWF()[nst.NSTBaseAPI.FLASH_API_ON_INIT_SUCCESS_METHOD_NAME](),this.logger.info("INITIALIZING TRACKER SUCCEEDED\nplayerId: "+this.playerId)},nst.NSTBaseAPI.prototype.onInitError=function(t){this.logger.error("onInitError: "+t),void 0!==this.onInitErrorCallback&&this.onInitErrorCallback(t),this.swfObjectTagId&&this.getSWF()[nst.NSTBaseAPI.FLASH_API_ON_INIT_ERROR_METHOD_NAME]()},nst.NSTBaseAPI.prototype.getSWF=function(){return-1!==navigator.appName.indexOf("Microsoft")?window[this.swfObjectTagId]:document[this.swfObjectTagId]},nst.NSTBaseAPI.prototype.init=function(t,e){this.visibilityRunningConfirmed=!1,this.isPlaying&&this.setIsPlaying(!1,this.getPos()),this.playheadChecker&&this.playheadChecker.reset(),this.initDataSet=!0,this.preHeartbeatDone=!1,this.checkIfTrackerInit(),this.isVideoInit=!0,this.playbackId=(new Date).getTime()+"-"+Math.floor(1e4*Math.random()),this.videoId=t,this.groupId=e.groupid,this.videoCategory=e.videocategory,this.clipURL=e.clipurl,this.clipType=e.cliptype,this.videoTitle=e.videotitle,this.clipReleaseTime=e.clipreleasetime,this.videoDuration=e.videoduration,this.clipQuality=e.clipquality,delete e.groupid,delete e.videocategory,delete e.clipurl,delete e.cliptype,delete e.videotitle,delete e.clipreleasetime,delete e.videoduration,delete e.clipquality,this.extendedData=e,this.playheadCheckerTimer&&this.playheadCheckerTimer.start();var i=(this.htmlPlayerId+this.playerId).replace(/[\W]+/gi,""),s=this;"function"!=typeof window[i]&&(window[i]=function(t){s.setVisibility(t)}),setTimeout(function(){s.NSTMeetricsVisibility(s.htmlPlayerId,s.playerId,window.document,i)},0)},nst.NSTBaseAPI.prototype.custom=function(t,e){this.checkIfTrackerInit(),this.isVideoInit||this.logger.warn("before invoking tracking method 'click', you have to invoke the init method for initializing the video."),this.customProxy(this.playerId,this.clientId,this.playbackId,t,e)},nst.NSTBaseAPI.prototype.playback=function(t){var e;e=t===nst.NSTBaseAPI.PLAYBACK_SUB_EVENT_ID_HEARTBEAT||t===nst.NSTBaseAPI.PLAYBACK_SUB_EVENT_ID_MUTE||t===nst.NSTBaseAPI.PLAYBACK_SUB_EVENT_ID_FULLSCREEN||t===nst.NSTBaseAPI.PLAYBACK_SUB_EVENT_ID_VISIBLE?this.getPos():this.videoPos,this.checkIfTrackerInit(),this.isVideoInit||this.logger.warn("before invoking tracking method 'playback', you have to invoke the init method for initializing the video.");var i=this,s=nst.NSTBaseAPI.CHECK_VISIBILITY_TRY_COUNT,a=function(){if(!i.visibilityRunningConfirmed&&0==i.getVisibility()&&s>0)s--,setTimeout(a,nst.NSTBaseAPI.CHECK_VISIBILITY_TIMEOUT);else{var n=1===i.fullscreen?100:i.getVisibility();i.playbackProxy(i.playerId,i.clientId,i.playbackId,e,i.duration,n,i.fullscreen,i.mute,t)}};a()},nst.NSTBaseAPI.prototype.setIsPlaying=function(t,e){switch(this.videoPos=e,this.checkIfTrackerInit(),this.isVideoInit||this.logger.warn("before invoking tracking method 'setIsPlaying', you have to invoke the init method for initializing the video."),this.isPlaying=t,this.tDuration.stop(),this.tHeartbeat.stop(),this.tPreHeartbeat.stop(),this.isPlaying){case!0:this.duration=0,this.lPos=0,this.initDataSet&&(this.initProxy(this.playerId,this.clientId,this.playbackId,this.videoId,this.groupId,this.videoCategory,this.clipURL,this.clipType,this.videoTitle,this.clipReleaseTime,this.videoDuration,this.clipQuality,this.extendedData),this.initDataSet=!1),this.playback(nst.NSTBaseAPI.PLAYBACK_SUB_EVENT_ID_PLAY),this.tDuration.start(),!this.preHeartbeatDone&&nst.NSTBaseAPI.USE_HEARTBEAT_PRE_INTERVAL?this.tPreHeartbeat.start():this.tHeartbeat.start();break;case!1:this.playback(nst.NSTBaseAPI.PLAYBACK_SUB_EVENT_ID_STOP),this.duration=0,this.lPos=0}},nst.NSTBaseAPI.prototype.setMute=function(t){this.checkIfTrackerInit(),this.exists(t)&&this.isIntBoolean(t)?(this.isVideoInit||this.logger.warn("before invoking tracking method 'setMute', you have to invoke the init method for initializing the video."),this.mute=t,this.playback(nst.NSTBaseAPI.PLAYBACK_SUB_EVENT_ID_MUTE)):this.logger.error("parameter value is undefined or not from type boolean")},nst.NSTBaseAPI.prototype.setFullscreen=function(t){this.checkIfTrackerInit(),this.exists(t)&&this.isIntBoolean(t)?(this.isVideoInit||this.logger.warn("before invoking tracking method 'setFullscreen', you have to invoke the init method for initializing the video."),this.fullscreen=t,this.playback(nst.NSTBaseAPI.PLAYBACK_SUB_EVENT_ID_FULLSCREEN)):this.logger.error("parameter value is undefined or not from type int boolean (1,0,-1)")},nst.NSTBaseAPI.prototype.setVisible=function(t){},nst.NSTBaseAPI.prototype.getPosJS=function(){return this.getPosJSCallback()},nst.NSTBaseAPI.prototype.getPosFlash=function(){return this.getSWF()[nst.NSTBaseAPI.FLASH_API_GET_POS_METHOD_NAME]()},nst.NSTBaseAPI.prototype.tickPreHeartbeat=function(t){t.preHeartbeatDone=!0,t.tPreHeartbeat.stop(),t.tHeartbeat.stop(),t.tHeartbeat.start(),t.playback(nst.NSTBaseAPI.PLAYBACK_SUB_EVENT_ID_HEARTBEAT)},nst.NSTBaseAPI.prototype.tickHeartbeat=function(t){t.playback(nst.NSTBaseAPI.PLAYBACK_SUB_EVENT_ID_HEARTBEAT)},nst.NSTBaseAPI.prototype.tickDuration=function(t){_date=new Date;var e=60*_date.getMinutes()*1e3+1e3*_date.getSeconds()+_date.getMilliseconds();t.lPos>0?t.duration+=e-t.lPos:t.duration=0,t.lPos=e},nst.NSTBaseAPI.prototype.initProxy=function(t,e,i,s,a,n,r,o,h,l,T,c,A){if(this.countTrackingEvent=1,this.exists(t)&&this.exists(e)&&this.exists(i)){void 0===s&&this.logger.warn("videoId is undefined, but should be set.");var p="TRACK INIT"+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR;p+="BASE DATA"+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"playerid: "+t+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"clientid: "+e+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"playbackid: "+i+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"videoid: "+s+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"groupid: "+a+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"videocategory: "+n+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"clipURL: "+r+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"clipType: "+o+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"videoTitle: "+h+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"clipReleaseTime: "+l+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"videoDuration: "+T+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"clipquality: "+c+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"ADDITIONAL DATA"+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR;for(var S in A)"videoDuration"!==S&&(p+=S+": "+A[S]+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR);if(this.logger.info(p),!this.local){this.parameters=new Array,this.parameters.e=nst.NSTBaseAPI.EVENT_TYPE_START,this.parameters.playerid=t,""!==e&&void 0!==e&&(this.parameters.clientid=e),this.parameters.playbackid=i,this.parameters.videoid=s,this.parameters.groupid=a,this.parameters.videocategory=n,this.parameters.clipurl=r,this.parameters.cliptype=o,this.parameters.videotitle=h,this.parameters.clipreleasetime=void 0===l?"":l,void 0===T&&(T=-1),this.parameters.videoduration=T,this.parameters.clipquality=void 0===c?"":c,this.parameters.v=nst.NSTBaseAPI.API_VERSION,this.clipreferer=escape(window.location.href.toString()),this.parameters.clipreferer=this.clipreferer,this.parameters.apitype=this.apiType,this.parameters.counttrackingevent=this.countTrackingEvent,this.parameters.timestamp=(new Date).getTime();for(var I in A)this.parameters[I]=void 0===A[I]?"":A[I];this.webService.sendSync(this.parameters)}}else this.logger.error("no init track could be perform. there are one or more errors in the permitted values.")},nst.NSTBaseAPI.prototype.playbackProxy=function(t,e,i,s,a,n,r,o,h){this.exists(t)&&this.exists(e)&&this.exists(i)?(this.countTrackingEvent++,this.logger.info("TRACK PLAYBACK\nplayerId: "+t+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"clientId: "+e+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"playbackId: "+i+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"pos: "+s+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"dur: "+a+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"visible: "+n+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"fullscreen: "+r+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"mute: "+o+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"subEventId: "+h+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR),this.local||(this.parameters=new Array,this.parameters.e=nst.NSTBaseAPI.EVENT_TYPE_PLAYBACK,this.parameters.playerid=t,""!==e&&void 0!==e&&(this.parameters.clientid=e),this.parameters.playbackid=i,this.parameters.pos=s,this.parameters.dur=a,this.parameters.visible=n,this.parameters.fullscreen=r,this.parameters.mute=o,this.parameters.subeventid=h,this.parameters.v=nst.NSTBaseAPI.API_VERSION,this.parameters.clipreferer=this.clipreferer,this.parameters.counttrackingevent=this.countTrackingEvent,this.parameters.timestamp=(new Date).getTime(),this.webService.sendSync(this.parameters))):this.logger.error("no playback track could be perform. there are one or more errors in the permitted values.")},nst.NSTBaseAPI.prototype.customProxy=function(t,e,s,a,n){if(this.exists(t)&&this.exists(e)&&this.exists(s)){this.countTrackingEvent++,this.eventId&&this.logger.warn("eventId is undefined, but should be set.");var r="TRACK CUSTOM\nplayerId: "+t+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"clientId: "+e+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"playbackId: "+s+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR+"eventId: "+a+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR;for(i in n)r+=i+": "+n[i]+nst.NSTBaseAPI.LOG_TRACK_PARAMETER_SEPERATOR;if(this.logger.info(r),!this.local){this.parameters=new Array,this.parameters.e=nst.NSTBaseAPI.EVENT_TYPE_CUSTOM,this.parameters.playerId=t,""!==e&&void 0!==e&&(this.parameters.clientId=e),this.parameters.playbackId=s,this.parameters.eventId=a,this.parameters.v=nst.NSTBaseAPI.API_VERSION,this.parameters.clipreferer=this.clipreferer,this.parameters.countTrackingEvent=this.countTrackingEvent,this.parameters.timestamp=(new Date).getTime();for(k in n)this.parameters[k]=n[k];this.webService.sendSync(this.parameters)}}else this.logger.error("no custom track could be perform. there are one or more errors in the permitted values.")},nst.NSTBaseAPI.prototype.setIsPlayingManually=function(t,e){if(void 0===this.playheadChecker){if(e=void 0===e?this.getPos():e,this.isPlaying==t)return;this.setIsPlaying(t,e)}else this.logger.warn("do not use NSTBaseAPI.setIsPlayingManually() with enabled PlayheadChecker!")},nst.NSTBaseAPI.prototype.playheadCheckerOnPlay=function(t){t.isPlaying||t.setIsPlaying(!0,t.getPos())},nst.NSTBaseAPI.prototype.playheadCheckerOnStop=function(t){t.isPlaying&&t.setIsPlaying(!1,t.getPos())},nst.NSTBaseAPI.prototype.playheadCheckerOnSeekFW=function(t){t.isPlaying&&t.setIsPlaying(!1,t.playheadChecker.lt)},nst.NSTBaseAPI.prototype.playheadCheckerOnSeekBW=function(t){t.isPlaying&&t.setIsPlaying(!1,t.playheadChecker.lt)},nst.NSTBaseAPI.prototype.checkPlayerStatus=function(t){t.playheadChecker.setTime(t.getPos())},nst.NSTBaseAPI.prototype.checkIfTrackerInit=function(){this.isTrackerInit||this.logger.warn("before you use one of the tracking methods (init, click, custom, playback, setIsPlaying, setMute, setFullscreen, setVisible), you have to invoke an init method (initJS, initFlash).")},nst.NSTBaseAPI.prototype.exists=function(t){return void 0!==t||(this.logger.error("value is undefined. tracking could not be proceeded"),!1)},nst.NSTBaseAPI.prototype.isBoolean=function(t){return!0===t||!1===t||(this.logger.error("permitted type is not from type boolean. valid values are true or false."),!1)},nst.NSTBaseAPI.prototype.isIntBoolean=function(t){return 0===t||1===t||-1===t||(this.logger.error("permitted type is not from type int boolean. valid values are 1, 0 or -1"),!1)},nst.Logger=function(t,e){void 0===t&&(t=4),this.level=t,this.inputTextfield=e},nst.Logger.prototype.error=function(t){this.level>=1&&(window.console&&console.error(t),this.inputTextfield&&(this.inputTextfield.value+="ERROR: "+t+"\n---------------\n"))},nst.Logger.prototype.warn=function(t){this.level>=2&&(this.isRelease||(window.console&&console.warn(t),this.inputTextfield&&(this.inputTextfield.value+="WARN: "+t+"\n---------------\n")))},nst.Logger.prototype.info=function(t){this.level>=3&&(this.isRelease||(window.console&&console.info(t),this.inputTextfield&&(this.inputTextfield.value+="INFO: "+t+"\n---------------\n")))},nst.Logger.prototype.debug=function(t){this.level>=4&&(this.isRelease||(window.console&&console.debug(t),this.inputTextfield&&(this.inputTextfield.value+="DEBUG: "+t+"\n---------------\n")))},nst.Logger.LEVEL_LIST=["OFF","ERROR","WARN","INFO","DEBUG"],nst.Timer=function(t,e,i){this.created=!1,void 0!==t?void 0!==e?void 0!==i?(this.tickCallback=e,this.created=!0,this.thisRef=i,this.frequence=t,this.interval=void 0):alert("please pass a thisRef paramter for the timer.\n no timer could be created."):alert("please pass a tickCallback paramter for the timer.\n no timer could be created."):alert("please pass a frequence paramter for the timer.\n no timer could be created.")},nst.Timer.prototype.onTick=function(){this.tickCallback(this.thisRef)},nst.Timer.prototype.start=function(){this.stop();var t=this;this.created&&(window.clearInterval(this.interval),this.interval=window.setInterval(function(){t.onTick()},this.frequence))},nst.Timer.prototype.stop=function(){window.clearInterval(this.interval),this.interval=void 0},nst.UrlFactory=function(t,e){this.url="",this.url=t+e},nst.UrlFactory.prototype.getUrl=function(t){this.parameterString="";for(var e in t)"string"!=typeof t[e]&&"number"!=typeof t[e]&&void 0!==t[e]||(this.parameterString+=e+"="+encodeURIComponent(t[e])+"&");return"&"==this.parameterString.charAt(this.parameterString.length-1)&&(this.parameterString=this.parameterString.substring(0,this.parameterString.length-1)),this.url+"?"+this.parameterString},nst.WebService=function(){this.curImageKey=-1,this.loading=!1,this.requestBuffer=[];var t=document.getElementsByTagName("body")[0];this.img=new Image(1,1),this.img.id="nstWebserviceImg",this.img.style.height="1px",this.img.style.display="none",this.img.style.width="1px",this.img.src="",this.img.alt="nstWebserviceImg",this.img.title="nstWebserviceImg";try{t.appendChild(this.img)}catch(t){}var e=this;this.img.onload=this.img.onabort=this.img.onerror=function(){e.loading=!1,e.checkRequestBuffer()}},nst.WebService.prototype.checkAvailability=function(){return!0},nst.WebService.prototype.checkRequestBuffer=function(){if(!this.loading&&this.requestBuffer.length){this.loading=!0;var t=this.requestBuffer.shift();this.img.src=t}},nst.WebService.prototype.sendSync=function(t){this.urlFactory=new nst.UrlFactory(nst.NSTBaseAPI.HTTP_SERVICE_BASE_URL,nst.NSTBaseAPI.HTTP_SERVICE_ENDPOINT),this.requestBuffer.push(this.urlFactory.getUrl(t)),this.checkRequestBuffer()},nst.NSTPlayheadChecker=function(t,e,i,s,a){this._status="",this.onPlay=e,this.onStop=i,this.onSeekFW=s,this.onSeekBW=a,this.callbacksRef=t},nst.NSTPlayheadChecker.STAT_PLAY="play",nst.NSTPlayheadChecker.STAT_PLAY_NOT="stopOrPause",nst.NSTPlayheadChecker.STAT_SEEK_FW="seekFW",nst.NSTPlayheadChecker.STAT_SEEK_BW="seekBW",nst.NSTPlayheadChecker.WHEN_STAT_IS_SEEK_OFF_TIME=2e3,nst.NSTPlayheadChecker.MAX_LT_EQUALS=4,nst.NSTPlayheadChecker.prototype._t=0,nst.NSTPlayheadChecker.prototype.lt=0,nst.NSTPlayheadChecker.prototype.ltEqualsCount=0,nst.NSTPlayheadChecker.prototype.setTime=function(t){this._t=t,this.check(),this.lt=this._t},nst.NSTPlayheadChecker.prototype.check=function(){this.checkIfPause()&&this._status!==nst.NSTPlayheadChecker.STAT_PLAY_NOT?(void 0!==this.onStop&&this.onStop(this.callbacksRef),this._status=nst.NSTPlayheadChecker.STAT_PLAY_NOT):this.checkIfPlaying()&&this._status!==nst.NSTPlayheadChecker.STAT_PLAY?(void 0!==this.onPlay&&this.onPlay(this.callbacksRef),this._status=nst.NSTPlayheadChecker.STAT_PLAY):this.checkIfSeekFW()&&this._status!==nst.NSTPlayheadChecker.STAT_SEEK_FW?(void 0!==this.onSeekFW&&this.onSeekFW(this.callbacksRef),this._status=nst.NSTPlayheadChecker.STAT_SEEK_FW):this.checkIfSeekBW()&&this._status!==nst.NSTPlayheadChecker.STAT_SEEK_BW&&(void 0!==this.onSeekBW&&this.onSeekBW(this.callbacksRef),this._status=nst.NSTPlayheadChecker.STAT_SEEK_BW)},nst.NSTPlayheadChecker.prototype.checkIfPause=function(){return this._t===this.lt&&(this.ltEqualsCount++,this.ltEqualsCount>=nst.NSTPlayheadChecker.MAX_LT_EQUALS)},nst.NSTPlayheadChecker.prototype.checkIfPlaying=function(){return this._t!==this.lt&&this._t>this.lt&&this._t-this.lt<nst.NSTPlayheadChecker.WHEN_STAT_IS_SEEK_OFF_TIME&&(this.ltEqualsCount=0,!0)},nst.NSTPlayheadChecker.prototype.checkIfSeekFW=function(){return this._t!==this.lt&&this._t>this.lt&&this._t-this.lt>nst.NSTPlayheadChecker.WHEN_STAT_IS_SEEK_OFF_TIME&&(this.ltEqualsCount=0,!0)},nst.NSTPlayheadChecker.prototype.checkIfSeekBW=function(){return this._t!==this.lt&&this._t<this.lt&&this.lt-this._t>nst.NSTPlayheadChecker.WHEN_STAT_IS_SEEK_OFF_TIME&&(this.ltEqualsCount=0,!0)},nst.NSTPlayheadChecker.prototype.reset=function(){this._status=nst.NSTPlayheadChecker.STAT_PLAY_NOT},nst.generateGroupId=function(){return"g"+(new Date).getTime()+"-"+Math.floor(1e4*Math.random())};
