var JSWebrtc = {
  Player: null,
  VideoElement: null,
  CreateVideoElements: function () {
    var elements = document.querySelectorAll(".jswebrtc");
    for (var i = 0; i < elements.length; i++) {
      new JSWebrtc.VideoElement(elements[i])
    }
  },
  FillQuery: function (query_string, obj) {
    obj.user_query = {};
    if (query_string.length == 0) return;
    if (query_string.indexOf("?") >= 0) query_string = query_string.split("?")[1];
    var queries = query_string.split("&");
    for (var i = 0; i < queries.length; i++) {
      var query = queries[i].split("=");
      obj[query[0]] = query[1];
      obj.user_query[query[0]] = query[1]
    }
    if (obj.domain) obj.vhost = obj.domain
  },
  ParseUrl: function (rtmp_url) {
    var a = document.createElement("a");
    a.href = rtmp_url.replace("rtmp://", "http://").replace("webrtc://", "http://").replace("rtc://", "http://");
    var vhost = a.hostname;
    var app = a.pathname.substr(1, a.pathname.lastIndexOf("/") - 1);
    var stream = a.pathname.substr(a.pathname.lastIndexOf("/") + 1);
    app = app.replace("...vhost...", "?vhost=");
    if (app.indexOf("?") >= 0) {
      var params = app.substr(app.indexOf("?"));
      app = app.substr(0, app.indexOf("?"));
      if (params.indexOf("vhost=") > 0) {
        vhost = params.substr(params.indexOf("vhost=") + "vhost=".length);
        if (vhost.indexOf("&") > 0) {
          vhost = vhost.substr(0, vhost.indexOf("&"))
        }
      }
    }
    if (a.hostname == vhost) {
      var re = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;
      if (re.test(a.hostname)) vhost = "__defaultVhost__"
    }
    var schema = "rtmp";
    if (rtmp_url.indexOf("://") > 0) schema = rtmp_url.substr(0, rtmp_url.indexOf("://"));
    var port = a.port;
    if (!port) {
      if (schema === "http") {
        port = 80
      } else if (schema === "https") {
        port = 443
      } else if (schema === "rtmp") {
        port = 1935
      } else if (schema === "webrtc" || schema === "rtc") {
        port = 1985
      }
    }
    var ret = {
      url: rtmp_url,
      schema: schema,
      server: a.hostname,
      port: port,
      vhost: vhost,
      app: app,
      stream: stream
    };
    JSWebrtc.FillQuery(a.search, ret);
    return ret
  },
  HttpPost: function (url, data) {
    return new Promise(function (resolve, reject) {
      var xhr = new XMLHttpRequest;
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4 && (xhr.status >= 200 && xhr.status < 300)) {
          var respone = JSON.parse(xhr.responseText);
          xhr.onreadystatechange = new Function;
          xhr = null;
          resolve(respone)
        }
      };
      xhr.open("POST", url, true);
      xhr.timeout = 5e3;
      xhr.responseType = "text";
      xhr.setRequestHeader("Content-Type", "application/json");
      xhr.send(data)
    })
  }
};
if (document.readyState === "complete") {
  JSWebrtc.CreateVideoElements()
} else {
  document.addEventListener("DOMContentLoaded", JSWebrtc.CreateVideoElements)
}
JSWebrtc.VideoElement = function () {
  "use strict";
  var VideoElement = function (element) {
    var url = element.dataset.url;
    if (!url) {
      throw "VideoElement has no `data-url` attribute"
    }
    var addStyles = function (element, styles) {
      for (var name in styles) {
        element.style[name] = styles[name]
      }
    };
    this.container = element;
    addStyles(this.container, {
      display: "inline-block",
      position: "relative",
      minWidth: "80px",
      minHeight: "80px"
    });
    this.video = document.createElement("video");
    this.video.width = 960;
    this.video.height = 540;
    addStyles(this.video, {
      display: "block",
      width: "100%"
    });
    this.container.appendChild(this.video);
    this.playButton = document.createElement("div");
    this.playButton.innerHTML = VideoElement.PLAY_BUTTON;
    addStyles(this.playButton, {
      zIndex: 2,
      position: "absolute",
      top: "0",
      bottom: "0",
      left: "0",
      right: "0",
      maxWidth: "75px",
      maxHeight: "75px",
      margin: "auto",
      opacity: "0.7",
      cursor: "pointer"
    });
    this.container.appendChild(this.playButton);
    var options = {
      video: this.video
    };
    for (var option in element.dataset) {
      try {
        options[option] = JSON.parse(element.dataset[option])
      } catch (err) {
        options[option] = element.dataset[option]
      }
    }
    this.player = new JSWebrtc.Player(url, options);
    element.playerInstance = this.player;
    if (options.poster && !options.autoplay) {
      options.decodeFirstFrame = false;
      this.poster = new Image;
      this.poster.src = options.poster;
      this.poster.addEventListener("load", this.posterLoaded);
      addStyles(this.poster, {
        display: "block",
        zIndex: 1,
        position: "absolute",
        top: 0,
        left: 0,
        bottom: 0,
        right: 0
      });
      this.container.appendChild(this.poster)
    }
    if (!this.player.options.streaming) {
      this.container.addEventListener("click", this.onClick.bind(this))
    }
    if (options.autoplay) {
      this.playButton.style.display = "none"
    }
    if (this.player.audioOut && !this.player.audioOut.unlocked) {
      var unlockAudioElement = this.container;
      if (options.autoplay) {
        this.unmuteButton = document.createElement("div");
        this.unmuteButton.innerHTML = VideoElement.UNMUTE_BUTTON;
        addStyles(this.unmuteButton, {
          zIndex: 2,
          position: "absolute",
          bottom: "10px",
          right: "20px",
          width: "75px",
          height: "75px",
          margin: "auto",
          opacity: "0.7",
          cursor: "pointer"
        });
        this.container.appendChild(this.unmuteButton);
        unlockAudioElement = this.unmuteButton
      }
      this.unlockAudioBound = this.onUnlockAudio.bind(this, unlockAudioElement);
      unlockAudioElement.addEventListener("touchstart", this.unlockAudioBound, false);
      unlockAudioElement.addEventListener("click", this.unlockAudioBound, true)
    }
  };
  VideoElement.prototype.onUnlockAudio = function (element, ev) {
    if (this.unmuteButton) {
      ev.preventDefault();
      ev.stopPropagation()
    }
    this.player.audioOut.unlock(function () {
      if (this.unmuteButton) {
        this.unmuteButton.style.display = "none"
      }
      element.removeEventListener("touchstart", this.unlockAudioBound);
      element.removeEventListener("click", this.unlockAudioBound)
    }.bind(this))
  };
  VideoElement.prototype.onClick = function (ev) {
    if (this.player.isPlaying) {
      this.player.pause();
      this.playButton.style.display = "block"
    } else {
      this.player.play();
      this.playButton.style.display = "none";
      if (this.poster) {
        this.poster.style.display = "none"
      }
    }
  };
  VideoElement.PLAY_BUTTON = '<svg style="max-width: 75px; max-height: 75px;" ' + 'viewBox="0 0 200 200" alt="Play video">' + '<circle cx="100" cy="100" r="90" fill="none" ' + 'stroke-width="15" stroke="#fff"/>' + '<polygon points="70, 55 70, 145 145, 100" fill="#fff"/>' + "</svg>";
  VideoElement.UNMUTE_BUTTON = '<svg style="max-width: 75px; max-height: 75px;" viewBox="0 0 75 75">' + '<polygon class="audio-speaker" stroke="none" fill="#fff" ' + 'points="39,13 22,28 6,28 6,47 21,47 39,62 39,13"/>' + '<g stroke="#fff" stroke-width="5">' + '<path d="M 49,50 69,26"/>' + '<path d="M 69,50 49,26"/>' + "</g>" + "</svg>";
  return VideoElement
}();
JSWebrtc.Player = function () {
  "use strict";
  var Player = function (openUrl, url, options) {
    this.options = options || {};
    if (!url.match(/^webrtc?:\/\//)) {
      throw "JSWebrtc just work with webrtc"
    }
    if (!this.options.video) {
      throw "VideoElement is null"
    }
    this.urlParams = JSWebrtc.ParseUrl(url);
    this.pc = null;
    this.autoplay = !!options.autoplay || false;
    this.paused = true;
    if (this.autoplay) this.options.video.muted = true;
    this.startLoading(openUrl)
  };
  Player.prototype.startLoading = function (openUrl) {
    var _self = this;
    if (_self.pc) {
      _self.pc.close()
    }
    _self.pc = new RTCPeerConnection(null);
    _self.pc.ontrack = function (event) {
      _self.options.video["srcObject"] = event.streams[0]
    };
    _self.pc.addTransceiver("audio", {
      direction: "recvonly"
    });
    _self.pc.addTransceiver("video", {
      direction: "recvonly"
    });
    _self.pc.createOffer().then(function (offer) {
      return _self.pc.setLocalDescription(offer).then(function () {
        return offer
      })
    }).then(function (offer) {
      return new Promise(function (resolve, reject) {
        var port = _self.urlParams.port || 1985;
        var api = _self.urlParams.user_query.play || "/rtc/v1/play/";
        if (api.lastIndexOf("/") != api.length - 1) {
          api += "/"
        }
        var url = "http://" + _self.urlParams.server + ":" + port + api;
        for (var key in _self.urlParams.user_query) {
          if (key != "api" && key != "play") {
            url += "&" + key + "=" + _self.urlParams.user_query[key]
          }
        }
        url = openUrl ? openUrl : `https://caps.runde.pro/rtc/v1/play/`;
        var data = {
          api: url,
          streamurl: _self.urlParams.url,
          clientip: null,
          sdp: offer.sdp
        };
        JSWebrtc.HttpPost(url, JSON.stringify(data)).then(function (res) {
		  if (res.code === 400) {
            _self.options.onFail()
          }
          resolve(res.sdp)
        }, function (rej) {
          reject(rej)
        })
      })
    }).then(function (answer) {
      return _self.pc.setRemoteDescription(new RTCSessionDescription({
        type: "answer",
        sdp: answer
      }))
    }).catch(function (reason) {
      throw reason
    });
    if (this.autoplay) {
      this.play()
    }
  };
  Player.prototype.play = function (ev) {
    if (this.animationId) {
      return
    }
    this.animationId = requestAnimationFrame(this.update.bind(this));
    this.paused = false
  };
  Player.prototype.pause = function (ev) {
    if (this.paused) {
      return
    }
    cancelAnimationFrame(this.animationId);
    this.animationId = null;
    this.isPlaying = false;
    this.paused = true;
    this.options.video.pause();
    if (this.options.onPause) {
      this.options.onPause(this)
    }
  };
  Player.prototype.stop = function (ev) {
    this.pause()
  };
  Player.prototype.destroy = function () {
    this.pause();
    this.pc && this.pc.close() && this.pc.destroy();
    this.audioOut && this.audioOut.destroy()
  };
  Player.prototype.update = function () {
    this.animationId = requestAnimationFrame(this.update.bind(this));
    if (this.options.video.readyState < 4) {
      return
    }
    if (!this.isPlaying) {
      this.isPlaying = true;
      this.options.video.play();
      if (this.options.onPlay) {
        this.options.onPlay(this)
      }
    }
  };
  return Player
}();
