

#ifndef INCLUDE_ATMOSPHERIC_HORIZON
#define INCLUDE_ATMOSPHERIC_HORIZON

// Developed by EminGT
// Modified by Haider

#include "/lib/color_schemes/core_color_system.glsl"

#ifdef CAVE_FOG
    #include "/lib/atmospherics/particles/depthFactor.glsl"
#endif

// Main atmospheric horizon rendering with advanced scattering
vec3 GetSkyHorizon(float VdotU, float VdotS, float dither, bool doGlare, bool doGround) {
    // Atmospheric variable preparation
    
    // Night factor calculations for smooth transitions
    float nightFactorSqrt2 = sqrt2(nightFactor);
    float nightFactorM = sqrt2(nightFactorSqrt2) * 0.4;
    
    // Sun direction calculations with enhanced precision
    float VdotSM1 = pow2(max(VdotS, 0.0));      // Sun intensity factor
    float VdotSM2 = pow2(VdotSM1);              // Enhanced sun effect
    float VdotSM3 = pow2(pow2(max(-VdotS, 0.0))); // Anti-sun direction
    float VdotSML = sunVisibility > 0.5 ? VdotS : -VdotS; // Light source selection
    
    // View direction calculations for horizon effects
    float VdotUmax0 = max(VdotU, 0.0);          // Above horizon only
    float VdotUmax0M = 1.0 - pow2(VdotUmax0);   // Inverted horizon factor

    // Sky color preparation
    vec3 upColor = mix(
        nightUpSkyColor * (1.5 - 0.5 * nightFactorSqrt2 + nightFactorM * VdotSM3 * 1.5),
        dayUpSkyColor,
        sunFactor
    );
        nightMiddleSkyColor * (3.0 - 2.0 * nightFactorSqrt2),
        dayMiddleSkyColor * (1.0 + VdotSM2 * 0.3),
        sunFactor
    );
    
    vec3 downColor = mix(
        nightDownSkyColor,
        dayDownSkyColor,
        (sunFactor + sunVisibility) * 0.5
    );

    // Atmospheric scattering simulation
    float VdotUM1 = pow2(1.0 - VdotUmax0);
    VdotUM1 = pow(VdotUM1, 1.0 - VdotSM2 * 0.4);  // Sun influence on gradient
    VdotUM1 = mix(VdotUM1, 1.0, rainFactor2 * 0.15);
    vec3 finalSky = mix(upColor, middleColor, VdotUM1);

    // Sunset/sunrise scattering
    float VdotUM2 = pow2(1.0 - abs(VdotU));
    VdotUM2 = VdotUM2 * VdotUM2 * (3.0 - 2.0 * VdotUM2); // Smoothstep for natural transition
    VdotUM2 *= (0.7 - nightFactorM + VdotSM1 * (0.3 + nightFactorM)) * invNoonFactor * sunFactor;
    finalSky = mix(finalSky, sunsetDownSkyColorP * (1.0 + VdotSM1 * 0.3), VdotUM2 * invRainFactor);

    // Horizon ground scattering
    float VdotUM3 = min(max0(-VdotU + 0.08) / 0.35, 1.0);
    VdotUM3 = smoothstep1(VdotUM3);
    
    vec3 scatteredGroundMixer = vec3(
        VdotUM3 * VdotUM3,
        sqrt1(VdotUM3),
        sqrt3(VdotUM3)
    );
    scatteredGroundMixer = mix(vec3(VdotUM3), scatteredGroundMixer, 0.75 - 0.5 * rainFactor);
    finalSky = mix(finalSky, downColor, scatteredGroundMixer);

    // Environmental effects
    if (doGround) {
        finalSky *= smoothstep1(pow2(1.0 + min(VdotU, 0.0)));
    }

    if (isEyeInWater == 1) {
        finalSky = mix(finalSky * 3.0, waterFogColor, VdotUmax0M);
    }

    // Celestial glare system
    #if !(defined(DISABLE_UNBOUND_SUN_MOON) && (SUN_MOON_STYLE >= 2))
    if (doGlare && 0.0 < VdotSML) {
        float glareScatter = 4.0 * (2.0 - clamp01(VdotS * 1000.0));
        float VdotSM4 = pow(abs(VdotS), glareScatter);

        float visfactor = 0.075;
        float glare = visfactor / (1.0 - (1.0 - visfactor) * VdotSM4) - visfactor;

        glare *= 0.5 + pow2(noonFactor) * 1.2;
        glare *= 1.0 - rainFactor * 0.5;

        float glareWaterFactor = isEyeInWater * sunVisibility;
        vec3 glareColor = mix(vec3(0.38, 0.4, 0.5) * 0.7, vec3(0.5), sunVisibility);
        glareColor = glareColor + glareWaterFactor * vec3(7.0);

        finalSky += glare * shadowTime * glareColor;
    }
    #endif

    // Cave environment integration
    #ifdef CAVE_FOG
        finalSky = mix(finalSky, caveFogColor, GetCaveFactor() * VdotUmax0M);
    #endif

    // Strong world fog for day/night travel
    float fogDistance = length(vec3(texcoord.x - 0.5, texcoord.y - 0.5, 0.0) * 2.0);
    float fogDensity = 0.35 + 0.15 * rainFactor; // Stronger fog in rain
    float fogAmount = exp(-fogDistance * fogDensity);
    
    vec3 fogColor = mix(
        nightMiddleSkyColor * 0.4, // Dark fog at night
        mix(dayMiddleSkyColor * 0.7, vec3(0.6, 0.65, 0.7), rainFactor), // Day fog with rain tint
        sunFactor
    );
    
    finalSky = mix(fogColor, finalSky, fogAmount);

    // Final processing
    finalSky += (dither - 0.5) / 128.0;

    return finalSky;
}

// Performance optimized sky module
vec3 GetOptimizedSkyHorizon(float VdotU, float VdotS, float dither, bool doGlare, bool doGround) {
    // Simplified variable setup
    
    float VdotUmax0 = max(VdotU, 0.0);
    float VdotUmax0M = 1.0 - pow2(VdotUmax0);

    // Basic color preparation
    
    vec3 upColor = mix(nightUpSkyColor, dayUpSkyColor, sunFactor);
    vec3 middleColor = mix(nightMiddleSkyColor, dayMiddleSkyColor, sunFactor);

    // Simplified sky gradient
    
    // Basic sky gradient with weather influence
    float VdotUM1 = pow2(1.0 - VdotUmax0);
    VdotUM1 = mix(VdotUM1, 1.0, rainFactor2 * 0.2);
    vec3 finalSky = mix(upColor, middleColor, VdotUM1);

    float VdotUM2 = pow2(1.0 - abs(VdotU));
    VdotUM2 *= invNoonFactor * sunFactor * (0.8 + 0.2 * VdotS);
    finalSky = mix(finalSky, sunsetDownSkyColorP * (shadowTime * 0.6 + 0.2), VdotUM2 * invRainFactor);

    finalSky *= pow2(pow2(1.0 + min(VdotU, 0.0)));

    if (isEyeInWater == 1) {
        finalSky = mix(finalSky, waterFogColor, VdotUmax0M);
    }

    #if !(defined(DISABLE_UNBOUND_SUN_MOON) && (SUN_MOON_STYLE >= 2))
    finalSky *= 1.0 + mix(nightFactor, 0.5 + 0.7 * noonFactor, VdotS * 0.5 + 0.5) * pow2(pow2(pow2(VdotS)));
    #endif

    #ifdef CAVE_FOG
        finalSky = mix(finalSky, caveFogColor, GetCaveFactor() * VdotUmax0M);
    #endif

    return finalSky;
}

// Legacy compatibility
#define GetSky GetSkyHorizon
#define GetLowQualitySky GetOptimizedSkyHorizon

#endif // INCLUDE_ATMOSPHERIC_HORIZON
