import { Color } from "../filler/common";
import { LayerAB, Scene } from "./Scene";
import { createProgram, createShader } from "./utils";

export class FrameLayer extends LayerAB {
  private vertexShaderCode = /*glsl*/ `
    attribute vec2 a_position;
    uniform mat4 u_matrix;

    void main() {
      gl_Position = u_matrix * vec4(a_position, 0, 1);
    }
  `;

  private fragmentShaderCode = /*glsl*/ `
    precision mediump float;
    uniform vec4 u_color;

    void main() {
      gl_FragColor = u_color;
    }
  `;

  program: WebGLProgram;

  aPositionLoc: number;
  uMatrixLoc: WebGLUniformLocation;
  uColorLoc: WebGLUniformLocation;

  vertexBuffer: WebGLBuffer;

  vertexArray: Float32Array;

  colorArray: Float32Array;

  constructor(
    private scene: Scene,
    private x: number,
    private y: number,
    private width: number,
    private height: number,
    private color: number = 0xffff0000,
    private lineWidth: number = 30
  ) {
    super();

    const gl = scene.gl;

    this.program = createProgram(
      gl,
      createShader(gl, gl.VERTEX_SHADER, this.vertexShaderCode)!,
      createShader(gl, gl.FRAGMENT_SHADER, this.fragmentShaderCode)!
    )!;

    this.aPositionLoc = gl.getAttribLocation(this.program, "a_position");
    this.uMatrixLoc = gl.getUniformLocation(this.program, "u_matrix")!;
    this.uColorLoc = gl.getUniformLocation(this.program, "u_color")!;

    this.vertexArray = this.generateThickBorderVertices(x, y, width, height, lineWidth);

    this.vertexBuffer = gl.createBuffer()!;
    gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, this.vertexArray, gl.STATIC_DRAW);

    this.colorArray = new Color(color).toFloatArray();
  }

  private generateThickBorderVertices(x: number, y: number, width: number, height: number, lineWidth: number): Float32Array {
    const halfLineWidth = lineWidth / 2;
    return new Float32Array([
      // 上边框
      x - halfLineWidth, y - halfLineWidth,
      x + width + halfLineWidth, y - halfLineWidth,
      x - halfLineWidth, y + halfLineWidth,
      x + width + halfLineWidth, y + halfLineWidth,

      // 右边框
      x + width - halfLineWidth, y - halfLineWidth,
      x + width + halfLineWidth, y - halfLineWidth,
      x + width - halfLineWidth, y + height + halfLineWidth,
      x + width + halfLineWidth, y + height + halfLineWidth,

      // 下边框
      x + width + halfLineWidth, y + height - halfLineWidth,
      x - halfLineWidth, y + height - halfLineWidth,
      x + width + halfLineWidth, y + height + halfLineWidth,
      x - halfLineWidth, y + height + halfLineWidth,

      // 左边框
      x + halfLineWidth, y + height,
      x - halfLineWidth, y + height,
      x + halfLineWidth, y,
      x - halfLineWidth, y,
    ]);
  }

  override draw() {
    const gl = this.scene.gl;
    gl.useProgram(this.program);

    gl.enableVertexAttribArray(this.aPositionLoc);

    gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);

    gl.vertexAttribPointer(this.aPositionLoc, 2, gl.FLOAT, false, 0, 0);

    gl.uniformMatrix4fv(this.uMatrixLoc, false, this.scene.drawMatrix);
    gl.uniform4fv(this.uColorLoc, this.colorArray);

    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 16);
  }
}