/**
 */

(function(vjs) {
  'use strict';
  var extend = function(obj) {
    var arg;
    var index;
    var key;
    for (index = 1; index < arguments.length; index++) {
      arg = arguments[index];
      for (key in arg) {
        if (arg.hasOwnProperty(key)) {
          obj[key] = arg[key];
        }
      }
    }
    return obj;
  };

  var pgads_defaults = {
    debug: false,
    timeout: 5000,
    prerollTimeout: 100,
    adLabel: '',
    showControlsForJSAds: true
  };

  var init = function(options, readyCallback) {
    this.pgads = new PGAdsPlugin(this, options, readyCallback);
  };

  var PGAdsPlugin = function(player, options, readyCallback) {
  
    this.player = player;

    /**
     * Assigns the unique id and class names to the given element as well as the style class
     * @param element
     * @param controlName
     * @private
     */
    var assignControlAttributes_ = function(element, controlName) {
      element.id = this.controlPrefix + controlName;
      element.className = this.controlPrefix + controlName + ' ' + controlName;
    }.bind(this);

    /**
     * Returns a regular expression to test a string for the given className
     * @param className
     * @returns {RegExp}
     * @private
     */
    var getClassRegexp_ = function(className){
      return new RegExp('\\b' + className + '\\b', 'gi');
    };

    /**
     * Adds a class to the given element if it doesn't already have the class
     * @param element
     * @param classToAdd
     * @private
     */
    var addClass_ = function(element, classToAdd){
      if(getClassRegexp_(classToAdd).test(element.className)){
        return element;
      }

      return element.className = element.className.trim() + ' ' + classToAdd;
    };

    /**
     * Removes a class from the given element if it has the given class
     * @param element
     * @param classToRemove
     * @private
     */
    var removeClass_ = function(element, classToRemove){
      var classRegexp = getClassRegexp_(classToRemove);

      if(!classRegexp.test(element.className)){
        return element;
      }

      return element.className = element.className.trim().replace(classRegexp, '');
    };

    /**
     * Creates the ad container passed to the PG SDK.
     * @private
     */
    var createAdContainer_ = function() {
      // The adContainerDiv is the DOM of the element that will house
      // the ads and ad controls.
      this.vjsControls = this.player.getChild('controlBar');
      this.adContainerDiv =
          this.vjsControls.el().parentNode.appendChild(
              document.createElement('div'));
      assignControlAttributes_(this.adContainerDiv, 'pg-ad-container-bottom');
      this.adContainerDiv.style.position = "absolute";
      this.adContainerDiv.style.zIndex = 1111;

      this.adContainerTopDiv =
          this.vjsControls.el().parentNode.appendChild(
              document.createElement('div'));
      assignControlAttributes_(this.adContainerTopDiv, 'pg-ad-container-top');
      this.adContainerTopDiv.style.position = "absolute";
      this.adContainerTopDiv.style.zIndex = 1111;
      //add lister for desktop browser
    //   if (navigator.userAgent.match(/iPhone/i) ||
    //   navigator.userAgent.match(/iPad/i) || navigator.userAgent.match(/Android/i)) {
        
    //     this.adContainerDiv.addEventListener(
    //         'mouseenter',
    //         showAdControls_,
    //         false);
    //     this.adContainerDiv.addEventListener(
    //         'mouseleave',
    //         hideAdControls_,
    //         false);
    // }

      createControls_();

      this.adDisplayContainer =
          new pgads.AdDisplayContainer(this.adContainerDiv,this.adContainerTopDiv, this.contentPlayer);

    }.bind(this);

    /**
     * Creates the controls for the ad.
     * @private
     */
    var createControls_ = function() {
      this.controlsDiv = document.createElement('div');
      assignControlAttributes_(this.controlsDiv, 'pg-controls-div');
      this.controlsDiv.style.width = '100%';

      this.controlsTopDiv = document.createElement('div');
      assignControlAttributes_(this.controlsTopDiv, 'pg-top-controls-div');
      this.controlsTopDiv.style.width = '100%';


      this.countdownDiv = document.createElement('div');
      assignControlAttributes_(this.countdownDiv, 'pg-countdown-div');
      this.countdownDiv.innerHTML = this.settings.adLabel;
      this.countdownDiv.style.display = this.showCountdown ? 'block' : 'none';
      this.playPauseDiv = document.createElement('div');
      assignControlAttributes_(this.playPauseDiv, 'pg-play-pause-div');
      addClass_(this.playPauseDiv, 'pg-playing');
      this.playPauseDiv.addEventListener(
          'click',
          onAdPlayPauseClick_,
          false);
      this.muteDiv = document.createElement('div');
      assignControlAttributes_(this.muteDiv, 'pg-mute-div');
      addClass_(this.muteDiv, 'pg-non-muted');
      this.muteDiv.addEventListener(
          'click',
          onAdMuteClick_,
          false);
        
      this.seekBarDiv = document.createElement('div');
      assignControlAttributes_(this.seekBarDiv, 'pg-seek-bar-div');
      this.seekBarDiv.style.width = '100%';
      this.progressDiv = document.createElement('div');
      assignControlAttributes_(this.progressDiv, 'pg-progress-div');
      this.sliderDiv = document.createElement('div');
      assignControlAttributes_(this.sliderDiv, 'pg-slider-div');
      this.sliderDiv.addEventListener(
          'mousedown',
          onAdVolumeSliderMouseDown_,
          false);
      this.sliderLevelDiv = document.createElement('div');
      assignControlAttributes_(this.sliderLevelDiv, 'pg-slider-level-div');
      
      this.learnMoreDiv = document.createElement('div');
      assignControlAttributes_(this.learnMoreDiv, 'pg-learnmore-div');
      this.learnMoreDiv.innerHTML = "Learn More";
      this.learnMoreDiv.addEventListener(
        'click',
        onLearnMoreDivClick_,
        false);

      this.fullscreenDiv = document.createElement('div');
      assignControlAttributes_(this.fullscreenDiv, 'pg-fullscreen-div');
      addClass_(this.fullscreenDiv, 'pg-non-fullscreen');
      this.fullscreenDiv.addEventListener(
          'click',
          onAdFullscreenClick_,
          false);
        
      this.adContainerDiv.appendChild(this.controlsDiv);
      this.adContainerDiv.appendChild(this.seekBarDiv);    
      this.adContainerTopDiv.appendChild(this.controlsTopDiv);
      
      
      this.controlsDiv.appendChild(this.playPauseDiv);
      this.controlsDiv.appendChild(this.countdownDiv);
      this.controlsDiv.appendChild(this.muteDiv);
//      this.controlsDiv.appendChild(this.sliderDiv);
      this.controlsTopDiv.appendChild(this.learnMoreDiv);
      this.controlsTopDiv.appendChild(this.fullscreenDiv);
        
      this.seekBarDiv.appendChild(this.progressDiv);
      this.sliderDiv.appendChild(this.sliderLevelDiv);
      
//      this.controlsDiv.appendChild(this.seekBarDiv);
    }.bind(this);

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

    /**
     * Creates the AdsRequest and request ads through the AdsLoader.
     */
    this.requestAds = function() {
      if (!this.adDisplayContainerInitialized) {
        this.adDisplayContainer.initialize();
      }
      var adsRequest = new pgads.AdsRequest();
      if (this.settings.adTagUrl) {
        adsRequest.adTagUrl = this.settings.adTagUrl;
      } else {
        adsRequest.adsResponse = this.settings.adsResponse;
      }
      if (this.settings.forceNonLinearFullSlot) {
        adsRequest.forceNonLinearFullSlot = true;
      }

      adsRequest.linearAdSlotWidth = this.getPlayerWidth();
      adsRequest.linearAdSlotHeight = this.getPlayerHeight();
      adsRequest.nonLinearAdSlotWidth =
          this.settings.nonLinearWidth || this.getPlayerWidth();
      adsRequest.nonLinearAdSlotHeight =
          this.settings.nonLinearHeight || (this.getPlayerHeight() / 3);

      this.adsLoader.requestAds(adsRequest);
    }.bind(this);

    /**
     * Listener for the ADS_MANAGER_LOADED event. Creates the AdsManager,
     * sets up event listeners, and triggers the 'adsready' event for
     * videojs-ads-contrib.
     * @private
     */
    var onAdsManagerLoaded_ = function() {
     // this.adsManager = adsManagerLoadedEvent.getAdsManager(
     //     this.contentPlayheadTracker, this.adsRenderingSettings);
      this.adsManager = new pgads.AdsManager(player);
      this.adsManager.addEventListener(
          pgads.AdEvent.Type.AD_ERROR,
          onAdError_);
      this.adsManager.addEventListener(
          pgads.AdEvent.Type.AD_BREAK_READY,
          onAdBreakReady_);
      this.adsManager.addEventListener(
          pgads.AdEvent.Type.CONTENT_PAUSE_REQUESTED,
          this.onContentPauseRequested_);
      this.adsManager.addEventListener(
          pgads.AdEvent.Type.CONTENT_RESUME_REQUESTED,
          this.onContentResumeRequested_);
      this.adsManager.addEventListener(
          pgads.AdEvent.Type.ALL_ADS_COMPLETED,
          onAllAdsCompleted_);

      this.adsManager.addEventListener(
          pgads.AdEvent.Type.LOADED,
          onAdLoaded_);
      this.adsManager.addEventListener(
          pgads.AdEvent.Type.STARTED,
          onAdStarted_);
      this.adsManager.addEventListener(
          pgads.AdEvent.Type.CLICK,
          onAdPlayPauseClick_);
      this.adsManager.addEventListener(
          pgads.AdEvent.Type.COMPLETE,
          this.onAdComplete_);
      this.adsManager.addEventListener(
          pgads.AdEvent.Type.SKIPPED,
          this.onAdComplete_);

      this.adsManager.addEventListener(
          pgads.AdEvent.Type.PAUSED,
          this.onAdPaused_);

      this.adsManager.addEventListener(
          pgads.AdEvent.Type.AD_PLAYING,
          this.onAdPlaying_);

      if (!this.autoPlayAdBreaks) {
        try {
          var initWidth = this.getPlayerWidth();
          var initHeight = this.getPlayerHeight();
          this.adsManagerDimensions.width = initWidth;
          this.adsManagerDimensions.height = initHeight;
          this.adsManager.init(
              initWidth,
              initHeight,
              pgads.ViewMode.NORMAL);
          this.adsManager.setVolume(this.player.muted() ? 0 : this.player.volume());
        } catch (adError) {
          onAdError_(adError);
        }
      }
     
      //uncomment this line when use videojs-contrib-ads
      //this.player.trigger('adsready');
      this.player.trigger('readyforpreroll');
      //TODO: call player.play() direct bcz there is no content we will use thi for mobile app
      var isContent = false;
      if(this.player.currentSrc()) {
        isContent = true;
       } else {
        isContent = false;
       }
      if(!isContent) {
        this.player.play();
      }
      //this.player.trigger('play');
      //this.player.off('click');
      this.player.on('click', function (event) {
        showAdControls_(true);
        // if(this.currentType() != 'application/javascript') {
        //   this.trigger('vpaid.AdClickThru');
        // } 
      });

    }.bind(this);

    /**
     * DEPRECATED: Use startFromReadyCallback
     * Start ad playback, or content video playback in the absence of a
     * pre-roll.
     */
    this.start = function() {
      window.console.log(
          'WARNING: player.pgads.start is deprecated. Use ' +
              'player.pgads.startFromReadyCallback instead.');
    };

    /**
     * Start ad playback, or content video playback in the absence of a
     * pre-roll. **NOTE**: This method only needs to be called if you provide
     * your own readyCallback as the second parameter. If you
     * only provide options and do not provide your own readyCallback,
     * **DO NOT** call this method. If you do provide your own readyCallback,
     * you should call this method in the last line of that callback. For more
     * info, see this method's usage in our advanced and playlist examples.
     */
    this.startFromReadyCallback = function() {
      if (this.autoPlayAdBreaks) {
        try {
          this.adsManager.init(
              this.getPlayerWidth(),
              this.getPlayerHeight(),
              pgads.ViewMode.NORMAL);
          this.adsManager.setVolume(this.player.muted() ? 0 : this.player.volume());
          this.adsManager.start();
        } catch (adError) {
          this.onAdError_(adError);
        }
      }
    }.bind(this);

    /**
     * Listener for errors fired by the AdsLoader.
     * @param {pgads.AD_ERROR} event The error event thrown by the
     *     AdsLoader. See
     * @private
     */
    var onAdsLoaderError_ = function(event) {
     // alert('onAdsLoaderError_');
      window.console.log('AdsLoader error: ' + event.getError());
      //document.getElementById("pg-sample-console").innerHTML = document.getElementById("pg-sample-console").innerHTML + '<br/>' + 'AdsLoader error: ' + event.getError();
      this.adContainerDiv.style.display = 'none';
      this.adContainerTopDiv.style.display = 'none';
      if (this.adsManager) {
        this.adsManager.destroy();
      }
      this.player.trigger({type: 'adserror', data: { AdError: event.getError(), AdErrorEvent: event }});
    }.bind(this);

    /*
    * adPused event callback
   */

    this.onAdPaused_ = function (event) {
      if(this.adPauseDueToButtonClick == true) {
        this.adPauseDueToButtonClick = false;
        showAdControls_(false);
      } else {
          addClass_(this.playPauseDiv, 'pg-paused');
          removeClass_(this.playPauseDiv, 'pg-playing');
          this.adPlaying = false;
        }
    }.bind(this);
    /*
    * adPlaying event callback

   */
    this.onAdPlaying_ = function (event) {
      showAdControls_(true);
      addClass_(this.playPauseDiv, 'pg-playing');
      removeClass_(this.playPauseDiv, 'pg-paused');
      this.adPlaying = true;
    }.bind(this);
    
    /**
     * Listener for errors thrown by the AdsManager.
     * @param {pgads.AD_ERROR} adErrorEvent The error event thrown by
     *     the AdsManager.
     * @private
     */
    var onAdError_ = function(adErrorEvent) {
      //alert('onAdError_');
      window.console.log('Ad error: ' + adErrorEvent.getError());
      //document.getElementById("pg-sample-console").innerHTML = document.getElementById("pg-sample-console").innerHTML + '<br/>' + 'Ad error: ' + adErrorEvent.getError();
      this.vjsControls.show();
      this.adsManager.destroy();
      this.adContainerDiv.style.display = 'none';
      this.adContainerTopDiv.style.display = 'none';
      this.player.trigger({ type: 'adserror', data: { AdError: adErrorEvent.getError(), AdErrorEvent: adErrorEvent }});
    }.bind(this);

    /**
     * Listener for AD_BREAK_READY. Passes event on to publisher's listener.
     * @param {pgads.AdEvent} adEvent AdEvent thrown by the AdsManager.
     * @private
     */
    var onAdBreakReady_ = function(adEvent) {
      this.adBreakReadyListener(adEvent);
    }.bind(this);

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

    /**
     * Pauses the content video and displays the ad container so ads can play.
     * @param {pgads.AdEvent} adEvent The AdEvent thrown by the AdsManager.
     * @private
     */
    this.onContentPauseRequested_ = function(adEvent) {
      //alert('onContentPauseRequested_');
      this.adsActive = true;
      this.adPlaying = true;
      this.player.off('ended', this.localContentEndedListener);
      //TODO:
      //if (adEvent.getAd().getAdPodInfo().getPodIndex() != -1) {
      if (adEvent.getAdPosition() != -1) {
        // Skip this call for post-roll ads
        //this.player.ads.startLinearAdMode();
      }
      this.adContainerDiv.style.display = 'block';
      this.adContainerTopDiv.style.display = 'block';

      var contentType =  adEvent.getContentType();
      if ((contentType === pgads.AdType.VPAID) && !this.settings.showControlsForJSAds) {
        this.controlsDiv.style.display = 'none';
      } else {
        this.controlsDiv.style.display = 'table';
      }

      this.vjsControls.hide();
      this.player.pause();
    }.bind(this);

    /**
     * Resumes content video and hides the ad container.
     * @param {pgads.AdEvent} adEvent The AdEvent thrown by the AdsManager.
     * @private
     */
    this.onContentResumeRequested_ = function(adEvent) {


     if (navigator.userAgent.match(/iPhone/i) ||
      navigator.userAgent.match(/iPad/i) || navigator.userAgent.match(/Android/i)) {
            //send java script error in case of mobile to stop error message while showing ad on mobile
        showAdControls_(false);
        this.pauseAd();
        this.adTrackingTimer = setInterval(
            onAdPlayheadTrackerInterval_, 250);
        // Don't bump container when controls are shown
        removeClass_(this.adContainerDiv, 'bumpable-pg-ad-container');
        removeClass_(this.adContainerTopDiv, 'bumpable-pg-ad-container');
       this.currentAd.isLinear();
   }
      this.adsActive = false;
      this.adPlaying = false;
      this.player.on('ended', this.localContentEndedListener);
      if (this.currentAd == null // hide for post-roll only playlist
          || this.currentAdEventInfo.isLinear())
       { 
         // don't hide for non-linear ads
        if(!this.player.currentSrc()) {
           hideAdControls_();
         }  else {
            showAdControls_(true);
         }
      }

      this.vjsControls.show();
      if (!this.currentAd && this.player.currentSrc()) {
        // Something went wrong playing the ad
        //this.player.ads.endLinearAdMode();
      } else if (!this.contentComplete &&
          // Don't exit linear mode after post-roll or content will auto-replay
          //TODO:
          //this.currentAd.getAdPodInfo().getPodIndex() != -1 ) {
            adEvent.getPodIndex() != -1 && this.player.currentSrc()) {
        //this.player.ads.endLinearAdMode();
      }
      this.countdownDiv.innerHTML = '';
    }.bind(this);

    /**
     * Records that ads have completed and calls contentAndAdsEndedListeners
     * if content is also complete.
     * @param {pgads.AdEvent} adEvent The AdEvent thrown by the AdsManager.
     * @private
     */
    var onAllAdsCompleted_ = function(adEvent) {
      this.allAdsCompleted = true;
      if (this.contentComplete == true) {
        for (var index in this.contentAndAdsEndedListeners) {
          this.contentAndAdsEndedListeners[index]();
        }
      }
    }.bind(this);

    /**
     * Starts the content video when a non-linear ad is loaded.
     * @param {pgads.AdEvent} adEvent The AdEvent thrown by the AdsManager.
     * @private
     */
   var onAdLoaded_ = function(adEvent) {
    //alert('onAdLoaded_');
      if (!adEvent.isLinear()) {
        this.player.play();
      }
    }.bind(this);

    /**
     * Starts the interval timer to check the current ad time when an ad starts
     * playing.
     * @param {pgads.AdEvent} adEvent The AdEvent thrown by the AdsManager.
     * @private
     */
    var onAdStarted_ = function(adEvent) {

      this.currentAd = adEvent.getAd();
      this.currentAdEventInfo = adEvent;
      if(adEvent.getContentType() === pgads.AdType.VPAID) {
        //this.learnMoreDiv.style.display = 'none';
        this.learnMoreDiv.innerHTML = '';
      }

      if(this.player.muted()) {
        addClass_(this.muteDiv, 'pg-muted');
        removeClass_(this.muteDiv, 'pg-non-muted');
        this.adsManager.setVolume(0);
        // Bubble down to content player
        this.player.muted(true);
        this.adMuted = true;
        this.sliderLevelDiv.style.width = "0%";
      }

      //TODO:
      //if (this.currentAd.isLinear()) {
      if (adEvent.isLinear()) {
        this.adTrackingTimer = setInterval(
            onAdPlayheadTrackerInterval_, 250);
        // Don't bump container when controls are shown
        removeClass_(this.adContainerDiv, 'bumpable-pg-ad-container');
        removeClass_(this.adContainerTopDiv, 'bumpable-pg-ad-container');
        //removeClass_(this.player.el(), 'vjs-vast-ad-loading');
      } else {
        // Bump container when controls are shown
        addClass_(this.adContainerDiv, 'bumpable-pg-ad-container');
        addClass_(this.adContainerTopDiv, 'bumpable-pg-ad-container');
      }

      this.adControlsTimer = setTimeout(hideAdControls_, 5000);

    }.bind(this);

    /**
     * Clears the interval timer for current ad time when an ad completes.
     * @param {pgads.AdEvent} adEvent The AdEvent thrown by the AdsManager.
     * @private
     */
    this.onAdComplete_ = function(adEvent) {
      //TODO:
      //if (this.currentAd.isLinear()) {
      if (adEvent.isLinear()) {
        clearInterval(this.adTrackingTimer);
      }
    }.bind(this);

    /**
     * Gets the current time and duration of the ad and calls the method to
     * update the ad UI.
     * @private
     */
    var onAdPlayheadTrackerInterval_ = function() {
      var remainingTime = this.adsManager.getRemainingTime();
      var duration =  this.adsManager.getDuration();
      var currentTime = duration - remainingTime;
      currentTime = currentTime > 0 ? currentTime : 0;
      var isPod = false;
      var totalAds = 0;
      var adPosition;
      if (this.currentAdEventInfo.getAd()) {
        isPod = true;
        adPosition = this.currentAdEventInfo.getAdPosition();
        totalAds = this.currentAdEventInfo.getTotalAds();
      }

      // 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 (isPod && (totalAds > 1)) {
        podCount = ' (' + adPosition + ' of ' + totalAds + '): ';
      }
      
      if(typeof remainingSeconds === 'NaN') {
         this.countdownDiv.innerHTML =
          this.settings.adLabel + podCount + '0:0';
      } else {
      this.countdownDiv.innerHTML =
          this.settings.adLabel + podCount +
          remainingMinutes + ':' + remainingSeconds;
      }

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

    this.getPlayerWidth = function() {
      var retVal = parseInt(getComputedStyle(this.player.el()).width, 10) ||
          this.player.width();
      return retVal;
    }.bind(this);

    this.getPlayerHeight = function() {
      var retVal = parseInt(getComputedStyle(this.player.el()).height, 10) ||
          this.player.height();
      return retVal;
    }.bind(this);

    /**
     * Hides the ad controls on mouseout.
     * @private
     */
    var hideAdControls_ = function() {
     // this.controlsDiv.style.height = '14px';
     // this.playPauseDiv.style.display = 'none';
     // this.muteDiv.style.display = 'none';
     // this.sliderDiv.style.display = 'none';
     // this.fullscreenDiv.style.display = 'none';
     if(this.adsManager.isVPAID()) {
      this.adContainerDiv.style.display = 'none';
      this.adContainerTopDiv.style.display = 'none';
     }
      clearInterval(this.adControlsTimer);
    }.bind(this);

    /**
     * Shows ad controls on mouseover.
     * @private
     */
     var showAdControls_ = function(hideControls) {
      // this.controlsDiv.style.height = '37px';
      // this.playPauseDiv.style.display = 'block';
      // this.muteDiv.style.display = 'block';
      // this.sliderDiv.style.display = 'block';
      // this.fullscreenDiv.style.display = 'block';
      this.adContainerDiv.style.display = 'block';
      this.adContainerTopDiv.style.display = 'block';
      clearInterval(this.adControlsTimer);
      if(hideControls) {
        this.adControlsTimer = setInterval(hideAdControls_, 5000);
      }
    }.bind(this);

    /**
     * Listener for clicks on the play/pause button during ad playback.
     * @private
     */
    var onAdPlayPauseClick_ = function() {
      this.adPauseDueToButtonClick = true ;
      clearInterval(this.adControlsTimer);

      if (this.adPlaying) {
        addClass_(this.playPauseDiv, 'pg-paused');
        removeClass_(this.playPauseDiv, 'pg-playing');
        this.adsManager.pause();
        this.adPlaying = false;
      } else {
        addClass_(this.playPauseDiv, 'pg-playing');
        removeClass_(this.playPauseDiv, 'pg-paused');
        this.adsManager.resume();
        this.adPlaying = true;
      }
    }.bind(this);

    /**
     * Listener for clicks on the mute button during ad playback.
     * @private
     */
    var onAdMuteClick_ = function() {
      if (this.adMuted) {
        addClass_(this.muteDiv, 'pg-non-muted');
        removeClass_(this.muteDiv, 'pg-muted');
        this.adsManager.setVolume(1);
        // Bubble down to content player
        this.player.muted(false);
        this.adMuted = false;
        this.sliderLevelDiv.style.width = this.player.volume() * 100 + "%";
      } else {
        addClass_(this.muteDiv, 'pg-muted');
        removeClass_(this.muteDiv, 'pg-non-muted');
        this.adsManager.setVolume(0);
        // Bubble down to content player
        this.player.muted(true);
        this.adMuted = true;
        this.sliderLevelDiv.style.width = "0%";
      }
    }.bind(this);

    /* Listener for mouse down events during ad playback. Used for volume.
     * @private
     */
    var onAdVolumeSliderMouseDown_ = function() {
       document.addEventListener('mouseup', onMouseUp_, false);
       document.addEventListener('mousemove', onMouseMove_, false);
    };

    /* Mouse movement listener used for volume slider.
     * @private
     */
    var onMouseMove_ = function(event) {
      setVolumeSlider_(event);
    };

    /* Mouse release listener used for volume slider.
     * @private
     */
    var onMouseUp_ = function(event) {
      setVolumeSlider_(event);
      document.removeEventListener('mousemove', onMouseMove_);
      document.removeEventListener('mouseup', onMouseUp_);
    };

    /* Utility function to set volume and associated UI
     * @private
     */
    var setVolumeSlider_ = 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 + "%";
      this.player.volume(percent / 100); //0-1
      this.adsManager.setVolume(percent / 100);
      if (this.player.volume() == 0) {
        addClass_(this.muteDiv, 'pg-muted');
        removeClass_(this.muteDiv, 'pg-non-muted');
        this.player.muted(true);
        this.adMuted = true;
      }
      else
      {
        addClass_(this.muteDiv, 'pg-non-muted');
        removeClass_(this.muteDiv, 'pg-muted');
        this.player.muted(false);
        this.adMuted = false;
      }
    }.bind(this);

    /**
     * Listener for clicks on the fullscreen button during ad playback.
     * @private
     */
    var onAdFullscreenClick_ = function() {
      if (this.player.isFullscreen()) {
        this.player.exitFullscreen();
      } else {
        this.player.requestFullscreen();
      }
    }.bind(this);

    /**
     * Listener for clicks on the learnmore button during ad playback.
     * @private
     */
    var onLearnMoreDivClick_ = function() {
      window.open(this.adsManager.getClickThruUrl(), "_blank");      
    }.bind(this);
    /**
     * Listens for the video.js player to change its fullscreen status. This
     * keeps the fullscreen-ness of the AdContainer in sync with the player.
     * @private
     */
    var onFullscreenChange_ = function() {
      //alert("here");
      if (this.player.isFullscreen()) {
        //alert('here');
        addClass_(this.fullscreenDiv, 'pg-fullscreen-view');
        removeClass_(this.fullscreenDiv, 'pg-non-fullscreen');
        if (this.adsManager) {
          this.adsManager.resize(
              window.screen.width,
              window.screen.height,
              pgads.ViewMode.FULLSCREEN);
        }
      } else {
        addClass_(this.fullscreenDiv, 'pg-non-fullscreen');
        removeClass_(this.fullscreenDiv, 'pg-fullscreen-view');
        if (this.adsManager) {
          this.adsManager.resize(
              this.getPlayerWidth(),
              this.getPlayerHeight(),
              pgads.ViewMode.NORMAL);
        }
      }
    }.bind(this);

    /**
     * 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
     * @private
     */
    var onVolumeChange_ = function() {
      var newVolume = this.player.muted() ? 0 : this.player.volume();
      if (this.adsManager) {
        this.adsManager.setVolume(newVolume);
      }
      // Update UI
      if (newVolume == 0) {
        this.adMuted = true;
        addClass_(this.muteDiv, 'pg-muted');
        removeClass_(this.muteDiv, 'pg-non-muted');
        this.sliderLevelDiv.style.width = '0%';
      } else {
        this.adMuted = false;
        addClass_(this.muteDiv, 'pg-non-muted');
        removeClass_(this.muteDiv, 'pg-muted');
        this.sliderLevelDiv.style.width = newVolume * 100 + '%';
      }
    }.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.
     * @private
     */
    var seekContentToZero_ = function() {
      this.player.off('loadedmetadata', seekContentToZero_);
      this.player.currentTime(0);
    }.bind(this);

    /**
     * Seeks content to 00:00:00 and starts playback. This is used as an event
     * handler for the loadedmetadata event, since seeking is not possible until
     * that event has fired.
     * @private
     */
    var playContentFromZero_ = function() {
      this.player.off('loadedmetadata', playContentFromZero_);
      this.player.currentTime(0);
      this.player.play();
    }.bind(this);

    /**
     * Destroys the AdsManager, sets it to null, and calls contentComplete to
     * reset correlators. Once this is done it requests ads again to keep the
     * inventory available.
     * @private
     */
    var resetPGAds_ = function() {
      this.adsActive = false;
      this.adPlaying = false;
      this.player.on('ended', this.localContentEndedListener);
           // alert('resetPGAds');

      if (this.currentAd && this.currentAd.isLinear()) {
        this.adContainerDiv.style.display = 'none';
        this.adContainerTopDiv.style.display = 'none';

      }
      this.vjsControls.show();
      //this.player.ads.endLinearAdMode();
      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.contentComplete) {
        this.adsLoader.contentComplete();
      }
      this.contentComplete = false;
      this.allAdsCompleted = false;
    }.bind(this);

    /**
     * Ads an EventListener to the AdsManager. For a list of available events,
     * see
     * @param {pgads.AdEvent.Type} event The AdEvent.Type for which to listen.
     * @param {function} callback The method to call when the event is fired.
     */
    this.addEventListener = function(event, callback) {
      if (this.adsManager) {
        this.adsManager.addEventListener(event, callback);
      }
    }.bind(this);

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

    /**
     * DEPRECATED: Use setContentWithAdTag.
     * 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.
     * @param {?boolean} playOnLoad True to play the content once it has loaded,
     *     false to only load the content but not start playback.
     */
    this.setContent = function(contentSrc, adTag, playOnLoad) {
      this.setContentWithAdTag(contentSrc, adTag, playOnLoad);
    }.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.
     * @param {?boolean} playOnLoad True to play the content once it has loaded,
     *     false to only load the content but not start playback.
     */
    this.setContentWithAdTag = function(contentSrc, adTag, playOnLoad) {
     // alert('setContentWithAdTag');
      resetPGAds_();
      this.settings.adTagUrl = adTag ? adTag : this.settings.adTagUrl;
      changeSource_(contentSrc, playOnLoad);
    }.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.
     * @param {?boolean} playOnLoad True to play the content once it has loaded,
     *     false to only load the content but not start playback.
     */
    this.setContentWithAdsResponse = function(contentSrc, adsResponse, playOnLoad) {
      //alert('setContentWithAdsResponse');
     //TODO:
      resetPGAds_();

      this.settings.adsResponse = adsResponse ? adsResponse : this.settings.adsResponse;

      changeSource_(contentSrc, playOnLoad);
    }.bind(this);

    /**
     * Changes the player source.
     * @param {?string} contentSrc The URI for the content to be played. Leave
     *     blank to use the existing content.
     * @param {?boolean} playOnLoad True to play the content once it has loaded,
     *     false to only load the content but not start playback.
     * @private
     */
    var changeSource_ = function(contentSrc, playOnLoad) {
      // Only try to pause the player when initialised with a source already
      if (!!this.player.currentSrc()) {
        this.player.currentTime(0);
        this.player.pause();
      }
      if (contentSrc) {
        this.player.src(contentSrc);
      }
      if (playOnLoad) {
        this.player.on('loadedmetadata', playContentFromZero_);
      } else {
        this.player.on('loadedmetadata', seekContentToZero_);
      }
    }.bind(this);

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

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

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

    /**
     * Pauses the ad.
     */
    this.pauseAd = function() {
      if (this.adsActive && this.adPlaying) {
        addClass_(this.playPauseDiv, 'pg-paused');
        removeClass_(this.playPauseDiv, 'pg-playing');
        this.adsManager.pause();
        this.adPlaying = false;
      }
    }.bind(this);

    /**
     * Resumes the ad.
     */
    this.resumeAd = function() {
      if (this.adsActive && !this.adPlaying) {
        addClass_(this.playPauseDiv, 'pg-playing');
        removeClass_(this.playPauseDiv, 'pg-paused');
        this.adsManager.resume();
        this.adPlaying = true;
      }
    }.bind(this);

    /**
     * Set up intervals to check for seeking and update current video time.
     * @private
     */
    var setUpPlayerIntervals_ = function() {
      this.updateTimeIntervalHandle =
          setInterval(updateCurrentTime_, this.seekCheckInterval);
      this.seekCheckIntervalHandle =
          setInterval(checkForSeeking_, this.seekCheckInterval);
      this.resizeCheckIntervalHandle =
          setInterval(checkForResize_, this.resizeCheckInterval);
    }.bind(this);

    /**
     * Updates the current time of the video
     * @private
     */
    var updateCurrentTime_ = function() {
      if (!this.contentPlayheadTracker.seeking) {
        this.contentPlayheadTracker.currentTime = this.player.currentTime();
      }
    }.bind(this);

    /**
     * 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.
     *
     * @private
     */
    var checkForSeeking_ = function() {
      var tempCurrentTime = this.player.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.player.currentTime();
    }.bind(this);

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

      if (this.adsManager && (currentWidth != this.adsManagerDimensions.width ||
          currentHeight != this.adsManagerDimensions.height)) {
        this.adsManagerDimensions.width = currentWidth;
        this.adsManagerDimensions.height = currentHeight;
        this.adsManager.resize(currentWidth, currentHeight, pgads.ViewMode.NORMAL);
      }
    }.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.showCountdown = showCountdownIn;
      this.countdownDiv.style.display = this.showCountdown ? 'block' : 'none';
    }.bind(this);

    /**
     * Current plugin version.
     */
    this.VERSION = '0.2.0';

    /**
     * Stores user-provided settings.
     */
    this.settings;

    /**
     * Used to prefix videojs pg
     */
    this.controlPrefix;

    /**
     * Video element playing content.
     */
    this.contentPlayer;

    /**
     * Boolean flag to show or hide the ad countdown timer.
     */
    this.showCountdown;

    /**
     * Boolena flag to enable manual ad break playback.
     */
    this.autoPlayAdBreaks;

    /**
     * Video.js control bar.
     */
    this.vjsControls;

    /**
     * Div used as an ad container.
     */
    this.adContainerDiv;

    /**
     * Div used to display ad controls.
     */
    this.controlsDiv;

    /**
     * Div used to display ad countdown timer.
     */
    this.countdownDiv;

    /**
     * Div used to display add seek bar.
     */
    this.seekBarDiv;

    /**
     * Div used to display ad progress (in seek bar).
     */
    this.progressDiv;

    /**
     * Div used to display ad play/pause button.
     */
    this.playPauseDiv;

    /**
     * Div used to display ad mute button.
     */
    this.muteDiv;

    /**
     * Div used by the volume slider.
     */
    this.sliderDiv;

    /**
     * Volume slider level visuals
     */
    this.sliderLevelDiv;

    /**
     * Div used to display ad fullscreen button.
     */
    this.fullscreenDiv;

    /**
     * PG SDK AdDisplayContainer.
     */
    this.adDisplayContainer;

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

    /**
     * PG SDK AdsLoader
     */
    this.adsLoader;

    /**
     * PG SDK AdsManager
     */
    this.adsManager;

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

    /**
     * Ad tag URL. Should return VAST, VMAP, or ad rules.
     */
    this.adTagUrl;

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

    /**
     * Current PG SDK Ad.
     */
    this.currentAd;

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

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

    /**
     * Timer used to hide/show adControls.
     */
    this.adControlsTimer;

    /**
     * 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;

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

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

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

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

    /**
     * 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;

    /**
     * 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;

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

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

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

    /**
     * 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 = [];

    /**
     * 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 = [];

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

    /**
      * toggle play/pause button based on play/pause button click over adclickthru.
      */
    this.adPauseDueToButtonClick = false;


    /**
     * Local content ended listener for contentComplete.
     */
    this.localContentEndedListener = function() {
      if (this.adsLoader && !this.contentComplete) {
        this.adsLoader.contentComplete();
        this.contentComplete = true;
      }
      for (var index in this.contentEndedListeners) {
        this.contentEndedListeners[index]();
      }
      if (this.allAdsCompleted) {
        for (var index in this.contentAndAdsEndedListeners) {
          this.contentAndAdsEndedListeners[index]();
        }
      }
      clearInterval(this.updateTimeIntervalHandle);
      clearInterval(this.seekCheckIntervalHandle);
      clearInterval(this.resizeCheckIntervalHandle);
      if(this.player.el()) {
        this.player.one('play', setUpPlayerIntervals_);
      }
    }.bind(this);

    this.playerDisposedListener = function(){
      this.contentEndedListeners, this.contentAndAdsEndedListeners = [], [];
      this.contentComplete = true;
      this.player.off('ended', this.localContentEndedListener);
      var intervalsToClear = [this.updateTimeIntervalHandle, this.seekCheckIntervalHandle,
        this.adTrackingTimer, this.resizeCheckIntervalHandle];
      for (var index in intervalsToClear) {
        var interval = intervalsToClear[index];
        if (interval) {
          clearInterval(interval);
        }
      }
      if (this.adsManager) {
        this.adsManager.destroy();
        this.adsManager = null;
      }
    }.bind(this);

    this.settings = extend({}, pgads_defaults, options || {});

    // Currently this isn't used but I can see it being needed in the future, so
    // to avoid implementation problems with later updates I'm requiring it.
    if (!this.settings['id']) {
      window.console.log('Error: must provide id of video.js div');
      return;
    }

    this.controlPrefix = (this.settings.id + '_') || '';

    this.contentPlayer = document.getElementById(this.settings['id'] + '_html5_api');
    // Default showing countdown timer to true.
    this.showCountdown = true;
    if (this.settings['showCountdown'] == false) {
      this.showCountdown = false;
    }

    this.autoPlayAdBreaks = true;
    if (this.settings['autoPlayAdBreaks'] == false) {
      this.autoPlayAdBreaks = false;
    }

    player.one('play', setUpPlayerIntervals_);

    player.on('ended', this.localContentEndedListener);
    player.on('dispose', this.playerDisposedListener);

    var contrib_ads_defaults = {
      debug: this.settings.debug,
      timeout: this.settings.timeout,
      prerollTimeout: this.settings.prerollTimeout
    };

    var ads_plugin_settings =
        extend({}, contrib_ads_defaults, options['contribAdsSettings'] || {});
    //player.ads(ads_plugin_settings);

    // this.adsRenderingSettings = new google.ima.AdsRenderingSettings();
    // this.adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true;
    // if (this.settings['adsRenderingSettings']) {
    //   for (var setting in this.settings['adsRenderingSettings']) {
    //     this.adsRenderingSettings[setting] =
    //         this.settings['adsRenderingSettings'][setting];
    //   }
    // }

    // if (this.settings['locale']) {
    //   google.ima.settings.setLocale(this.settings['locale']);
    // }

    createAdContainer_();
    this.adsLoader = new pgads.AdsLoader(this.adDisplayContainer, player);

    
//     if (this.settings.numRedirects) {
//       this.adsLoader.getSettings().setNumRedirects(this.settings.numRedirects);
//     }
// this.adsLoader.getSettings().setVpaidMode(
//         google.ima.ImaSdkSettings.VpaidMode.ENABLED);
//     if (this.settings.vpaidAllowed == false) {
//       this.adsLoader.getSettings().setVpaidMode(
//           google.ima.ImaSdkSettings.VpaidMode.DISABLED);
//     }
//     if (this.settings.vpaidMode) {
//       this.adsLoader.getSettings().setVpaidMode(this.settings.vpaidMode);
//     }

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

//     this.adsLoader.getSettings().setPlayerType('videojs-ima');
//     this.adsLoader.getSettings().setPlayerVersion(this.VERSION);
//     this.adsLoader.getSettings().setAutoPlayAdBreaks(this.autoPlayAdBreaks);

    this.adsLoader.addEventListener(
      pgads.AdEvent.Type.ADS_MANAGER_LOADED,
      onAdsManagerLoaded_,
      false);
    this.adsLoader.addEventListener(
      pgads.AdEvent.Type.AD_ERROR,
      onAdsLoaderError_,
      false);
    if (!readyCallback) {
      readyCallback = this.startFromReadyCallback;
    }

    player.on('readyforpreroll', readyCallback);
    player.ready(function() {
      player.on('fullscreenchange', onFullscreenChange_);
      player.on('volumechange', onVolumeChange_);
    });
  };

  vjs.plugin('pgads', init);
}(window.videojs));
