#include "metalShaderTypes.h"
#include "alpha.h"
#include "textAnimationHelper.h"

typedef struct
{
    int direction;
    float blurBias;
    float easeInOut;
    float motionRamp;
    float motionSpeed;
} fxVars;

vertex vertexOut vertexFunc(uint vertexID [[ vertex_id ]],const device txShaderVers* in[[ buffer(0) ]],constant txShaderUniforms& uniforms[[ buffer(3) ]],constant fxVars& vars[[ buffer(2)]])
{
    vertexOut out;

    out.normPos=in[vertexID].pos.xy;

    vec4 tmpPos=vec4(in[vertexID].pos.xyz,1.0)*uniforms.worldViewProj;

    if(uniforms.transitionState==0)
    {
        out.mixValue.x = uniforms.transitionProgress;
    }
    else if(uniforms.transitionState==2)
    {
        out.mixValue.x = 1.0 - uniforms.transitionProgress;
    }

    tmpPos = handleContinuedMotion(tmpPos, uniforms.localTime, vars.motionRamp, vars.motionSpeed);

    out.position = tmpPos;

    out.tex1=in[vertexID].tex1;
    out.tex2=in[vertexID].tex2;
    out.texMask=in[vertexID].texMask;
    return out;
}

fragment float4 fragmentFunc(vertexOut input [[stage_in]]
                             ,texture2d<half> inputTex0 [[ texture(0) ]]
                             ,texture2d<half> inputTex1 [[ texture(1) ]]
                             ,texture2d<half> inputTexMask [[ texture(2) ]]
                             ,texture2d<half> blur1 [[ texture(3) ]]
                             ,texture2d<half> blur2 [[ texture(4) ]]
                             ,texture2d<half> blur3 [[ texture(5) ]]
                             ,texture2d<half> blur4 [[ texture(6) ]]
                             ,texture2d<half> blur5 [[ texture(7) ]]
                             ,texture2d<half> blur6 [[ texture(8) ]]
#ifdef IS_MEDIA_FILL
                             ,texture2d<half> blur1Alt [[ texture(9) ]]
                             ,texture2d<half> blur2Alt [[ texture(10) ]]
                             ,texture2d<half> blur3Alt [[ texture(11) ]]
                             ,texture2d<half> blur4Alt [[ texture(12) ]]
                             ,texture2d<half> blur5Alt [[ texture(13) ]]
                             ,texture2d<half> blur6Alt [[ texture(14) ]]
#endif
                             ,constant fxVars& vars[[ buffer(1)]]
                             ,constant txShaderUniforms& u[[ buffer(2) ]]
                             ,constant subFXVars& subVars[[buffer(3)]])
{
    float4 sharp = float4(inputTex0.sample(linearSampler, input.tex1));
//    float4 b6 = float4(blur6.sample(linearSampler, input.tex1));
    float4 b5 = float4(blur5.sample(linearSampler, input.tex1));
    float4 b4 = float4(blur4.sample(linearSampler, input.tex1));
    float4 b3 = float4(blur3.sample(linearSampler, input.tex1));
    float4 b2 = float4(blur2.sample(linearSampler, input.tex1));
    float4 b1 = float4(blur1.sample(linearSampler, input.tex1));

#ifdef IS_MEDIA_FILL
    float4 sharpColor = float4(inputTex1.sample(linearSampler, input.tex2));
//    float4 b6Alt = float4(blur6Alt.sample(linearSampler, input.tex2));
    float4 b5Alt = float4(blur5Alt.sample(linearSampler, input.tex2));
    float4 b4Alt = float4(blur4Alt.sample(linearSampler, input.tex2));
    float4 b3Alt = float4(blur3Alt.sample(linearSampler, input.tex2));
    float4 b2Alt = float4(blur2Alt.sample(linearSampler, input.tex2));
    float4 b1Alt = float4(blur1Alt.sample(linearSampler, input.tex2));
#endif

    // === Random staggered reveal logic ===
      // u.randomOnce is the same for the whole transition (global seed)
      // We combine it with the fragment's position to create a unique but stable random per-character
      // (This assumes your vertex shader or rendering setup makes characters have distinct tex coords / positions)

    float2 uv = input.tex1;                     // normalized UV for this glyph
    float uniqueSeed = u.randomOnce * (float) u.index;  // tweak multipliers for better distribution

    // Hash to get a pseudo-random value in [0, 1] that's stable for each character
    float rand = fract(sin(uniqueSeed * 43758.5453) * 43758.5453);

    // Control parameters (you can expose these in your uniform struct if you want to tweak from CPU)
    float totalDuration = 3.0;        // overall animation length (u.transitionProgress goes 0→1 over this)
    float maxDelay      = 2.0;        // max stagger delay in seconds (characters can start up to 1s late)
    float revealDuration = 0.85;      // how long each character's own blur→sharp transition takes

    // Calculate when this character should start revealing (0 to maxDelay)
    float startDelay = rand * maxDelay;

    // Global progress (0 to 1)
    float globalProg = input.mixValue.x;

    // Local progress for this character: when does it begin, and how far along is its own reveal?
    float localProg = saturate( (globalProg * totalDuration - startDelay) / revealDuration );

    // Optional: ease the local progress for a nicer feel (e.g. smoothstep or quadratic)
    localProg = smoothstep(0.0, 1.0, localProg);   // or pow(localProg, 0.6) etc.
    float alpha = u.baseAlpha * localProg;

    // Get the blurred color using your existing function
    float4 outColor = getBlur(1.0 - localProg, sharp, b5, b4, b3, b2, b1, vars.blurBias);   // adjust order if needed

#ifdef IS_MEDIA_FILL
    alpha *= outColor.a;
    outColor = getBlur(1.0 - localProg, sharpColor, b5Alt, b4Alt, b3Alt, b2Alt, b1Alt, vars.blurBias);
#endif

#ifdef USE_MASK
    alpha *= float(inputTexMask.sample(linearSampler, input.texMask).a);
#endif

    multiplyOpacity(outColor, alpha);

#ifdef SHOW_SEGMENT_OUTLINE
    showSegmentOutline(outColor);
#endif

    return outColor;
}
