import { fillRectangle, Rect } from "../base/2d";
import { m4 } from "../base/m4";
import { createProgram, createShader } from "../base/utils";
import { Area, AreaGroup, Color, Data } from "./common";





export function createColored(
  gl: WebGLRenderingContext,
  mapTexture: WebGLTexture,
  data: Data,
  width: number,
  height: number,
): WebGLTexture {


  const vertexShaderCode = /*glsl*/ `
      attribute vec2 a_position;
      attribute vec2 a_texCoord;
      attribute vec4 a_color;
      attribute vec4 a_destColor;
      uniform mat4 u_matrix;
      varying vec2 v_texCoord;
      varying vec4 v_color;
      varying vec4 v_destColor;

      void main() {
        gl_Position = u_matrix * vec4(a_position, 0, 1);
        v_texCoord = a_texCoord;
        v_color = a_color;
        v_destColor = a_destColor;
      }

    `;

  const fragmentShaderCode = /*glsl*/ `
      precision mediump float;
      uniform sampler2D u_image;
      //uniform vec4 u_color;
      varying vec2 v_texCoord;
      varying vec4 v_color;
      varying vec4 v_destColor;

      void main() {
        vec4 color = texture2D(u_image, v_texCoord);
        float dist = distance(color, v_color);
        if(dist < 0.001) {
          gl_FragColor = v_destColor;
        }else{
          gl_FragColor = vec4(0,0,0,0);
        }
      }

    `


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


  const target = gl.createTexture()
  gl.bindTexture(gl.TEXTURE_2D, target)
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null)

  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);


  const fb = gl.createFramebuffer()
  gl.bindFramebuffer(gl.FRAMEBUFFER, fb)
  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, target, 0)


  let aPositionLoc = gl.getAttribLocation(program, "a_position")
  let aTexCoordLoc = gl.getAttribLocation(program, "a_texCoord")
  let aColorIdLoc = gl.getAttribLocation(program, "a_color")
  let aDestColorLoc = gl.getAttribLocation(program, "a_destColor")
  let uMatrixLoc = gl.getUniformLocation(program, "u_matrix")


  const count = data.areaCount
  const vertexArray = new Float32Array(12 * count)
  const texCoordArray = new Float32Array(12 * count)
  const colorIdArray = new Float32Array(24 * count)
  const destColorArray = new Float32Array(24 * count)

  var vertexOffset = 0
  var colorOffset = 0

  for (var i = 0; i < data.areaGroups.length; i++) {
    var group = data.areaGroups[i]
    var destColor = new Color(group.color)
    for (var j = 0; j < group.areas.length; j++) {
      var area = group.areas[j]
      fillRectangle(vertexArray, vertexOffset, area.rect.x, area.rect.y, area.rect.width, area.rect.height)
      fillRectangle(texCoordArray, vertexOffset, area.rect.x / width, area.rect.y / height, area.rect.width / width, area.rect.height / height)
      var colorId = new Color(area.id)
      colorId.fillFloatArray(colorIdArray, colorOffset, 6)
      destColor.fillFloatArray(destColorArray, colorOffset, 6)
      vertexOffset += 12
      colorOffset += 24
    }
  }




  gl.useProgram(program)


  let colorsBuffer = gl.createBuffer()
  gl.bindBuffer(gl.ARRAY_BUFFER, colorsBuffer)
  gl.bufferData(gl.ARRAY_BUFFER, colorIdArray, gl.STATIC_DRAW)
  gl.enableVertexAttribArray(aColorIdLoc)
  gl.vertexAttribPointer(aColorIdLoc, 4, gl.FLOAT, false, 0, 0);

  let destColorsBuffer = gl.createBuffer()
  gl.bindBuffer(gl.ARRAY_BUFFER, destColorsBuffer)
  gl.bufferData(gl.ARRAY_BUFFER, destColorArray, gl.STATIC_DRAW)
  gl.enableVertexAttribArray(aDestColorLoc)
  gl.vertexAttribPointer(aDestColorLoc, 4, gl.FLOAT, false, 0, 0)

  let vertexBuffer = gl.createBuffer()
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
  gl.bufferData(gl.ARRAY_BUFFER, vertexArray, gl.STATIC_DRAW)
  gl.enableVertexAttribArray(aPositionLoc)
  gl.vertexAttribPointer(aPositionLoc, 2, gl.FLOAT, false, 0, 0)

  let textureBuffer = gl.createBuffer()
  gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer)
  gl.bufferData(gl.ARRAY_BUFFER, texCoordArray, gl.STATIC_DRAW)
  gl.enableVertexAttribArray(aTexCoordLoc)
  gl.vertexAttribPointer(aTexCoordLoc, 2, gl.FLOAT, false, 0, 0)


  gl.viewport(0, 0, width, height)
  gl.uniformMatrix4fv(uMatrixLoc, false, m4.projectionNoflipY(width, height))

  gl.activeTexture(gl.TEXTURE0)
  gl.bindTexture(gl.TEXTURE_2D, mapTexture)


  gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
  gl.enable(gl.BLEND);
  gl.disable(gl.DEPTH_TEST);

  gl.drawArrays(gl.TRIANGLES, 0, vertexArray.length / 2)

  gl.disableVertexAttribArray(aColorIdLoc)
  gl.disableVertexAttribArray(aTexCoordLoc)
  gl.disableVertexAttribArray(aPositionLoc)
  gl.disableVertexAttribArray(aDestColorLoc)

  gl.deleteBuffer(vertexBuffer)
  gl.deleteBuffer(textureBuffer)
  gl.deleteBuffer(colorsBuffer)
  gl.deleteBuffer(destColorsBuffer)

  gl.bindFramebuffer(gl.FRAMEBUFFER, null)

  gl.deleteFramebuffer(fb)


  return target!
}
