/**
 * GLSL shaders for pendulum rendering on WebGL.
 * Replicates the visual output of the WGSL pendulum compute+fragment shaders.
 * Uses a feedback texture (ping-pong) for trail persistence.
 *
 * Coordinate note: WGSL pixel buffer has Y=0 at top (screen space).
 * GLSL UVs have Y=0 at bottom. We flip Y via (1.0 - uv.y) to match.
 */

export const PENDULUM_VERTEX_SHADER_GLSL = `
    precision highp float;

    attribute vec3 position;
    attribute vec2 uv;

    varying vec2 vUV;

    void main() {
        vUV = uv;
        gl_Position = vec4(position, 1.0);
    }
`;

/**
 * Shader for the feedback pass: renders pendulum state to a render target texture.
 * The R channel stores trail1 intensity, G stores trail2 intensity.
 */
export const PENDULUM_FEEDBACK_FRAGMENT_GLSL = `
    precision highp float;

    uniform vec2 resolution;
    uniform float theta1;
    uniform float theta2;
    uniform float l1;
    uniform float l2;
    uniform float trailDecay;
    uniform sampler2D previousFrame;

    varying vec2 vUV;

    void main() {
        // Flip Y to match WGSL screen-space (Y=0 at top)
        vec2 uv = vec2(vUV.x, 1.0 - vUV.y);
        float aspect = resolution.x / resolution.y;
        vec2 uvCorrected = vec2(uv.x * aspect, uv.y);

        vec4 prev = texture2D(previousFrame, vUV);
        float trail1 = prev.r * trailDecay;
        float trail2 = prev.g * trailDecay;

        vec2 origin = vec2(0.5 * aspect, 0.3);
        float displayScale = 0.15;

        vec2 p1 = origin + vec2(sin(theta1), cos(theta1)) * l1 * displayScale;
        vec2 p2 = p1 + vec2(sin(theta2), cos(theta2)) * l2 * displayScale;

        float dMass1 = length(uvCorrected - p1);
        float dMass2 = length(uvCorrected - p2);

        if (dMass1 < 0.02) {
            trail1 = 1.0;
        }
        if (dMass2 < 0.02) {
            trail2 = 1.0;
        }

        gl_FragColor = vec4(trail1, trail2, 0.0, 1.0);
    }
`;

/**
 * Display shader: reads trail data from feedback texture and renders final colors.
 */
export const PENDULUM_DISPLAY_FRAGMENT_GLSL = `
    precision highp float;

    uniform vec2 resolution;
    uniform float theta1;
    uniform float theta2;
    uniform float l1;
    uniform float l2;
    uniform sampler2D trailTexture;

    varying vec2 vUV;

    float sdSegment(vec2 p, vec2 a, vec2 b) {
        vec2 pa = p - a;
        vec2 ba = b - a;
        float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
        return length(pa - ba * h);
    }

    void main() {
        // Flip Y to match WGSL screen-space (Y=0 at top)
        vec2 uv = vec2(vUV.x, 1.0 - vUV.y);
        float aspect = resolution.x / resolution.y;
        vec2 uvCorrected = vec2(uv.x * aspect, uv.y);

        vec4 trailData = texture2D(trailTexture, vUV);
        float trail1 = trailData.r;
        float trail2 = trailData.g;

        vec2 origin = vec2(0.5 * aspect, 0.3);
        float displayScale = 0.15;

        vec2 p1 = origin + vec2(sin(theta1), cos(theta1)) * l1 * displayScale;
        vec2 p2 = p1 + vec2(sin(theta2), cos(theta2)) * l2 * displayScale;

        float dLine1 = sdSegment(uvCorrected, origin, p1);
        float dLine2 = sdSegment(uvCorrected, p1, p2);
        float dMass1 = length(uvCorrected - p1);
        float dMass2 = length(uvCorrected - p2);

        vec3 bgColor = vec3(0.1, 0.1, 0.15);
        vec3 mass1Color = vec3(1.0, 0.0, 0.0);
        vec3 mass2Color = vec3(0.0, 1.0, 0.0);
        vec3 line1Color = vec3(1.0, 1.0, 0.0);
        vec3 line2Color = vec3(1.0, 0.0, 1.0);

        vec3 finalColor = bgColor;
        finalColor = mix(finalColor, mass1Color, clamp(trail1, 0.0, 1.0));
        finalColor = mix(finalColor, mass2Color, clamp(trail2, 0.0, 1.0));

        if (dMass1 >= 0.02 && dMass2 >= 0.02) {
            if (dLine1 < 0.003) {
                finalColor = line1Color;
            } else if (dLine2 < 0.003) {
                finalColor = line2Color;
            }
        }

        gl_FragColor = vec4(finalColor, 1.0);
    }
`;
