import LoopElement from "./LoopElement.js";
import Ticker from "../utils/Ticker.js";
import GLMesh from "../gl/GLMesh.js";
import GLProgram from "../gl/GLProgram.js";
import GLTexture from "../gl/GLTexture.js";

(() => {
  let style = document.createElement("style");
  style.textContent = `
    dlib-webglvideo {
      display: block;
      position: relative;
    }
  `;
  document.head.appendChild(style);
})();

export default class WebGLVideoElement extends LoopElement {
  constructor() {
    super({
      autoplay: false
    });

    this._resizeBinded = this.resize.bind(this);

    this._video = document.createElement("video");
    this._video.setAttribute("playsinline", "true");
    this._canvas = document.createElement("canvas");
    this._canvas.style.width = "100%";
    this.appendChild(this._canvas);
    this.gl = this._canvas.getContext("webgl", {
      premultipliedAlpha: false
    });

    this._mesh = new GLMesh({
      gl: this.gl,
      attributes: [
        ["position", {
          data: new Float32Array([
            -1, -1,
            -1, 1,
            1, -1,
            1, 1
          ]),
          size: 2
        }],
        ["uv", {
          data: new Float32Array([
            0, 1,
            0, 0,
            1, 1,
            1, 0
          ]),
          size: 2
        }]
      ]
    });

    this._videoTexture = new GLTexture({
      gl: this.gl
    });
    this._videoTexture.minFilter = this.gl.LINEAR;
    this._videoTexture.wrapS = this._videoTexture.wrapT = this.gl.CLAMP_TO_EDGE;

    this.program = new GLProgram({
      gl: this.gl,
      uniforms: [
        ["video", this._videoTexture]
      ],
      vertexShader: `
        attribute vec2 position;
        attribute vec2 uv;
        varying vec2 vUv;

        void main() {
          gl_Position = vec4(position, 0., 1.);
          vUv = uv;
        }
      `,
      fragmentShader: `
        precision highp float;

        uniform sampler2D video;
        varying vec2 vUv;

        void main() {
          gl_FragColor = texture2D(video, vUv);
        }
      `
    });
    this.program.use();

    this.program.attributes.set(this._mesh.attributes);

    this.src = this.getAttribute("src");
  }

  connectedCallback() {
    super.connectedCallback();
    window.addEventListener("resize", this._resizeBinded);
  }

  disconnectedCallback() {
    super.disconnectedCallback();
    window.removeEventListener("resize", this._resizeBinded);
  }

  update() {
    this.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight);
    this.gl.clearColor(0, 0, 0, 1);
    this.gl.clear(this.gl.COLOR_BUFFER_BIT);
    this._videoTexture.source = this._video;
    this._mesh.draw({
      mode: this.gl.TRIANGLE_STRIP,
      count: 4
    });
  }

  resize() {
    this._canvas.style.height = `${this._canvas.offsetWidth * this._video.videoHeight / this._video.videoWidth}px`;
    this._canvas.width = Math.min(this._video.videoWidth, this.offsetWidth * window.devicePixelRatio);
    this._canvas.height = Math.min(this._video.videoHeight, this.offsetHeight * window.devicePixelRatio);
  }

  get src() {
    return this._video.src;
  }

  set src(value) {
    this._video.src = value;

    const resizeCanvas = () => {
      this._video.removeEventListener("loadedmetadata", resizeCanvas);
      this.resize();
    }

    this._video.addEventListener("loadedmetadata", resizeCanvas);

    this._video.addEventListener("playing", () => {
      super.play();
    });

    this._video.addEventListener("pause", () => {
      super.pause();
    });
  }

  play() {
    this._video.play();
  }

  pause() {
    this._video.pause();
  }

  set currentTime(value) {
    this._video.currentTime = value;
    this.update();
  }

  get currentTime() {
    return this._video.currentTime;
  }

  set loop(value) {
    this._video.loop = value;
  }

  get loop() {
    return this._video.loop;
  }

  get duration() {
    return this._video.duration;
  }
}

window.customElements.define("dlib-webglvideo", WebGLVideoElement);

@@ -517,24 +517,48 @@
 oplay: false
+,%0A      background: true
 %0A    %7D);%0A%0A  
@@ -2371,32 +2371,94 @@
 tedCallback() %7B%0A
+    this.gl.getExtension(%22WEBGL_lose_context%22).loseContext();%0A
     super.discon
@@ -2467,32 +2467,32 @@
 ctedCallback();%0A
-
     window.remov
@@ -2869,124 +2869,8 @@
 ) %7B%0A
-    this._canvas.style.height = %60$%7Bthis._canvas.offsetWidth * this._video.videoHeight / this._video.videoWidth%7Dpx%60;%0A
     
@@ -2890,25 +2890,16 @@
 width = 
-Math.min(
 this._vi
@@ -2916,53 +2916,8 @@
 idth
-, this.offsetWidth * window.devicePixelRatio)
 ;%0A  
@@ -2944,17 +2944,8 @@
 t = 
-Math.min(
 this
@@ -2967,54 +2967,8 @@
 ight
-, this.offsetHeight * window.devicePixelRatio)
 ;%0A  
@@ -3508,24 +3508,182 @@
 use();%0A  %7D%0A%0A
+  addEventListener() %7B%0A    this._video.addEventListener(...arguments);%0A  %7D%0A%0A  removeEventListener() %7B%0A    this._video.removeEventListener(...arguments);%0A  %7D%0A%0A
   set curren
@@ -3887,24 +3887,24 @@
 et loop() %7B%0A
-
     return t
@@ -3921,24 +3921,205 @@
 .loop;%0A  %7D%0A%0A
+  set autoplay(value) %7B%0A    this._video.autoplay = value;%0A  %7D%0A%0A  get autoplay() %7B%0A    return this._video.autoplay;%0A  %7D%0A%0A  get readyState() %7B%0A    return this._video.readyState;%0A  %7D%0A%0A
   get durati

add more video parameters to WebGLVideoElement