#include "/lib/config.glsl"

#ifdef RAIN_PUDDLES
    // Iris 1.11.x discovers boolean shader options through direct #ifdef /
    // #ifndef references. Keep this direct guard so the master toggle appears.
    #if !defined NETHER && !defined THE_END && (defined GBUFFER_TERRAIN || defined GBUFFER_TEXTURED)
        #define RAIN_SURFACE_PASS
    #endif
#endif

/* Color utils */

#if defined 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 gaux3;
uniform vec3 sunPosition;
uniform int isEyeInWater;
uniform float light_mix;
uniform float far;
uniform float rainStrength;
uniform float wetness;
uniform ivec2 eyeBrightnessSmooth;
uniform mat4 gbufferProjectionInverse;

#ifdef DISTANT_HORIZONS
    uniform int dhRenderDistance;
#endif

#ifdef DYN_HAND_LIGHT
    uniform int heldItemId;
    uniform int heldItemId2;
#endif

#ifdef UNKNOWN_DIM
    uniform sampler2D lightmap;
#endif

#if defined FOLIAGE_V || defined THE_END || defined NETHER
    uniform mat4 gbufferModelView;
#endif

uniform mat4 gbufferModelViewInverse;

#if defined MATERIAL_GLOSS && !defined NETHER
    uniform vec3 moonPosition;
#endif

#if defined SHADOW_CASTING && !defined NETHER
    uniform mat4 shadowModelView;
    uniform mat4 shadowProjection;
    uniform vec3 shadowLightPosition;
#endif

#if WAVING == 1 || defined RAIN_SURFACE_PASS
    uniform vec3 cameraPosition;
#endif

#if defined IS_IRIS && defined THE_END && MC_VERSION >= 12109
    uniform float endFlashIntensity;
#endif

/* Ins / Outs */

varying vec2 texcoord;
varying vec4 tint_color;
varying float fog_adj;
varying vec3 direct_light_color;
varying vec3 candle_color;
varying float direct_light_strength;
varying vec3 omni_light;
varying float block_type_f;
varying float exposure;
varying float depth;

#if defined EMMISIVE_MATERIAL || defined EMMISIVE_ORE
    varying float ore_type_f;
    varying float emitter_type_f;
#endif

#ifdef FOLIAGE_V
    varying float is_foliage;
#endif

#if defined FANTASY_LIFE_SYSTEM && defined FANTASY_NIGHT_FLORA
    varying float fantasy_plant_f;
#endif

#if defined SHADOW_CASTING && !defined NETHER
    varying vec3 shadow_pos;
    varying float shadow_diffuse;
#endif

#if defined MATERIAL_GLOSS && !defined NETHER
    varying vec3 flat_normal;
    varying vec3 sub_position3;
    varying vec3 sub_position3_norm;
    varying vec2 lmcoord_alt;
    varying float gloss_factor;
    varying float gloss_power;
    varying float luma_factor;
    varying float luma_power;
#endif

#if defined GBUFFER_BLOCK || defined FOLIAGE_V || defined GBUFFER_TERRAIN || defined GBUFFER_WATER || defined GBUFFER_HAND || (defined MATERIAL_GLOSS && !defined NETHER)
    attribute vec4 mc_Entity;
    attribute int blockEntityId;
#endif

varying vec4 position;

#if WAVING == 1
    attribute vec2 mc_midTexCoord;
#endif

#ifdef RAIN_SURFACE_PASS
    varying vec3 worldPos;
    varying vec3 world_normal;
    varying vec3 puddle_sky_zenith;
    varying float no_puddle_f;
    varying float sky_light_f;
#endif

/* Utility functions */

#if AA_TYPE > 0
    #include "/src/taa_offset.glsl"
#endif

#include "/lib/basic_utils.glsl"

#if defined SHADOW_CASTING && !defined NETHER
    #include "/lib/shadow_vertex.glsl"
#endif

#if WAVING == 1
    #include "/lib/vector_utils.glsl"
#endif

#include "/lib/luma.glsl"

#define FOG_BIOME
#include "/lib/biome_sky.glsl"
#include "/lib/downscale.glsl"

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

void main() {
    // Iris 1.11 / Minecraft 26.2 creates more specialized terrain and entity
    // programs than earlier versions.  These varyings are consumed by the
    // shared fragment stage even when a specialized vertex path has no
    // material ID to write. Explicit neutral values give every program a
    // complete vertex/fragment interface at compile time.
    block_type_f = 0.0;
    #if defined FANTASY_LIFE_SYSTEM && defined FANTASY_NIGHT_FLORA
        fantasy_plant_f = 0.0;
    #endif
    #if defined EMMISIVE_MATERIAL || defined EMMISIVE_ORE
        ore_type_f = 0.0;
        emitter_type_f = 0.0;
    #endif

    exposure = texture2D(gaux3, vec2(0.5)).r;
    position = gbufferModelViewInverse * gl_ModelViewMatrix * gl_Vertex;

    vec2 eye_bright_smooth = vec2(eyeBrightnessSmooth);
    vec3 hi_sky_color;
    vec3 pure_hi_sky_color;
    float visible_sky;
    int mc_entity_x_int; 

    #include "/src/basiccoords_vertex.glsl"
    #include "/src/position_vertex.glsl"
    resize_vertex(gl_Position);
    #include "/src/hi_sky.glsl"
    #include "/src/light_vertex.glsl"
    #include "/src/fog_vertex.glsl"

    depth = length(gl_ModelViewMatrix * gl_Vertex);

    #if defined SHADOW_CASTING && !defined NETHER
        #include "/src/shadow_src_vertex.glsl"
    #endif

    #if defined FOLIAGE_V && !defined NETHER
        #ifdef SHADOW_CASTING
            float foliage_mask = step(0.2, is_foliage);
            float shadow_fade = clamp((gl_Position.z / SHADOW_LIMIT) * 2.0 - 0.5, 0.0, 1.0);
            direct_light_strength = mix(direct_light_strength, far_direct_light_strength, foliage_mask * shadow_fade);
        #endif
    #endif

    #if defined GBUFFER_BLOCK   
        block_type_f = step(10090.5, float(blockEntityId)) * step(float(blockEntityId), 10091.5); 
    #endif

    #if defined GBUFFER_TERRAIN 
        float eid = float(mc_Entity.x);

        #if defined FANTASY_LIFE_SYSTEM && defined FANTASY_NIGHT_FLORA
            float fantasy_flower = step(10509.5, eid) * step(eid, 10510.5);
            float fantasy_blossom_leaves = step(10510.5, eid) * step(eid, 10511.5);
            float fantasy_leaves = step(10017.5, eid) * step(eid, 10018.5);
            float fantasy_grass_flora = step(10030.5, eid) * step(eid, 10031.5);
            fantasy_plant_f = fantasy_flower
                + fantasy_leaves * 2.0
                + fantasy_blossom_leaves * 3.0
                + fantasy_grass_flora * 4.0;
        #endif

        #if defined EMMISIVE_ORE
            float is_ore = step(8999.5, eid) * step(eid, 9007.5);
            ore_type_f = (eid - 8999.0) * is_ore;
        #endif
        
        #if defined EMMISIVE_MATERIAL
            float m_rangeA = step(9007.5, eid) * step(eid, 9015.5);
            float typeA = (eid - 9007.0) + (step(9013.5, eid) * 3.0);

            float m_rangeB = step(10088.5, eid) * step(eid, 10090.5);
            float typeB = mix(8.0, 7.0, step(10089.5, eid));

            float m_rangeC = step(10212.5, eid) * step(eid, 10214.5);
            float typeC = 9.0;

            emitter_type_f = (typeA * m_rangeA) + (typeB * m_rangeB) + (typeC * m_rangeC);
        #endif
    #endif

    // --- LÓGICA DE MATERIAL GLOSS ---
    #if defined MATERIAL_GLOSS && !defined NETHER
        float id = float(mc_Entity.x);

        luma_factor = 1.5; luma_power = 2.0; gloss_power = 1.25; gloss_factor = 1.0;

        float m_sand     = step(10409.5, id) * step(id, 10410.5);
        float m_stone    = step(10410.5, id) * step(id, 10411.5);
        float m_metal    = step(10399.5, id) * step(id, 10400.5);
        float m_fabric   = step(10439.5, id) * step(id, 10440.5);
        float m_polished = step(10419.5, id) * step(id, 10420.5);
        float m_rough    = step(10429.5, id) * step(id, 10430.5);
        float m_concrete = step(10449.5, id) * step(id, 10450.5);
        float m_w_pol    = step(10420.5, id) * step(id, 10421.5);
        float m_white    = step(10414.5, id) * step(id, 10415.5);
        float m_leaves   = step(10017.5, id) * step(id, 10018.5);
        float m_w_leaves = step(10018.5, id) * step(id, 10019.5);

        luma_factor = mix(luma_factor, 1.1,  m_sand);
        luma_factor = mix(luma_factor, 1.75, m_stone + m_polished);
        luma_factor = mix(luma_factor, 3.0,  m_fabric);
        luma_factor = mix(luma_factor, 6.5,  m_concrete);
        luma_factor = mix(luma_factor, 2.0,  m_w_pol);
        luma_factor = mix(luma_factor, 1.0,  m_white);
        luma_factor = mix(luma_factor, 1.25, m_leaves + m_w_leaves);

        luma_power = mix(luma_power, 12.0, m_sand + m_w_leaves);
        luma_power = mix(luma_power, 8.0,  m_stone);
        luma_power = mix(luma_power, 5.0,  m_metal);
        luma_power = mix(luma_power, 6.0,  m_polished + m_w_pol);
        luma_power = mix(luma_power, 10.0, m_rough);
        luma_power = mix(luma_power, 0.5,  m_concrete);
        luma_power = mix(luma_power, 1.0,  m_white);
        luma_power = mix(luma_power, 0.25, m_leaves);

        gloss_power = mix(gloss_power, 4.0,  m_sand + m_stone);
        gloss_power = mix(gloss_power, 35.0, m_metal);
        gloss_power = mix(gloss_power, 3.0,  m_fabric + m_w_leaves);
        gloss_power = mix(gloss_power, 15.0, m_polished + m_rough + m_concrete);
        gloss_power = mix(gloss_power, 20.0, m_w_pol);
        gloss_power = mix(gloss_power, 1.5,  m_white);
        gloss_power = mix(gloss_power, 2.0,  m_leaves);

        gloss_factor = mix(gloss_factor, 2.5,  m_sand);
        gloss_factor = mix(gloss_factor, 1.5,  m_metal);
        gloss_factor = mix(gloss_factor, 0.1,  m_fabric + m_w_leaves);
        gloss_factor = mix(gloss_factor, 3.0,  m_polished);
        gloss_factor = mix(gloss_factor, 0.3,  m_rough);
        gloss_factor = mix(gloss_factor, 0.2,  m_w_pol);
        gloss_factor = mix(gloss_factor, 0.75, m_white);
        gloss_factor = mix(gloss_factor, 1.25, m_leaves);

        flat_normal = normal;
        sub_position3 = sub_position.xyz;
        sub_position3_norm = normalize(sub_position3);
        lmcoord_alt = lmcoord;      
    #endif

    #ifdef RAIN_SURFACE_PASS
        worldPos = position.xyz + cameraPosition;
        world_normal = normalize((gbufferModelViewInverse * vec4(normal, 0.0)).xyz);
        // hi_sky_color is Aurora's own weather/time-aware zenith colour in XYZ.
        // Passing it to the fragment stage keeps puddle reflections in the same
        // colour language as the rendered sky instead of a flat grey value.
        puddle_sky_zenith = hi_sky_color;
        sky_light_f = clamp((lmcoord.y - 0.8) / 0.2, 0.0, 1.0);
        // Mark hot/dry blocks that should not have puddles
        #if defined GBUFFER_TERRAIN
            float eid_puddle = float(mc_Entity.x);
            // 10410 = sand-like, 10090 = lava/magma/fire
            float is_sand = step(10409.5, eid_puddle) * step(eid_puddle, 10410.5);
            float is_lava = step(10089.5, eid_puddle) * step(eid_puddle, 10090.5);
            no_puddle_f = max(is_sand, is_lava);
        #else
            no_puddle_f = 0.0;
        #endif
    #endif

    #if defined GBUFFER_ENTITY_GLOW
        gl_Position.z *= 0.01;
    #endif
}
