import React, { useRef, useEffect, useState } from "react";
import vsSource from './glsl/timeline/vert.glsl';
import fsSource from './glsl/timeline/frag.glsl';

interface Uniforms {
    startDate: number;
    endDate: number;
    currentDate: number;
    radius: number;
    d: number;
    viewportSize: [number, number];
}

interface Instants {
    position: Float32Array;
    color: Float32Array;
}

interface Props extends React.HTMLAttributes<HTMLDivElement> {
    boxSize?: [number, number];
    startDate?: Date;
    endDate?: Date;
    currentDate?: Date;
    onDateChange?: (date: Date) => void;
    onPlay?: () => void;
    onPause?: () => void;
}

export const Timeline: React.FC<Props> = ({ startDate, endDate, currentDate, onDateChange, onPlay, onPause, boxSize = [4, 8], ...props }) => {

    const canvasRef = useRef<HTMLCanvasElement>(null);

    const vaoRef = useRef<WebGLVertexArrayObject | null>(null);
    const vertex_bfRef = useRef<WebGLBuffer | null>(null);
    const uniform_bfRef = useRef<WebGLBuffer | null>(null);
    const instants_bfRef = useRef<WebGLBuffer | null>(null);
    const programRef = useRef<WebGLProgram | null>(null);
    const instants_countRef = useRef<number>(0);

    const { radius, d } = calcVersicaUni(boxSize);
    console.log(radius, d);

    const current_uniforms = useRef<Uniforms>({
        startDate: 0,
        endDate: 0,
        currentDate: 0,
        radius: radius,
        d: d,
        viewportSize: [0, 0],
    })

    useEffect(() => {
        if (!canvasRef.current) return;
        const { radius, d } = calcVersicaUni(boxSize);
        const width = canvasRef.current.clientWidth;
        const height = canvasRef.current.clientHeight;

        // 设置canvas的实际像素尺寸
        canvasRef.current.width = width;
        canvasRef.current.height = height;

        console.log(`Canvas初始化: ${width}x${height}, vesica: r=${radius.toFixed(2)}, d=${d.toFixed(2)}`);

        current_uniforms.current.viewportSize = [width, height];
        current_uniforms.current.radius = radius;
        current_uniforms.current.d = d;


        const gl = (canvasRef.current.getContext('webgl2') as WebGL2RenderingContext);
        if (!gl) {
            console.error('WebGL2 not supported');
            return;
        }

        const program = createProgram(gl);
        if (!program) {
            console.error('Failed to create program');
            return;
        }

        // 绑定uniform buffer到着色器程序
        const uniformBlockIndex = gl.getUniformBlockIndex(program, 'Uniforms');
        if (uniformBlockIndex !== gl.INVALID_INDEX) {
            gl.uniformBlockBinding(program, uniformBlockIndex, 0);
        }

        const vao = gl.createVertexArray();

        if (!vao) {
            console.error('Failed to create vertex array');
            return;
        }
        gl.bindVertexArray(vao);

        const vertex_bf = defaultVb(gl);
        const instants_bf = defaultIb(gl);
        const uniform_bf = defaultUb(gl, current_uniforms.current);

        gl.bindVertexArray(null);
        gl.bindBuffer(gl.ARRAY_BUFFER, null);
        gl.bindBuffer(gl.UNIFORM_BUFFER, null);

        vaoRef.current = vao;
        vertex_bfRef.current = vertex_bf;
        uniform_bfRef.current = uniform_bf;
        instants_bfRef.current = instants_bf;
        programRef.current = program;
        instants_countRef.current = 15; // 设置实例数量（时间轴刻度）

        function render() {
            gl.clearColor(0.1, 0.1, 0.1, 1); // 深灰背景，便于看到刻度
            gl.clear(gl.COLOR_BUFFER_BIT);

            gl.useProgram(program);
            gl.bindVertexArray(vaoRef.current);

            // 绑定uniform buffer
            gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, uniform_bfRef.current);

            console.log(`绘制实例数量: ${instants_countRef.current}`);
            gl.drawArraysInstanced(gl.TRIANGLE_STRIP, 0, 4, instants_countRef.current);
            gl.bindVertexArray(null);
        }

        function updateUniforms(gl: WebGL2RenderingContext, uniforms: Uniforms) {
            gl.bindBuffer(gl.UNIFORM_BUFFER, uniform_bfRef.current!);
            const uniformData = new Float32Array([
                uniforms.startDate,
                uniforms.endDate,
                uniforms.currentDate,
                uniforms.radius,
                uniforms.d,
                0.0,  // padding1 - 填充以对齐vec2到8字节边界
                uniforms.viewportSize[0],
                uniforms.viewportSize[1]
            ]);
            gl.bufferData(gl.UNIFORM_BUFFER, uniformData, gl.DYNAMIC_DRAW);
        }

        function updateInstants(instants: Instants[]) {
            gl.bindBuffer(gl.ARRAY_BUFFER, instants_bfRef.current!);

            // 使用明确的数组顺序确保内存布局正确
            const instantsData = new Float32Array(instants.length * 6); // 每个实例6个float (2个position + 4个color)

            for (let i = 0; i < instants.length; i++) {
                const offset = i * 6;
                const instant = instants[i];

                // position (2个float)
                instantsData[offset + 0] = instant.position[0];
                instantsData[offset + 1] = instant.position[1];

                // color (4个float)
                instantsData[offset + 2] = instant.color[0];
                instantsData[offset + 3] = instant.color[1];
                instantsData[offset + 4] = instant.color[2];
                instantsData[offset + 5] = instant.color[3];
            }

            gl.bufferData(gl.ARRAY_BUFFER, instantsData, gl.DYNAMIC_DRAW);
            instants_countRef.current = instants.length;
            render(); // 更新后重新渲染
        }

        // TODO: 可以通过props传入自定义的时间轴刻度数据
        // 或使用useImperativeHandle暴露更新方法

        gl.viewport(0, 0, width, height);
        render();

        const handleMove = (e: MouseEvent) => {
            const rect = canvasRef.current?.getBoundingClientRect();
            if (!rect) return;
            const px = e.clientX - rect.left;
            const py = e.clientY - rect.top;
            console.log(px, py);
        }

        canvasRef.current?.addEventListener('mousemove', handleMove);

        // 使用ResizeObserver监听canvas尺寸变化
        const resizeObserver = new ResizeObserver((entries) => {
            for (const entry of entries) {
                const { width: new_width, height: new_height } = entry.contentRect;

                // 更新canvas的实际像素尺寸
                canvasRef.current!.width = new_width;
                canvasRef.current!.height = new_height;

                current_uniforms.current.viewportSize = [new_width, new_height];

                updateUniforms(gl, current_uniforms.current);
                gl.viewport(0, 0, new_width, new_height);
                render();
            }
        });

        resizeObserver.observe(canvasRef.current!);

        return () => {
            // 移除事件监听器
            canvasRef.current?.removeEventListener('mousemove', handleMove);
            resizeObserver.disconnect();

            // 清理WebGL资源
            if (vaoRef.current) gl.deleteVertexArray(vaoRef.current);
            if (vertex_bfRef.current) gl.deleteBuffer(vertex_bfRef.current);
            if (uniform_bfRef.current) gl.deleteBuffer(uniform_bfRef.current);
            if (instants_bfRef.current) gl.deleteBuffer(instants_bfRef.current);
            if (programRef.current) gl.deleteProgram(programRef.current);
        }
    }, [boxSize])

    return (
        <div {...props}>
            <canvas ref={canvasRef} className="w-full h-full" />
        </div>
    );
}

function createProgram(gl: WebGL2RenderingContext) {
    const [vs, fs] = createShader(gl)!;
    const prog = gl.createProgram();

    gl.attachShader(prog, vs);
    gl.attachShader(prog, fs);
    gl.linkProgram(prog);

    if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) {
        console.error('Failed to link program');
        console.error(gl.getProgramInfoLog(prog));
        // 清理着色器对象
        gl.deleteShader(vs);
        gl.deleteShader(fs);
        return null;
    }

    // 程序链接成功后，删除着色器对象以释放内存
    gl.deleteShader(vs);
    gl.deleteShader(fs);

    return prog;
}

function createShader(gl: WebGL2RenderingContext) {

    const vs = gl.createShader(gl.VERTEX_SHADER);
    if (!vs) {
        console.error('Failed to create vertex shader');
        return null;
    }
    gl.shaderSource(vs, vsSource);
    gl.compileShader(vs);

    if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {
        console.error('Failed to compile vertex shader:', gl.getShaderInfoLog(vs));
        gl.deleteShader(vs);
        return null;
    }

    const fs = gl.createShader(gl.FRAGMENT_SHADER);
    if (!fs) {
        console.error('Failed to create fragment shader');
        gl.deleteShader(vs);
        return null;
    }
    gl.shaderSource(fs, fsSource);
    gl.compileShader(fs);

    if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {
        console.error('Failed to compile fragment shader:', gl.getShaderInfoLog(fs));
        gl.deleteShader(vs);
        gl.deleteShader(fs);
        return null;
    }

    return [vs, fs] as [WebGLShader, WebGLShader];
}

function defaultVb(gl: WebGL2RenderingContext) {

    const plane = new Float32Array([
        -1, -1,
        -1, 1,
        1, -1,
        1, 1,
    ]);

    const vertex_bf = gl.createBuffer()!;

    gl.bindBuffer(gl.ARRAY_BUFFER, vertex_bf);
    gl.bufferData(gl.ARRAY_BUFFER, plane, gl.STATIC_DRAW);

    gl.enableVertexAttribArray(0);
    gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
    gl.vertexAttribDivisor(0, 0)

    return vertex_bf;
}

function defaultUb(gl: WebGL2RenderingContext, uniforms: Uniforms) {
    const ub = gl.createBuffer()!;
    gl.bindBuffer(gl.UNIFORM_BUFFER, ub);

    // std140布局：需要添加填充以正确对齐vec2
    const uniformData = new Float32Array([
        uniforms.startDate,
        uniforms.endDate,
        uniforms.currentDate,
        uniforms.radius,
        uniforms.d,
        0.0,  // padding1 - 填充以对齐vec2到8字节边界
        uniforms.viewportSize[0],
        uniforms.viewportSize[1]
    ]);

    gl.bufferData(gl.UNIFORM_BUFFER, uniformData, gl.DYNAMIC_DRAW);
    return ub;
}

// 时间轴刻度生成函数
function generateTimelineMarks(startX: number, y: number, interval: number, count: number): Instants[] {
    const marks = [];
    for (let i = 0; i < count; i++) {
        marks.push({
            position: new Float32Array([startX + i * interval, y]),
            color: new Float32Array([0.8, 0.8, 0.8, 1])  // 统一的灰色刻度
        });
    }
    return marks;
}

function defaultIb(gl: WebGL2RenderingContext, canvasWidth: number, canvasHeight: number) {

    // 时间轴刻度：根据canvas尺寸调整位置
    const startX = 20; // 左边距
    const centerY = Math.floor(canvasHeight * 0.5); // 垂直居中
    const interval = 12; // 刻度间距（比vesica宽度大）
    const maxCount = Math.floor((canvasWidth - startX - 20) / interval); // 根据宽度计算数量
    const count = Math.min(maxCount, 20); // 最多20个刻度

    console.log(`生成刻度: 起始=${startX}, Y=${centerY}, 间距=${interval}, 数量=${count}`);
    const instants: Instants[] = generateTimelineMarks(startX, centerY, interval, count);

    const instants_bf = gl.createBuffer()!;

    gl.bindBuffer(gl.ARRAY_BUFFER, instants_bf);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(instants.flatMap(i => [...i.position, ...i.color])), gl.DYNAMIC_DRAW);

    gl.enableVertexAttribArray(1);
    gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 24, 0); // 6 floats * 4 bytes = 24 bytes stride
    gl.vertexAttribDivisor(1, 1);

    gl.enableVertexAttribArray(2);
    gl.vertexAttribPointer(2, 4, gl.FLOAT, false, 24, 8); // 2 floats * 4 bytes = 8 bytes offset
    gl.vertexAttribDivisor(2, 1);

    return instants_bf;
}

function calcVersicaUni(box_size: [number, number]) {
    const [w, h] = [box_size[0], box_size[1]];

    // 正确的vesica参数：
    // radius: 每个圆的半径，应该稍大于高度的一半以包含整个形状
    // d: 两个圆心之间的距离，必须 < 2*radius
    const radius = Math.max(w * 0.6, h * 0.6); // 确保能包含形状
    const d = Math.min(w * 0.4, radius * 1.5);  // 确保 d < 2*radius

    console.log(`vesica参数: w=${w}, h=${h}, radius=${radius.toFixed(2)}, d=${d.toFixed(2)}`);
    console.log(`验证: d < 2*radius? ${d} < ${2 * radius} = ${d < 2 * radius}`);
    console.log(`验证: r²-d² = ${radius * radius} - ${d * d} = ${radius * radius - d * d}`);

    return {
        radius,
        d,
    }
}