var interactivePlayerSelfScriptPath = document.getElementsByTagName('script')[document.getElementsByTagName('script').length-1].src;

function loadJsWindows (callback) {
  if (window.JSWindow) callback();
  else {
    var jswScript = document.getElementById('JSWindowScript');
    if (jswScript)
      jswScript.addEventListener('load', callback);
    else {
      if (interactivePlayerSelfScriptPath.indexOf('\/interactivePlayer.js') < 0) throw 'interactivePlayer.js cannot determine its script path. You have to load it when page loads.';
      var selfScriptPath = interactivePlayerSelfScriptPath.substring(0, interactivePlayerSelfScriptPath.lastIndexOf('\/')+1);
      jswScript = document.createElement('script');
      jswScript.setAttribute('type', 'text/javascript');
      jswScript.addEventListener('load', callback);
      jswScript.src = selfScriptPath+'JSWindow.js';
      document.getElementsByTagName('head')[0].appendChild(jswScript);
    }
  }
}

window.previewVideoWin = null;
window.showPreview = function (preview, video, asWindow=true) {
  if (player && player.currentVideo >= 0) return;
  loadJsWindows(function () {
    let img = document.createElement('img');
    img.src = preview;
    img.style.width = '100%';
    img.style.height = '100%';
    img.style.cursor = 'pointer';
    let previewVideoWin = new JSWindow();
    window.previewVideoWin = previewVideoWin;
    if (asWindow) previewVideoWin.pos.position = 'fixed';
    else previewVideoWin.pos.position = 'absolute';
    previewVideoWin.pos.top = Number.NaN;
    previewVideoWin.pos.left = 10;
    previewVideoWin.pos.width = 300;
    previewVideoWin.pos.height = 220;
    previewVideoWin.pos.right = Number.NaN;
    previewVideoWin.pos.bottom = 10;
    previewVideoWin.minimizable = false;
    previewVideoWin.maximizable = !asWindow;
    previewVideoWin.setTitle('Video');
    previewVideoWin.el['InnerBox'].appendChild(img);
    previewVideoWin.el['InnerBox'].style.overflow = 'hidden';
    previewVideoWin.addEventListener('hide', function () {
      window.previewVideoWin = null;
    });
    previewVideoWin.show((asWindow)?document.body:document.getElementById('SideVideo'));
    if (!asWindow) previewVideoWin.maximize();
    img.addEventListener('click', function () {
      player.play(video, 0, true);
    }, false);
  });
}


function InteractivePlayer () {
  var _this = this;
  this.queryActions = new Array();
  this.playlist = new Array();
  if (interactivePlayerSelfScriptPath.indexOf('\/interactivePlayer.js') < 0) throw 'interactivePlayer.js cannot determine its script path. You have to load it when page loads.';
  this.selfScriptPath = interactivePlayerSelfScriptPath.substring(0, interactivePlayerSelfScriptPath.lastIndexOf('\/')+1);
  function videoQualityLoad () {
    _this.loading = false;
    while (_this.queryActions.length > 0) {
      var act = _this.queryActions.shift();
      var fkt = act.shift();
      fkt.apply(_this, act);
    }
  }
  function videojsLoad () {
    var qualitySelectScript = document.createElement('script');
    qualitySelectScript.setAttribute('type', 'text/javascript');
    qualitySelectScript.addEventListener('load', videoQualityLoad);
    qualitySelectScript.src = _this.selfScriptPath+'silvermine-videojs-quality-selector.min.js';
    document.body.appendChild(qualitySelectScript);
  }
  loadJsWindows(function () {
    if (window.videojs) videojsLoad();
    else {
      window.HELP_IMPROVE_VIDEOJS = false;
      var videojsStyle = document.createElement('link');
      videojsStyle.setAttribute('rel', 'stylesheet');
      let cssPath = _this.selfScriptPath.split('/');
      if (cssPath.pop() == '') cssPath.pop();
      videojsStyle.href = cssPath.join('/')+'/css/video-js.min.css';
      document.getElementsByTagName('head')[0].appendChild(videojsStyle);
      var videoScript = document.createElement('script');
      videoScript.setAttribute('type', 'text/javascript');
      videoScript.addEventListener('load', videojsLoad);
      videoScript.src = _this.selfScriptPath+'video.min.js';
      document.body.appendChild(videoScript);
    }
  });
}
InteractivePlayer.prototype = {
  // private
  selfScriptPath : '',
  win : null,
  video : null,
  player : null,
  playlist : null,
  loading : true,
  queryActions : null,
  currentVideo : -1,
  currentAction : 0,
  prevBut : null,
  nextBut : null,
  _asWindow : true,
  get asWindow () { return this._asWindow; }, set asWindow (v) {
    if (this.win) {
      this.win.maximizable = !this._asWindow;
      if (v) {
        this.win.show(document.body);
        this.win.normalize();
        if (!this._asWindow) this.win.hide();
      } else {
        this.win.show(document.getElementById('SideVideo'));
        this.win.maximize();
      }
    }
    this._asWindow = v;
  },
  timeset : -1,
  playall : false,
  lastWaiting : null, // contains alternating pairs of video time and real time


  indexById : /* private */ function (id) {
    for (var i = 0; i < this.playlist.length; i++)
      if (this.playlist[i].id == id)
        return i;
    return -1;
  },

  videoByHashtag : /* public */ function (hashtag) {
    for (var i = 0; i < this.playlist.length; i++)
      if (this.playlist[i].hashtags && this.playlist[i].hashtags.indexOf(hashtag) >= 0)
        return this.playlist[i].id;
    return '';
  },

  timeupdate : /* private */ function () {
    if (this.timeset >= 0) {
      this.video.currentTime = this.timeset;
      this.timeset = -1;
    }
    if (this.currentVideo < 0 || !this.playlist[this.currentVideo].actions) return;
    var t = this.video.currentTime;
    var stopInd = this.currentAction;
    while (stopInd < this.playlist[this.currentVideo].actions.length)
      if (this.playlist[this.currentVideo].actions[stopInd].time > t) break;
      else stopInd++;
    while (this.currentAction < stopInd) {
      try {
        if ((this.currentAction == stopInd-1 || this.playlist[this.currentVideo].actions[this.currentAction].required) && this.playlist[this.currentVideo].actions[this.currentAction].fkt)
          this.playlist[this.currentVideo].actions[this.currentAction].fkt.call(this, this.currentAction == stopInd-1);
      } finally {
        this.currentAction++;
      }
    }
  },

  videoended : /* private */ function () {
    if (!this.playall) return;
    if (this.currentVideo >= this.playlist.length-1) {
      this.playall = false;
      return;
    }
    this.currentVideo++;
    this.currentAction = 0;
    this.loadVideo(this.currentVideo);
    try {
      this.player.play();
    } catch (e) { }
  },

  getCurrentQuality : /* private */ function () {
    var q = null;
    var quality = '';
    for (var i = 0; i < this.video.parentElement.getElementsByTagName('div').length; i++)
      if (this.video.parentElement.getElementsByTagName('div')[i].className.indexOf('vjs-quality-selector') >= 0) {
        q = this.video.parentElement.getElementsByTagName('div')[i];
        break;
      }
    if (q) {
      for (var i = 0; i < q.getElementsByTagName('li').length; i++)
        if (q.getElementsByTagName('li')[i].className.indexOf('vjs-menu-item') >= 0) if (q.getElementsByTagName('li')[i].className.indexOf('vjs-selected') >= 0) {
          q = q.getElementsByTagName('li')[i];
          break;
        }
      if (q) {
        for (var i = 0; i < q.getElementsByTagName('span').length; i++)
          if (q.getElementsByTagName('span')[i].className.indexOf('vjs-menu-item-text') >= 0) {
            q = q.getElementsByTagName('span')[i];
            break;
          }
        if (q) {
          quality = q.textContent;
        }
      }
    }
    return quality;
  },

  videowaiting : /* private */ function (timerRecall=false) {
    var _this = this;
    this.lastWaiting.push(this.video.currentTime);
    this.lastWaiting.push(Math.floor(Date.now() / 1000));
    if (!timerRecall)
      window.setTimeout(function () { _this.videowaiting(true); }, 2000);
    var l = this.lastWaiting.length;
    if (!timerRecall && l >= 8 || l >= 4 && (this.lastWaiting[l-2] - this.lastWaiting[l-4]) * 2 + 1 < (this.lastWaiting[l-1] - this.lastWaiting[l-3])) {
      var quality = this.getCurrentQuality();
      var redQualBegin = '!';
      if (quality.indexOf('1080p') >= 0)
        redQualBegin = '720p';
      if (quality.indexOf('720p') >= 0)
        redQualBegin = '400p';
      this.lastWaiting = new Array();
      if (redQualBegin == '!') return;
      console.log('Reducing video quality to '+redQualBegin);
      var q = null;
      for (var i = 0; i < this.video.parentElement.getElementsByTagName('div').length; i++)
        if (this.video.parentElement.getElementsByTagName('div')[i].className.indexOf('vjs-quality-selector') >= 0) {
          q = this.video.parentElement.getElementsByTagName('div')[i];
          break;
        }
      if (q) {
        for (var i = 0; i < q.getElementsByTagName('li').length; i++)
          if (q.getElementsByTagName('li')[i].className.indexOf('vjs-menu-item') >= 0)
            if (q.getElementsByTagName('li')[i].textContent.indexOf(redQualBegin) >= 0) {
              q.getElementsByTagName('li')[i].click();
              break;
            }
      }
    }
  },

  closeWindow : /* private */ function () {
    if (this.currentVideo >= 0 || this.playlist[this.currentVideo].actions)
      while (this.currentAction < this.playlist[this.currentVideo].actions.length) {
        try {
          if (this.playlist[this.currentVideo].actions[this.currentAction].final && this.playlist[this.currentVideo].actions[this.currentAction].fkt)
            this.playlist[this.currentVideo].actions[this.currentAction].fkt.call(this, false);
        } catch (e) { }
        this.currentAction++;
      }
    this.player.dispose();
    this.freePlayer();
  },

  freePlayer : /* private */ function () {
    this.video = null;
    this.player = null;
    this.win = null;
    this.prevBut = null;
    this.nextBut = null;
    this.currentVideo = -1;
  },

  createWindow : /* prvate */ function () {
    if (this.win) throw 'Window already created!';
    this.playall = false;
    var _this = this;
    this.win = new JSWindow();
    this.win.pos.position = 'fixed';
    this.win.pos.top = 300;
    this.win.pos.left = 150;
    this.win.pos.width = Number.NaN;
    this.win.pos.height = Number.NaN;
    this.win.pos.right = 150;
    this.win.pos.bottom = 10;
    this.win.excludable = true;
    this.win.minimizable = !this.asWindow;
    this.win.setTitle('Video');
    this.win.addEventListener('hide', function () { _this.closeWindow(); });
    this.win.addEventListener('free', function () { _this.freePlayer(); });
    this.video = document.createElement('video');
    this.video.className = 'video-js';
    this.video.setAttribute('controls', '');
    this.video.disablePictureInPicture = true;
    this.video.addEventListener('timeupdate', function () { _this.timeupdate(); }, false);
    this.video.addEventListener('ended', function () { _this.videoended(); }, false);
    this.video.addEventListener('waiting', function () { _this.videowaiting(); }, false);
    this.win.el['InnerBox'].appendChild(this.video);
    this.win.show((this.asWindow)?document.body:document.getElementById('SideVideo'));
    if (!this.asWindow) this.win.maximize();
    this.player = videojs(this.video);
    this.player.controlBar.addChild('QualitySelector');
    var divs = this.video.parentElement.getElementsByTagName('div');
    for (var i = 0; i < divs.length; i++)
      if ((' '+divs[i].className+' ').indexOf(' vjs-control-bar ') >= 0) {
        this.nextBut = document.createElement('a');
        this.nextBut.href = 'javascript:';
        this.nextBut.className = 'video-next-but';
        this.nextBut.addEventListener('click', function () {
          _this.next();
        });
        this.nextBut.innerHTML = 'n&auml;chstes Video &#9654; &#9654;';
        divs[i].appendChild(this.nextBut);
        this.prevBut = document.createElement('a');
        this.prevBut.href = 'javascript:';
        this.prevBut.className = 'video-prev-but';
        this.prevBut.addEventListener('click', function () {
          _this.prev();
        });
        this.prevBut.innerHTML = '&#9664; &#9664; vorheriges Video';
        divs[i].appendChild(this.prevBut);
        break;
      }
  },

  clearPlaylist : /* public */ function () {
    if (this.player) this.player.pause();
    this.playlist = new Array();
    this.currentVideo = -1;
  },

  loadVideo : /* private */ function (nr) {
    if (this.prevBut)
      this.prevBut.style.visibility = (nr > 0)?'visible':'hidden';
    if (this.nextBut)
      this.nextBut.style.visibility = (nr < this.playlist.length - 1)?'visible':'hidden';
    var url = this.playlist[nr].src;
    var quality = this.getCurrentQuality();
    this.player.src([
      {type: "video\/mp4", src: url+((this.playlist[nr].fixedResolution)?'.mp4':'-1080p.mp4'), label: '1080p 50fps', selected: (quality == '1080p 50fps')},
      {type: "video\/mp4", src: url+((this.playlist[nr].fixedResolution)?'.mp4':'-720p.mp4'), label: '720p 25fps', selected: (quality == '720p 25fps')},
      {type: "video\/mp4", src: url+((this.playlist[nr].fixedResolution)?'.mp4':'-400p.mp4'), label: '400p 25fps', selected: (quality == '400p 25fps')},
    ]);
    this.lastWaiting = [0, Math.floor(Date.now() / 1000)];
  },

  addVideo : /* public */ function (videoInfo) {
    if (videoInfo.actions)
      videoInfo.actions.sort(function (a, b) { return a.time - b.time; });
    var absPath = document.createElement('a');
    absPath.style.display = 'none';
    document.body.appendChild(absPath);
    absPath.href = videoInfo.src;
    videoInfo.src = absPath.href;
    document.body.removeChild(absPath);
    this.playlist.push(videoInfo);
  },

  play : /* public */ function (id, time=-1, playall=false) {
    if (window.previewVideoWin)
      window.previewVideoWin.hide();
    var i = this.indexById(id);
    if (i < 0) return;
    if (this.loading) {
      this.queryActions.push([this.play, id, time]);
      return;
    }
    this.currentVideo = i;
    this.currentAction = 0;
    if (!this.win)
      this.createWindow();
    else if (!this.win.visible) this.win.show((this.asWindow)?document.body:document.getElementById('SideVideo'));
    this.loadVideo(i);
    this.timeset = time;
    try {
      this.player.play();
      if (playall) this.playall = true;
    } catch (e) { }
  },

  playAll : /* public */ function () {
    if (this.playlist.length == 0) return;
    if (this.loading) {
      this.queryActions.push([this.playAll]);
      return;
    }
    this.play(this.playlist[0].id);
    this.playall = true;
  },

  next : /* public */ function () {
    if (this.loading) {
      this.queryActions.push([this.next]);
      return;
    }
    if (this.currentVideo >= this.playlist.length-1) return;
    this.play(this.playlist[this.currentVideo+1].id);
    this.playall = this.video.paused;
  },

  prev : /* public */ function () {
    if (this.loading) {
      this.queryActions.push([this.prev]);
      return;
    }
    if (this.currentVideo <= 0) return;
    this.play(this.playlist[this.currentVideo-1].id);
  }
};
