#include "/lib/config.glsl"

/* Color utils */

#ifdef THE_END
    #include "/lib/color_utils_end.glsl"
#elif defined NETHER
    #include "/lib/color_utils_nether.glsl"
#else
    #include "/lib/color_utils.glsl"
#endif

/* Uniforms */

uniform sampler2D gaux4;
uniform float pixelSizeX;
uniform float pixelSizeY;
uniform mat4 gbufferProjectionInverse;
uniform mat4 gbufferModelView;
uniform mat4 gbufferModelViewInverse;
uniform float viewWidth;
uniform float viewHeight;
uniform vec3 sunPosition;
uniform vec3 moonPosition;
uniform float rainStrength;
uniform float frameTimeCounter;


#ifdef NETHER
    uniform vec3 fogColor;
#endif


/* Ins / Outs */

#if MC_VERSION < 11604
    varying vec3 upVector;
    varying vec3 zenithSkyColor;
    varying vec3 horizonSkyColor;
#endif

varying vec4 star_data;

/* Utility functions */

#ifdef THE_END
    #include "/lib/end_space.glsl"
#endif

#if MC_VERSION < 11604
    #include "/lib/dither.glsl"
#endif


vec3 prismaRoundSunMoon(vec3 viewDir, vec3 upDir) {
    vec3 sunDir = normalize(sunPosition);
    vec3 moonDir = normalize(moonPosition);

    float sunCos = clamp(dot(viewDir, sunDir), -1.0, 1.0);
    float moonCos = clamp(dot(viewDir, moonDir), -1.0, 1.0);

    // Keep the disk clean and avoid the dusty halo when the sun is off-center.
    // The direct look-at-sun glow is handled in final_fragment instead.
    float sunCore = smoothstep(cos(0.0405), cos(0.0300), sunCos);
    float sunGlow = smoothstep(cos(0.0435), cos(0.0300), sunCos) * (1.0 - sunCore);
    sunGlow *= sunGlow;
    sunGlow *= sunGlow;
    sunGlow *= sunGlow;

    float moonCore = smoothstep(cos(0.0360), cos(0.0265), moonCos);
    float moonGlow = smoothstep(cos(0.0390), cos(0.0265), moonCos) * (1.0 - moonCore);
    moonGlow *= moonGlow;
    moonGlow *= moonGlow;
    moonGlow *= moonGlow;

    float sunHorizon = smoothstep(-0.02, 0.05, dot(sunDir, upDir));
    float moonHorizon = smoothstep(-0.02, 0.05, dot(moonDir, upDir));
    float rainFade = 1.0 - rainStrength;

    vec3 sunTint = vec3(1.28, 1.18, 1.02);
    vec3 moonTint = vec3(0.72, 0.80, 0.96);

    vec3 sunColor = sunTint * (sunCore * 8.4 + sunGlow * 0.0025) * sunHorizon * rainFade;
    vec3 moonColor = moonTint * (moonCore * 0.94 + moonGlow * 0.0015) * moonHorizon;

    return sunColor + moonColor;
}

// MAIN FUNCTION ------------------

void main() {
    #if defined THE_END
        vec2 prismaNdcSky = gl_FragCoord.xy * vec2(pixelSizeX, pixelSizeY) * 2.0 - 1.0;
        vec4 prismaFragSky = gbufferProjectionInverse * vec4(prismaNdcSky, 1.0, 1.0);
        vec3 prismaViewDirSky = normalize(prismaFragSky.xyz / max(prismaFragSky.w, 1e-6));
        vec3 prismaWorldDirSky = normalize((gbufferModelViewInverse * vec4(prismaViewDirSky, 0.0)).xyz);
        vec4 blockColor = vec4(prismaEndSpaceSky(prismaWorldDirSky), 1.0);
    #elif defined NETHER  // Unused
        #if MC_VERSION < 11604
            vec4 background_color = vec4(mix(fogColor * 0.1, vec3(1.0), 0.04), 1.0);
        #endif
        vec4 blockColor = vec4(mix(fogColor * 0.1, vec3(1.0), 0.04), 1.0);
    #else
        #if MC_VERSION < 11604
            #if AA_TYPE > 0
                float dither = shiftedRDither(gl_FragCoord.xy);
            #else
                float dither = dither13(gl_FragCoord.xy);
            #endif

            dither = (dither - .5) * 0.03125;

            vec4 fragpos =
                gbufferProjectionInverse *
                (vec4(gl_FragCoord.xy * vec2(pixelSizeX, pixelSizeY), gl_FragCoord.z, 1.0) * 2.0 - 1.0);
            vec3 nfragpos = normalize(fragpos.xyz);
            float n_u = clamp(dot(nfragpos, upVector) + dither, 0.0, 1.0);
            vec4 background_color = vec4(mix(horizonSkyColor, zenithSkyColor, smoothstep(0.0, 1.0, pow(n_u, 0.333))), 1.0);
            background_color.rgb = xyzToRgb(background_color.rgb);
        #else

            // Toma el color puro del bloque
            vec4 background_color = texture2DLod(gaux4, gl_FragCoord.xy * vec2(pixelSizeX, pixelSizeY), 0);
        #endif

        vec4 blockColor = star_data;

        blockColor = mix(background_color, blockColor, blockColor);

        #if MC_VERSION >= 11604
            // blockColor.a = star_data.a;
        #endif
    #endif

    
    #if MC_VERSION >= 11604
        #if defined THE_END
            blockColor.a = 1.0;
        #else
            blockColor.rgba = vec4(texture2D(gaux4, gl_FragCoord.xy * vec2(pixelSizeX, pixelSizeY)).rgb, clamp(star_data.a * 2.0, 0.0, 1.0));
        #endif
    #endif

    #if !defined THE_END && !defined NETHER
        vec2 prismaNdc = gl_FragCoord.xy * vec2(pixelSizeX, pixelSizeY) * 2.0 - 1.0;
        vec4 prismaFrag = gbufferProjectionInverse * vec4(prismaNdc, 1.0, 1.0);
        vec3 prismaViewDir = normalize(prismaFrag.xyz / max(prismaFrag.w, 1e-6));
        vec3 prismaUpDir = normalize(gbufferModelView[1].xyz);
        blockColor.rgb += prismaRoundSunMoon(prismaViewDir, prismaUpDir);
        blockColor.a = 1.0;
    #endif

    #include "/src/writebuffers.glsl"
}
