#version 300 es

precision mediump float;

// Input varyings
in vec2 v_originTexCoord;
in vec2 v_originTexCoord_local;
in vec3 vONormal;
in float vRandom;
in float isEdge;
in vec4 sideShadow;
in float animZBrightness;

// Uniforms
uniform sampler2D uCellDecTex;
uniform sampler2D uCellTex;
uniform sampler2D uCellEdgeTex;
uniform sampler2D uCurrentMainTex;
uniform sampler2D uNextMainTex;
uniform int nightEyeProtection;
uniform float u_aspect_ratio;
uniform float uRate;
uniform float uProgress;
uniform vec3 uInnerCellPos;
uniform vec3 uCellPlaneColor;
uniform int uSkinType;

// Constants
const float shadowWidth = 0.9;
const float shadowIntensity = 33.7;
const float shadowFeather = 0.15;
const float lockShadowIntensity = 0.01;
// Additional inner shadow constants
const float addShadowWidth = 0.4;
const float addShadowIntensity = 0.3;
const float addShadowFeather = 0.1;
const float localShadowWidth = 0.2;// New constant for local shadow
const float localShadowFeather = 0.15;// Control shadow edge smoothness

// Inner shadow constants
const float INNER_SHADOW_HALF_SIZE = 0.95;
const float INNER_SHADOW_CORNER_RADIUS = 0.05;
const float INNER_SHADOW_BLUR_RADIUS = 0.07;
const float INNER_SHADOW_DIST_MULTIPLIER = -1.0;
const float INNER_SHADOW_BASE_POWER = 2.5;
const float INNER_SHADOW_STRENGTH_POWER = 1.5;
const float INNER_SHADOW_MAX_BRIGHTNESS = 1.0;
const float INNER_SHADOW_EDGE_BLEND_SMOOTHNESS = 1.2;

// Output
out vec4 fragColor;

// SDF for rectangle
float rectSDF(vec2 p, vec2 size) {
    vec2 d = abs(p) - size;
    return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
}

float sdRoundRect(in vec2 p, in vec2 b, in float r) {
    vec2 q = abs(p)-b+r;
    return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r;
}

float sigmoid(float t) {
    return 1.0 / (1.0 + exp(-t));
}

float makeShadow(vec2 pos, vec2 halfSize, float cornerRd, float blurRd, float distMul) {
    float dist = sigmoid(distMul * sdRoundRect(pos, halfSize, cornerRd + blurRd) / blurRd);
    return clamp(pow(dist, INNER_SHADOW_BASE_POWER), 0.0, 1.0);
}

vec4 getEdgeWeights(vec2 pos, vec2 halfSize) {
    vec2 p_norm = pos / halfSize;
    vec2 p_abs = abs(p_norm);

    float w = INNER_SHADOW_EDGE_BLEND_SMOOTHNESS;
    float horiz = smoothstep(p_abs.y - w, p_abs.y + w, p_abs.x);
    float vert = 1.0 - horiz;

    vec4 weights = vec4(0.0);
    // Top
    if (pos.y > 0.0) weights.x = vert;
    // Bottom
    else weights.z = vert;

    // Right
    if (pos.x > 0.0) weights.y = horiz;
    // Left
    else weights.w = horiz;

    return weights;
}

void main() {
    vec4 currentColor;
    vec4 nextColor;

    // Calculate face based on normal
    vec3 absNormal = abs(vONormal);
    float maxComp = max(max(absNormal.x, absNormal.y), absNormal.z);

    // Handle different faces
    if (maxComp == absNormal.x) {
        currentColor = vec4(uCellPlaneColor * 0.3, 5.0);
    } else if (maxComp == absNormal.y) {
        currentColor = vec4(uCellPlaneColor * 0.2, 1.0);
    } else if (vONormal.z > 0.5) {
        // Front face
        if (isEdge > 0.0) {
            currentColor = (uSkinType == 0)
                ? mix(texture(uCurrentMainTex, v_originTexCoord),
                     texture(uNextMainTex, v_originTexCoord),
                     uProgress)
                : texture(uCellEdgeTex, v_originTexCoord);
        } else {
            vec4 cellDecTex = texture(uCellDecTex, v_originTexCoord_local);
            
            // Calculate base color based on skin type
            if (uSkinType == 0) {
                vec4 curr = texture(uCurrentMainTex, v_originTexCoord) * cellDecTex * vRandom;
                vec4 next = texture(uNextMainTex, v_originTexCoord) * cellDecTex * vRandom;
                currentColor = mix(curr, next, uProgress);
            } else {
                currentColor = texture(uCellTex, v_originTexCoord_local) * vRandom * cellDecTex;
            }

            // Calculate shadow effects
            vec2 localPos = v_originTexCoord_local * 2.0 - 1.0;
            float shadow = makeShadow(localPos,
                vec2(INNER_SHADOW_HALF_SIZE),
                INNER_SHADOW_CORNER_RADIUS,
                INNER_SHADOW_BLUR_RADIUS,
                INNER_SHADOW_DIST_MULTIPLIER);
            float shadowStrength = pow(shadow, INNER_SHADOW_STRENGTH_POWER);

            vec4 inner_shadow_edge_min_brightness = vec4(sideShadow.x, sideShadow.w, sideShadow.y, sideShadow.z);
            vec4 edgeWeights = getEdgeWeights(localPos, vec2(INNER_SHADOW_HALF_SIZE));
            float min_brightness = dot(edgeWeights, inner_shadow_edge_min_brightness);

            // Apply shadow and brightness effects
            currentColor.rgb *= mix(min_brightness,
                INNER_SHADOW_MAX_BRIGHTNESS,
                shadowStrength) + 0.3;
            currentColor.rgb -= animZBrightness;
        }
    }

    // Apply night eye protection if enabled
    currentColor = (nightEyeProtection == 1)
        ? vec4(min(currentColor.r, 0.7), currentColor.g, currentColor.b * 0.8, currentColor.a)
        : currentColor;

    // Apply final rate adjustment
    fragColor = currentColor * min(uRate * 2., 1.0);
}