#include "/lib/config/water.glsl"

#include "/lib/config/light.glsl"

#include "/lib/config/constants.glsl"

#include "/lib/config/visual.glsl"

#include "/lib/config/sky.glsl"

#include "/lib/config/user.glsl"

#ifdef END
    const float sunPathRotation = 0.0;
#else
    #if LU_SUN_ANGLE == -1
        #if LU_SHADER_STYLE == 1
            const float sunPathRotation = 0.0;
            #define LU_PERPENDICULAR_TWEAKS
        #elif LU_SHADER_STYLE == 4
            const float sunPathRotation = -40.0;
        #endif
    #elif LU_SUN_ANGLE == 0
        const float sunPathRotation = 0.0;
        #define LU_PERPENDICULAR_TWEAKS
    #elif LU_SUN_ANGLE == 20
        const float sunPathRotation = 20.0;
    #elif LU_SUN_ANGLE == 30
        const float sunPathRotation = 30.0;
    #elif LU_SUN_ANGLE == 40
        const float sunPathRotation = 40.0;
    #elif LU_SUN_ANGLE == 50
        const float sunPathRotation = 50.0;
    #elif LU_SUN_ANGLE == 60
        const float sunPathRotation = 60.0;
    #elif LU_SUN_ANGLE == -20
        const float sunPathRotation = -20.0;
    #elif LU_SUN_ANGLE == -30
        const float sunPathRotation = -30.0;
    #elif LU_SUN_ANGLE == -40
        const float sunPathRotation = -40.0;
    #elif LU_SUN_ANGLE == -50
        const float sunPathRotation = -50.0;
    #elif LU_SUN_ANGLE == -60
        const float sunPathRotation = -60.0;
    #endif
#endif

#if LU_SUN_MOON_STYLE_DEFINE == -1
    #define LU_SUN_MOON_STYLE LU_SUN_MOON_STYLE_DEFAULT
#else
    #define LU_SUN_MOON_STYLE LU_SUN_MOON_STYLE_DEFINE
#endif

#if LU_RP_MODE >= 2
    #define LU_CUSTOM_PBR
    #define LU_POM
#endif
#if LU_RP_MODE == 1
    #define LU_IPBR
    #define LU_IPBR_PARTICLE_FEATURES
    //#define LU_GENERATED_NORMALS
    //#define LU_COATED_TEXTURES
    //#define LU_FANCY_GLASS
    //#define LU_GREEN_SCREEN_LIME
#endif

#if LU_CLOUD_STYLE_DEFINE == -1
    #define LU_CLOUD_STYLE LU_CLOUD_STYLE_DEFAULT
#else
    #define LU_CLOUD_STYLE LU_CLOUD_STYLE_DEFINE
#endif

#if LU_WATER_CAUSTIC_STYLE_DEFINE == -1
    #define LU_WATER_CAUSTIC_STYLE LU_WATER_STYLE
#else
    #define LU_WATER_CAUSTIC_STYLE LU_WATER_CAUSTIC_STYLE_DEFINE
#endif

#if LU_AURORA_STYLE_DEFINE == -1
    #define LU_AURORA_STYLE LU_AURORA_STYLE_DEFAULT
#else
    #define LU_AURORA_STYLE LU_AURORA_STYLE_DEFINE
#endif

#if LU_WATER_STYLE_DEFINE == -1
    #define LU_WATER_STYLE LU_WATER_STYLE_DEFAULT
#else
    #define LU_WATER_STYLE LU_WATER_STYLE_DEFINE
#endif

#if LU_SHADER_STYLE == 1
    #define LU_WATER_STYLE_DEFAULT 1
    //#define LU_WATER_CAUSTIC_STYLE_DEFAULT 1
    #define LU_AURORA_STYLE_DEFAULT 1
    #define LU_SUN_MOON_STYLE_DEFAULT 1
    #define LU_CLOUD_STYLE_DEFAULT 1
#elif LU_SHADER_STYLE == 4
    #define LU_WATER_STYLE_DEFAULT 3
    //#define LU_WATER_CAUSTIC_STYLE_DEFAULT 3
    #define LU_AURORA_STYLE_DEFAULT 2
    #define LU_SUN_MOON_STYLE_DEFAULT 2
    #define LU_CLOUD_STYLE_DEFAULT 3
#endif

#if LU_DETAIL_QUALITY >= 3 // High
    #undef LU_WATER_MAT_QUALITY
    #define LU_WATER_MAT_QUALITY 3 // we use LU_DETAIL_QUALITY >= 3 when writing in gbuffers_water because optifine bad
    #define LU_HQ_NIGHT_NEBULA
    #define LU_SKY_EFFECT_REFLECTION
    #define LU_CONNECTED_GLASS_CORNER_FIX
    #define LU_ACL_CORNER_LEAK_FIX
    #define LU_DO_NETHER_VINE_WAVING_OUTSIDE_NETHER
    #define LU_DO_MORE_FOLIAGE_WAVING
    #if defined IRIS_FEATURE_CUSTOM_IMAGES && LU_SHADOW_QUALITY > -1 && LU_RAIN_PUDDLES > 0 && LU_COLORED_LIGHTING_INTERNAL > 0
        #define LU_PUDDLE_VOXELIZATION
    #endif
    #if LU_CLOUD_QUALITY >= 3 && LU_CLOUD_STYLE > 0 && LU_CLOUD_STYLE != 50
        #define LU_ENTITY_TAA_NOISY_CLOUD_FIX
    #endif
#endif

#if LU_DETAIL_QUALITY == 0 // Potato
    #undef LU_PERPENDICULAR_TWEAKS
    #define LU_LOW_QUALITY_NETHER_STORM
    #define LU_LOW_QUALITY_ENDER_NEBULA
    #define LU_WATER_MAT_QUALITY 1
#endif

#if LU_DETAIL_QUALITY >= 2 // Medium
    #undef LU_WATER_MAT_QUALITY
    #define LU_WATER_MAT_QUALITY 2
    #define LU_FXAA_TAA_INTERACTION
    #define LU_TAA_MOVEMENT_IMPROVEMENT_FILTER
#endif

#if LU_DETAIL_QUALITY >= 1 // not an option for now
    #if LU_TAA_MODE >= 1
        #define LU_TAA
    #endif
    #define LU_WATER_MAT_QUALITY 1
#endif

#if LU_BLOCK_REFLECT_QUALITY >= 3 && LU_RP_MODE >= 1
    #define LU_TEMPORAL_FILTER
#endif
#if LU_BLOCK_REFLECT_QUALITY >= 1
    #define LU_LIGHT_HIGHLIGHT
#endif
#if LU_BLOCK_REFLECT_QUALITY >= 2 && LU_RP_MODE >= 1
    #define LU_PBR_REFLECTIONS
#endif

#if LU_SHADOW_QUALITY >= 1
    #if LU_SHADOW_QUALITY > 4 || LU_SHADOW_SMOOTHING < 3
        const int shadowMapResolution = 4096;
    #else
        const int shadowMapResolution = 2048;
    #endif
#else
    const int shadowMapResolution = 1024;
#endif

#if LU_LIGHTSHAFT_BEHAVIOUR > 0
    #define LU_LIGHTSHAFT_QUALI LU_LIGHTSHAFT_QUALI_DEFINE
#else
    #define LU_LIGHTSHAFT_QUALI 0
#endif
#if LU_SSAO_I > 0
    #define LU_SSAO_QUALI LU_SSAO_QUALI_DEFINE
#else
    #define LU_SSAO_QUALI 0
#endif

//Define Handling//
    #ifdef OVERWORLD
        #if LU_CLOUD_STYLE > 0 && LU_CLOUD_STYLE != 50 && LU_CLOUD_QUALITY > 0
            #define LU_VL_CLOUDS_ACTIVE
            #if LU_CLOUD_STYLE == 1
                #define LU_CLOUDS_REIMAGINED
            #endif
            #if LU_CLOUD_STYLE == 3
                #define LU_CLOUDS_UNBOUND
            #endif
        #endif
    #else
        #undef LU_LIGHT_HIGHLIGHT
        #undef LU_CAVE_FOG
        #undef LU_CLOUD_SHADOWS
        #undef SNOWY_WORLD
        #undef LIGHTSHAFT_SMOKE
    #endif
    #ifdef NETHER
        #undef LU_ATMOSPHERIC_FOG
        #undef LU_NO_WAVING_INDOORS
    #else
        #undef LU_NETHER_STORM
    #endif
    #ifndef END
        #undef LU_END_STORM
    #endif
    #ifdef END
        #undef LU_BLOOM_FOG
    #endif

    #ifndef LU_BLOOM
        #undef LU_BLOOM_FOG
    #endif

    #if defined PIXELATED_SHADOWS || defined PIXELATED_BLOCKLIGHT || defined PIXELATED_AO
        #if !defined LU_GBUFFERS_BASIC && !defined DH_TERRAIN && !defined DH_WATER
            #define LU_DO_PIXELATION_EFFECTS
        #endif
    #endif

    #ifndef LU_GBUFFERS_TERRAIN
        #undef PIXELATED_BLOCKLIGHT
    #endif

    #ifdef LU_BLOOM_FOG
        #if LU_WORLD_BLUR > 0
            #define LU_BLOOM_FOG_COMPOSITE3
        #elif defined MOTION_BLURRING
            #define LU_BLOOM_FOG_COMPOSITE2
        #else
            #define LU_BLOOM_FOG_COMPOSITE
        #endif
    #endif

    #if defined LU_GBUFFERS_HAND || defined LU_GBUFFERS_ENTITIES
        #undef SNOWY_WORLD
        #undef LU_DISTANT_LIGHT_BOKEH
    #endif
    #if defined LU_GBUFFERS_TEXTURED || defined LU_GBUFFERS_BASIC
        #undef LU_LIGHT_HIGHLIGHT
        #undef LU_DIRECTIONAL_SHADING
        #undef LU_SIDE_SHADOWING
    #endif
    #ifdef LU_GBUFFERS_WATER
        #undef LU_LIGHT_HIGHLIGHT
    #endif

    #ifndef LU_GLOWING_ENTITY_FIX
        #undef LU_GBUFFERS_ENTITIES_GLOWING
    #endif

    #if LU_LIGHTSHAFT_QUALI > 0 && defined OVERWORLD && LU_SHADOW_QUALITY > -1 || defined END
        #define LU_LIGHTSHAFTS_ACTIVE
    #endif

    #if defined LU_WAVING_FOLIAGE || defined LU_WAVING_LEAVES || defined LU_WAVING_LAVA || defined LU_WAVING_LILY_PAD
        #define LU_WAVING_ANYTHING_TERRAIN
    #endif

    #if LU_WATERCOLOR_R != 100 || LU_WATERCOLOR_G != 100 || LU_WATERCOLOR_B != 100
        #define LU_WATERCOLOR_RM LU_WATERCOLOR_R * 0.01
        #define LU_WATERCOLOR_GM LU_WATERCOLOR_G * 0.01
        #define LU_WATERCOLOR_BM LU_WATERCOLOR_B * 0.01
        #define LU_WATERCOLOR_CHANGED
    #endif

    #if LU_UNDERWATERCOLOR_R != 100 || LU_UNDERWATERCOLOR_G != 100 || LU_UNDERWATERCOLOR_B != 100
        #define LU_UNDERWATERCOLOR_RM LU_UNDERWATERCOLOR_R * 0.01
        #define LU_UNDERWATERCOLOR_GM LU_UNDERWATERCOLOR_G * 0.01
        #define LU_UNDERWATERCOLOR_BM LU_UNDERWATERCOLOR_B * 0.01
        #define LU_UNDERWATERCOLOR_CHANGED
    #endif

    #if defined IS_IRIS && !defined IRIS_HAS_TRANSLUCENCY_SORTING
        #undef LU_FANCY_GLASS
    #endif

    #ifdef DISTANT_HORIZONS
        #undef LU_DISTANT_LIGHT_BOKEH
    #endif

    #if defined MC_GL_VENDOR_AMD || defined MC_GL_VENDOR_ATI
        #ifndef LU_DEFERRED1
            #define LU_FIX_AMD_REFLECTION_CRASH //BFARC: Fixes a driver crashing problem on AMD GPUs
        #endif
    #endif

//Activate Settings//
    #ifdef POM_ALLOW_CUTOUT
    #endif
    #ifdef LU_BRIGHT_CAVE_WATER
    #endif
    #ifdef LU_IPBR_PARTICLE_FEATURES
    #endif
    #ifdef COLORED_CANDLE_LIGHT
    #endif
    #ifdef PIXELATED_AO
    #endif

//Very Common Stuff//
    // === Lunara: inlined contents of /lib/globals.glsl =====================
    #ifndef LU_LUNARA_RENDER_GLOBALS_GUARD
    #define LU_LUNARA_RENDER_GLOBALS_GUARD

    uniform float framemod8;
    uniform float isEyeInCave;
    uniform float inDry;
    uniform float inRainy;
    uniform float inSnowy;
    uniform float inDesert;
    uniform float velocity;
    uniform float starter;
    uniform float frameTimeSmooth;
    uniform float eyeBrightnessM;
    uniform float eyeBrightnessM2;
    uniform float rainFactor;
    uniform float inBasaltDeltas;
    uniform float inCrimsonForest;
    uniform float inNetherWastes;
    uniform float inSoulValley;
    uniform float inWarpedForest;
    uniform float inPaleGarden;

    const bool colortex0Clear = true;
    const bool colortex7Clear = false;
    const bool colortex3Clear = true;
    const bool colortex1Clear = false;
    const bool colortex6Clear = true;
    const bool colortex2Clear = false;
    const bool colortex4Clear = false;
    const bool colortex5Clear = false;

    uniform int blockEntityId;
    uniform int worldTime;
    uniform int currentRenderedItemId;
    uniform int frameCounter;
    uniform int entityId;
    uniform int worldDay;
    uniform int heldBlockLightValue;
    uniform int moonPhase;
    uniform int heldBlockLightValue2;
    uniform int isEyeInWater;
    uniform int heldItemId;
    uniform int heldItemId2;

    const int noiseTextureResolution = 128;

    uniform float aspectRatio;
    uniform float wetness;
    uniform float blindness;
    uniform float rainStrength;
    uniform float darknessFactor;
    uniform float sunAngle;
    uniform float darknessLightFactor;
    uniform float screenBrightness;
    uniform float maxBlindnessDarkness;
    uniform float playerMood;
    uniform float eyeAltitude;
    uniform float far;
    uniform float frameTime;
    uniform float near;
    uniform float frameTimeCounter;
    uniform float viewHeight;
    uniform float nightVision;
    uniform float viewWidth;

    const float drynessHalflife = 240.0;
    const float wetnessHalflife = 240.0;

    uniform ivec2 atlasSize;
    uniform ivec2 eyeBrightness;

    uniform vec3 relativeEyePosition;
    uniform vec3 cameraPosition;
    uniform vec3 skyColor;
    uniform vec3 fogColor;
    uniform vec3 previousCameraPosition;

    uniform vec4 entityColor;
    uniform vec4 lightningBoltPosition;

    const bool shadowHardwareFiltering = true;
    const float shadowDistanceRenderMul = 1.0;
    const float entityShadowDistanceMul = 0.125;

    const float ambientOcclusionLevel = 1.0;

    uniform mat4 gbufferModelView;
    uniform mat4 shadowModelView;
    uniform mat4 gbufferModelViewInverse;
    uniform mat4 shadowProjectionInverse;
    uniform mat4 gbufferPreviousModelView;
    uniform mat4 shadowModelViewInverse;
    uniform mat4 gbufferPreviousProjection;
    uniform mat4 shadowProjection;

    uniform sampler2D colortex0;
    uniform sampler2D colortex1;
    uniform sampler2D colortex2;
    uniform sampler2D colortex3;
    uniform sampler2D colortex4;
    uniform sampler2D colortex5;
    uniform sampler2D colortex6;
    uniform sampler2D colortex7;
    uniform sampler2D colortex8;
    uniform sampler2D colortex9;
    uniform sampler2D depthtex0;
    uniform sampler2D depthtex1;
    uniform sampler2D depthtex2;
    uniform sampler2D gaux1;
    uniform sampler2D gaux2;
    uniform sampler2D gaux4;
    uniform sampler2D normals;
    uniform sampler2D noisetex;
    uniform sampler2D specular;
    uniform sampler2D tex;

    uniform ivec3 cameraPositionInt;
    uniform ivec3 previousCameraPositionInt;
    uniform vec3 cameraPositionFract;
    uniform vec3 previousCameraPositionFract;

    #ifdef IS_IRIS
        uniform int renderStage;
    #endif

    #if LU_SHADOW_QUALITY > -1 || defined LU_LIGHTSHAFTS_ACTIVE || defined FF_BLOCKLIGHT
        uniform sampler2D shadowcolor0;
        uniform sampler2D shadowcolor1;

        uniform sampler2DShadow shadowtex1;

        #ifdef LU_COMPOSITE
            uniform sampler2D shadowtex0;
        #else
            uniform sampler2DShadow shadowtex0;
        #endif
    #endif

    #if !defined DH_TERRAIN && !defined DH_WATER
        uniform mat4 gbufferProjection;
        uniform mat4 gbufferProjectionInverse;
    #endif

    #ifdef DISTANT_HORIZONS
        uniform int dhRenderDistance;

        uniform mat4 dhProjection;
        uniform mat4 dhProjectionInverse;

        uniform sampler2D dhDepthTex;
        uniform sampler2D dhDepthTex1;
    #endif

    #if LU_COLORED_LIGHTING_INTERNAL > 0
        uniform usampler3D voxel_sampler;
        uniform sampler3D floodfill_sampler;
        uniform sampler3D floodfill_sampler_copy;
    #endif

    #ifdef LU_PUDDLE_VOXELIZATION
        uniform usampler2D puddle_sampler;
    #endif

    #endif
    // === End of inlined globals.glsl =======================================

    #if LU_SHADOW_QUALITY == -1
      float timeAngle = worldTime / 24000.0;
    #else
      float tAmin     = fract(sunAngle - 0.033333333);
      float tAlin     = tAmin < 0.433333333 ? tAmin * 1.15384615385 : tAmin * 0.882352941176 + 0.117647058824;
      float hA        = tAlin > 0.5 ? 1.0 : 0.0;
      float tAfrc     = fract(tAlin * 2.0);
      float tAfrs     = tAfrc*tAfrc*(3.0-2.0*tAfrc);
      float tAmix     = hA < 0.5 ? 0.3 : -0.1;
      float timeAngle = (tAfrc * (1.0-tAmix) + tAfrs * tAmix + hA) * 0.5;
    #endif

    #include "/lib/sky/globals.glsl"

    #ifndef DISTANT_HORIZONS
        float renderDistance = far;
    #else
        float renderDistance = float(dhRenderDistance);
    #endif

    const float shadowMapBias = 1.0 - 25.6 / shadowDistance;
    #ifndef LU_DREAM_TWEAKED_LIGHTING
        float noonFactor = sqrt(max(sin(timeAngle*6.28318530718),0.0));
    #else
        float noonFactor = pow(max(sin(timeAngle*6.28318530718),0.0), 0.2);
    #endif

float nightFactor = max(sin(timeAngle*(-6.28318530718)),0.0);
float invNightFactor = 1.0 - nightFactor;
float rainFactor2 = rainFactor * rainFactor;
float invRainFactor = 1.0 - rainFactor;
float invNoonFactor = 1.0 - noonFactor;
float invNoonFactor2 = invNoonFactor * invNoonFactor;

float vsBrightness = clamp(screenBrightness, 0.0, 1.0);

int modifiedWorldDay = int(mod(worldDay, 100) + 5.0);
float syncedTime = (worldTime + modifiedWorldDay * 24000) * 0.05;

#if IRIS_VERSION >= 10800
    vec3 cameraPositionBestFract = cameraPositionFract;
#else
    vec3 cameraPositionBestFract = fract(cameraPosition);
#endif

#include "/lib/colors/block_light.glsl"

#if LU_CAVE_LIGHTING < 100
    vec3 caveFogColor = caveFogColorRaw * 0.7;
#elif LU_CAVE_LIGHTING == 100
    vec3 caveFogColor = caveFogColorRaw * (0.7 + 0.3 * vsBrightness); // Default
#elif LU_CAVE_LIGHTING > 100
    vec3 caveFogColor = caveFogColorRaw;
#endif

#if LU_WATERCOLOR_MODE >= 2
    vec3 underwaterColorM1 = pow(fogColor, vec3(0.33, 0.21, 0.26));
#else
    vec3 underwaterColorM1 = vec3(0.46, 0.62, 1.0);
#endif
#ifndef LU_UNDERWATERCOLOR_CHANGED
    vec3 underwaterColorM2 = underwaterColorM1;
#else
    vec3 underwaterColorM2 = underwaterColorM1 * vec3(LU_UNDERWATERCOLOR_RM, LU_UNDERWATERCOLOR_GM, LU_UNDERWATERCOLOR_BM);
#endif
vec3 waterFogColor = underwaterColorM2 * vec3(0.2 + 0.1 * vsBrightness);

#if LU_NETHER_COLOR_MODE == 3
    float netherColorMixer = inNetherWastes + inCrimsonForest + inWarpedForest + inBasaltDeltas + inSoulValley;
    vec3 netherColor = mix(
        fogColor * 0.6 + 0.2 * normalize(fogColor + 0.0001),
        (
            inNetherWastes * vec3(0.38, 0.15, 0.05) + inCrimsonForest * vec3(0.33, 0.07, 0.04) +
            inWarpedForest * vec3(0.18, 0.1, 0.25) + inBasaltDeltas * vec3(0.25, 0.235, 0.23) +
            inSoulValley * vec3(0.1, vec2(0.24))
        ),
        netherColorMixer
    );
#elif LU_NETHER_COLOR_MODE == 2
    vec3 netherColor = fogColor * 0.6 + 0.2 * normalize(fogColor + 0.0001);
#elif LU_NETHER_COLOR_MODE == 0
    vec3 netherColor = vec3(0.7, 0.26, 0.08) * 0.6;
#endif

#if LU_WEATHER_TEX_OPACITY == 100
    const float rainTexOpacity = 0.25;
    const float snowTexOpacity = 0.5;
#else
    #define LU_WEATHER_TEX_OPACITY_M 100.0 / LU_WEATHER_TEX_OPACITY
    const float rainTexOpacity = pow(0.25, LU_WEATHER_TEX_OPACITY_M);
    const float snowTexOpacity = pow(0.5, LU_WEATHER_TEX_OPACITY_M);
#endif

#ifdef FRAGMENT_SHADER
    ivec2 texelCoord = ivec2(gl_FragCoord.xy);
#endif
