#include "dxShaderIncludes.h"
#include "alpha.h"
#include "textAnimationHelper.h"

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

cbuffer variableBuffer : register(b2)
{
    fxVars vars;
}

Texture2D blur1 : register(t3);
Texture2D blur2 : register(t4);
Texture2D blur3 : register(t5);
Texture2D blur4 : register(t6);
Texture2D blur5 : register(t7);
Texture2D blur6 : register(t8);
Texture2D blur1Alt : register(t9);
Texture2D blur2Alt : register(t10);
Texture2D blur3Alt : register(t11);
Texture2D blur4Alt : register(t12);
Texture2D blur5Alt : register(t13);
Texture2D blur6Alt : register(t14);

vertexOut vertexShader(txShaderVerts input)
{
    vertexOut output;

    output.normPos = input.position.xy;

    float4 tmpPos = mul(u.worldViewProj, float4(input.position.xyz, 1.0));

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

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

    output.position = tmpPos;

    output.tex1 = input.tex1;
    output.tex2 = input.tex2;
    output.texMask = input.texMask;

    return output;
}

float4 pixelShader(vertexOut input) : SV_TARGET
{
    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 HAS_BACKGROUND_EFFECT
    outColor = backgroundEffect(outColor, inputTex1, inputTexMask, input.position.xy, u, subVars);
#endif
    
#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 *= inputTexMask.Sample(linearSampler, input.texMask).a;
#endif

    multiplyOpacity(outColor, alpha);

#ifdef SHOW_SEGMENT_OUTLINE
    showSegmentOutline(outColor);
#endif

    return outColor;
}
