const VSHADER_SOURCE = `attribute vec4 a_Position;
    attribute vec2 a_TexCoord;
    uniform mat4 translation;
    varying vec2 v_TexCoord;
    void main() {
        gl_Position = translation * a_Position;
        v_TexCoord = a_TexCoord;
    }`;

const FSHADER_SOURCE = `precision mediump float;
    uniform sampler2D u_Sampler;
    varying vec2 v_TexCoord;
    void main() {
        gl_FragColor = texture2D(u_Sampler, v_TexCoord);
    }`;

let imgData = null;
let mtrData = null;
let gl = null;

function init(output) {
    var canvas = document.createElement('canvas');
    canvas.width = output.width;
    canvas.height = output.height;

    gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
    // 初始化之前先加载图片
    if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
        return;
    }
}
function main(opt) {
    const {
        imageData,
        mtr,
        output,
        input
    } = opt;

    mtrData = mtr;
    imgData = imageData;

    gl.clearColor(0, 0, 0, 1);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    const n = initVertexBuffers(gl);
    initTextures(gl, n, 0);
    let outputData = new Uint8Array(output.width * output.height * 4);
    gl.readPixels(0, 0, output.width, output.height, gl.RGBA, gl.UNSIGNED_BYTE, outputData);
    return outputData;
}

function initVertexBuffers(gl) {
    // 顶点坐标和纹理图像坐标
    const vertices = new Float32Array([
        // webgl坐标，纹理坐标
        -1.0, 1.0, 0.0, 0.0, 1.0,
        -1.0, -1.0, 0.0, 0.0, 0.0,
        1.0, 1.0, 0.0, 1.0, 1.0,
        1.0, -1.0, 0.0, 1.0, 0.0
    ]);

    const FSIZE = vertices.BYTES_PER_ELEMENT;

    const vertexBuffer = gl.createBuffer();

    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

    const aPosition = gl.getAttribLocation(gl.program, 'a_Position');
    const aTexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');

    var xformMatrix = new Float32Array([
        mtrData[0][0], mtrData[1][0], 0.0, 0.0,
        mtrData[0][1], mtrData[1][1], 0.0, 0.0,
        0.0, 0.0, 0.0, 1.0,
        mtrData[0][2], mtrData[1][2], 0.0, 1.0

    ]);


    var translation = gl.getUniformLocation(gl.program, 'translation');
    gl.uniformMatrix4fv(translation, false, xformMatrix);

    gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, FSIZE * 5, 0);
    gl.enableVertexAttribArray(aPosition);

    gl.vertexAttribPointer(aTexCoord, 2, gl.FLOAT, false, FSIZE * 5, FSIZE * 3);
    gl.enableVertexAttribArray(aTexCoord);

    return 4;
}


function initTextures(gl, n, index) {
    // 创建纹理对象
    const texture = gl.createTexture();
    const uSampler = gl.getUniformLocation(gl.program, 'u_Sampler');

    // WebGL纹理坐标中的纵轴方向和PNG，JPG等图片容器的Y轴方向是反的，所以先反转Y轴
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);

    // 激活纹理单元，开启index号纹理单元
    gl.activeTexture(gl[`TEXTURE${index}`]);

    // 绑定纹理对象
    gl.bindTexture(gl.TEXTURE_2D, texture);

    // 配置纹理对象的参数
    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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

    // 将纹理图像分配给纹理对象
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imgData);

    // 将纹理单元编号传给着色器
    gl.uniform1i(uSampler, index);

    // 绘制
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
    return;
}

function initShaders(gl, vshader, fshader) {
    var vertexShader = createShader(gl, vshader, gl.VERTEX_SHADER);
    var fragmentShader = createShader(gl, fshader, gl.FRAGMENT_SHADER);

    var program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);

    if (!program) {
        console.log('无法创建程序对象');
        return false;
    }
    gl.linkProgram(program);
    gl.useProgram(program);
    gl.program = program;

    return true;
}

function createShader(gl, sourceCode, type) {
    // Compiles either a shader of type gl.VERTEX_SHADER or gl.FRAGMENT_SHADER
    var shader = gl.createShader(type);
    gl.shaderSource(shader, sourceCode);
    gl.compileShader(shader);

    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        var info = gl.getShaderInfoLog(shader);
        throw 'Could not compile WebGL program. \n\n' + info;
    }
    return shader;
}

export default {
    main,
    init
};
