import { DEFAULT_MASK_COLOR } from '../constants'
import { getWebGLContext, initShaders } from '../libs/cuon-utils'
import { GLColor } from '../types/mattingDrawing'

const VSHADER_SOURCE = `
attribute vec4 a_Position;
attribute vec2 a_TexCoord;
varying vec2 v_TexCoord;
void main() {
    gl_Position = a_Position;
    v_TexCoord = a_TexCoord;
}
`
const FSHADER_SOURCE = `
precision highp float;
uniform sampler2D u_Sampler;
uniform vec4 u_MaskColor;
varying vec2 v_TexCoord;
void main() {
    vec4 color = texture2D(u_Sampler, v_TexCoord);
		vec3 mixRGB = color.a > 0.0 ? mix(color.rgb, u_MaskColor.rgb, u_MaskColor.a) : color.rgb;
    gl_FragColor = vec4(mixRGB, color.a);
}
`

export function initMaskRenderer(cvs: HTMLCanvasElement, maskColor: GLColor = DEFAULT_MASK_COLOR) {
  const gl = getWebGLContext(cvs)
  if (!gl) {
    return console.error('获取WebGL绘制上下文失败!')
  }
  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    return console.error('着色器初始化失败!')
  }

  if (!initBuffers(gl)) {
    return console.error('缓冲区初始化失败!')
  }

  initUniform(gl, 'u_MaskColor', maskColor)

  return (image: TexImageSource) => {
    console.time('draw mask image')
    if (!initTexture(gl, image)) {
      return console.error('纹理初始化失败!')
    }
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)
    console.timeEnd('draw mask image')
  }
}

function initUniform(gl: WebGLRenderingContext, location: string, val: number | GLColor) {
  const u_Location = gl.getUniformLocation(gl.program, location)
  if (!u_Location) {
    return console.error('获取attribute变量存储位置失败!')
  }
  if (Array.isArray(val)) {
    gl.uniform4fv(u_Location, val)
  } else {
    gl.uniform1i(u_Location, val)
  }
}

function initBuffers(gl: WebGLRenderingContext) {
  const aPosition = gl.getAttribLocation(gl.program, 'a_Position')
  const aTexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord')
  if (!~aPosition || !~aTexCoord) {
    console.error('获取attribute变量存储位置失败!')
    return false
  }
  const verticesBuffer = gl.createBuffer()
  const coordsBuffer = gl.createBuffer()
  if (!verticesBuffer || !coordsBuffer) {
    console.error('创建缓冲区对象失败!')
    return false
  }
  bindArrayBuffer(gl, verticesBuffer, aPosition, new Float32Array([-1, 1, 1, 1, -1, -1, 1, -1]))
  bindArrayBuffer(gl, coordsBuffer, aTexCoord, new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]))
  return true
}

function bindArrayBuffer(gl: WebGLRenderingContext, buffer: WebGLBuffer, attrib: number, data: Float32Array, pointNum = 2) {
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
  gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW)
  gl.vertexAttribPointer(attrib, pointNum, gl.FLOAT, false, 0, 0)
  gl.enableVertexAttribArray(attrib)
}

function initTexture(gl: WebGLRenderingContext, image: TexImageSource) {
  const texture = gl.createTexture()
  if (!texture) {
    console.error('创建纹理对象失败!')
    return false
  }

  const u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler')
  if (!u_Sampler) {
    console.error('获取取样器变量存储位置失败!')
    return false
  }
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1)
  gl.activeTexture(gl.TEXTURE0)
  gl.bindTexture(gl.TEXTURE_2D, texture)
  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)
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image)
  gl.uniform1i(u_Sampler, 0)
  return true
}
