#if defined OVERWORLD|| defined END
#include "/lib/lighting/shadows.glsl"
#endif

#include "/lib/lighting/colorLighting.glsl"

vec3 toLinear(vec3 color){

	return mix(color / 12.92, pow((color + 0.055) / 1.055, vec3(2.4)), vec3(greaterThan(color, vec3(0.04045))));
}

vec3 BlackBody(float Temperature){

    float t = pow(Temperature, -1.5);
    float lt = log(Temperature);

    vec3 col = vec3(0.0);
         col.x = 220000.0 * t + 0.58039215686;
         col.y = 0.39231372549 * lt - 2.44549019608;
         col.y = Temperature > 6500. ? 138039.215686 * t + 0.72156862745 : col.y;
         col.z = 0.76078431372 * lt - 5.68078431373;
         col = clamp01(col);
         col = Temperature < 1000. ? col * Temperature * 0.001 : col;

    return toLinear(col);
}

float CurveBlockLight(float blockLight){

    float decode=pow(blockLight,1.0/0.25);
    #ifdef LIGHT_JITTER
    const float speed=JITTER_SPEED;
        float jitter1=1.0-sin(frameTimeCounter*1.4*speed+cos(frameTimeCounter*6.9*speed)-sin(frameTimeCounter*9.5*speed))*JITTER_STRENGTH1;
        float jitter2=1.0-sin(frameTimeCounter*1.4*speed+cos(frameTimeCounter*3.0*speed)-sin(frameTimeCounter*4.5*speed))*JITTER_STRENGTH2;
        float jitter3=1.0-sin(frameTimeCounter*1.4*speed+cos(frameTimeCounter*1.5*speed)-sin(frameTimeCounter*2.5*speed))*JITTER_STRENGTH3;
    #endif

    #ifdef LIGHT_JITTER
        decode*=jitter1*jitter2*jitter3;
    #endif

    return decode;
}

void GetLighting(inout vec3 albedo, out vec3 shadow, vec3 viewPos, vec3 worldPos,
                 vec2 lightmap, float smoothLighting, float NoL, float vanillaDiffuse,
                 float parallaxShadow, float emission, float subsurface){

        #if EMISSIVE == 0 || (!defined ADVANCED_MATERIALS && EMISSIVE == 1 )
            emission = 0.0;
        #endif

        lightmap.x = Max0(lightmap.x * 1.15 - 0.15);
        float shadowMult = 1.0;
        float shadowTime = 1.0;
        float ambientColMult = 0.0;
        float lightingColMult = 0.0;

        #ifdef NEWMOON_DISABLER_STUFF
            float moonPhaseOffsetShadows =1.0 - (float((moonPhase == 4)) * (1.0- sunVisibility));
        #else
            float moonPhaseOffsetShadows = 1.0;
        #endif

        #ifndef SSS
            subsurface = 0.0;
        #endif

        #if defined OVERWORLD || defined END
            if (NoL > 0.0 || subsurface > 0.0) {
            shadow = GetShadow(worldPos, NoL, subsurface, lightmap.y);
            }

            shadow *= parallaxShadow;
            NoL = clamp01(NoL * 1.01 - 0.01);

            #ifdef OVERWORLD
                #ifdef NEWMOON_DISABLER_STUFF
                    shadow = mix(shadow,vec3(lightmap.y)*NEWMOON_SHADOWS_LIGHTMAP_CONTROL,(float(moonPhase == 4) * (1.0 - sunVisibility)));
                #else
                    shadow *= moonPhaseOffsetShadows;
                #endif
            #endif

            #ifdef ENABLE_DARKNESS_EFFECT
                #if MC_VERSION >= 11900
                    if (darknessFactor>0.001) shadow *= 0.25;
                #endif
            #endif

            float scattering = 0.0;
            if (subsurface > 0.0){
                float VoL = clamp01(dot(normalize(viewPos.xyz), lightVec) * 0.5 + 0.5);
                scattering = pow(VoL, 16.0) * (1.0 - rainStrengthS) * (1.0 - sunVisibility + 0.5) * (1.0 - moonVisibility + 2.0) * subsurface * moonPhaseOffsetShadows;
                NoL = mix(NoL, 1.0, sqrt(subsurface) * 0.7);
                NoL = mix(NoL, 1.0, scattering);
            }

            vec3 fullShadow = shadow * max(NoL, subsurface * (1.0 - max(rainStrengthS, (1.0 - sunVisibility)) * 0.50));

                #ifdef OVERWORLD

                        shadowMult = 1.0 * (1.0 - 0.95 * rainStrengthS) * shadowFade;
                        shadowTime = abs(sunVisibility - 0.5) * 2.0;
                        shadowTime *= shadowTime;
                        shadowMult *= pow2(shadowTime);

                    if (isEyeInWater == 1) ambientCol *= pow(lightmap.y, 2.5);

                    vec3 lightingCol = pow(lightCol, vec3(1.0 + sunVisibility * 2.0 - timeBrightness));

                    vec3 shadowDecider = fullShadow * shadowMult;
                    if (isEyeInWater == 1) shadowDecider *= pow(min(lightmap.y * 1.03, 1.0), 200.0);

                    vec3 sceneLighting = mix(mix(ambientCol * AMBIENT_MULT_NIGHT, lightingCol * LIGHT_MULT_NIGHT, shadowDecider),
                                             mix(ambientCol * AMBIENT_GROUND_DAY, lightingCol * LIGHT_GROUND_DAY, shadowDecider),
                                             sunVisibility);

                    #ifdef CLASSIC_EXPOSURE
                        sceneLighting *= 4.0 - 3.0 * eBS;
                    #endif

                    #ifdef ENABLE_DARKNESS_EFFECT
                        #if MC_VERSION >= 11900
                            if (darknessFactor>0.001) sceneLighting *= 0.2;
                        #endif
                    #endif

                    float newlightmapy = lightmap.y;
                    if (isEyeInWater == 1 ){

                        #ifdef LIGHT_SHAFT
                        if(length(fullShadow)> 0.01){
                            newlightmapy += 0.1;
                        }
                        #endif

                    }else{
                        sceneLighting *= pow(newlightmapy, 2.5);
                    }
                #endif

                #ifdef END
                    #if BRIGHTNESS_END == 1
                        float brightnessEnd = AMBIANT_END;
                    #elif BRIGHTNESS_END == 2
                        float brightnessEnd = (AMBIANT_END * 100);
                    #endif

                    vec3 ambientEnd = endCol.rgb * 0.17 * brightnessEnd;
                    vec3 lightEnd   = endCol.rgb * 0.37 * brightnessEnd;
                    vec3 shadowDecider = fullShadow * 3.0;
                    vec3 sceneLighting = mix(ambientEnd, lightEnd, shadowDecider);
                    sceneLighting *= 0.20 * (0.7 + 0.3 * screenBrightness2);
                #endif

        #else
            vec3 sceneLighting = netherColSqrt.rgb * 0.07;
        #endif

            float torchDist=length(viewPos);
            float handTorchLightmap=0.0;
            vec3 handLightCol=vec3(0.1);

                float handLight = max(float(heldBlockLightValue), float(heldBlockLightValue2));

                #ifdef COLORED_DYNAMIC_HAND_LIGHT
                    float handLightFactor = clamp((handLight - 2.0 * length(viewPos)) / 25.0, 0.0, 0.9333);
                #else
                    float handLightFactor = clamp((handLight - 1.0 * length(viewPos)) / 15.0, 0.0, 0.9333);
                #endif
                lightmap.x = max(lightmap.x, handLightFactor);

            	if (isLightHandled()){

                handTorchLightmap=clamp01(1.-((torchDist-DIST_MAX_LIGHT)/(DIST_DECLINE-DIST_MAX_LIGHT)))*MAX_LIGHT;

                #ifdef COLORED_DYNAMIC_HAND_LIGHT
                    changeLightingColorByHand(handLightCol);
                #endif
            }

        float LightPower=mix(LIGHTING_POWER_NIGHT, LIGHTING_POWER_DAY, sunVisibility);

        if  (isEyeInWater==0){
            LightPower = mix(LIGHTING_POWER_INSIDE, LightPower, eBS);
        }else if (isEyeInWater==1){
            LightPower = mix(LIGHTING_POWER_UNDERWATER, LightPower, eBS);
        }

        #if CONCENTRATE_BLOCK_LIGHT == 1
            float newLightmap  = pow(lightmap.x, 120.0 / LightPower) * 0.5 + Max0((lightmap.x - 0.05) * 0.925) * (screenBrightness2 * 0.05 + 0.95);
        #elif CONCENTRATE_BLOCK_LIGHT == 2
            float newLightmap  = sqrt(pow(lightmap.x, 120.0 / LightPower) * 0.5 + Max0((lightmap.x - 0.05) * 0.925) * (screenBrightness2 * 0.05 + 0.95));
        #endif

        #ifndef HAND
            #ifdef BLOCKLIGHT_BY_TEMP
                blocklightCol=BlackBody(BLOCKLIGHT_TEMP) * 2.0 * BLOCKLIGHT_LUMA;
            #endif
        #endif

        handTorchLightmap=CurveBlockLight(handTorchLightmap);
        newLightmap=CurveBlockLight(newLightmap);

        #ifdef OVERWORLD

            #if SHINE_BLOCKLIGHTINGLIMITER == 0
                float newLightMap = newLightmap;
            #endif

            #if SHINE_BLOCKLIGHTINGLIMITER == 1
                float newLightMap = pow2(newLightmap);
            #endif

                #ifdef COLORED_LIGHTING
                    float CLr = textureLod(noisetex, 0.00009 * (worldPos.xz + cameraPosition.xz), 0).r;
                    float CLg = textureLod(noisetex, 0.00012 * (worldPos.xz + cameraPosition.xz), 0).r;
                    float CLb = textureLod(noisetex, 0.00018 * (worldPos.xz + cameraPosition.xz), 0).r;
                    blocklightCol = vec3(CLr, CLg, CLb) * 2.2;
                    blocklightCol *= blocklightCol;
                    blocklightCol *= blocklightCol * 0.7;
                    blocklightCol *= sqrt(blocklightCol);
                #endif

            vec3 blockLighting=max(blocklightCol * newLightMap, handLightCol * (handTorchLightmap));
        #else
            vec3 blockLighting=max(blocklightCol * newLightmap, handLightCol * (handTorchLightmap));
        #endif

        float lightFlatten = clamp01(1.0 - pow(1.0 - emission, 128.0));

        vanillaDiffuse = mix(vanillaDiffuse, 1.0, lightFlatten);
        smoothLighting = mix(smoothLighting, 1.0, lightFlatten);

        float shade = pow(vanillaDiffuse, SHADING_STRENGTH);

        vec3 emissiveLighting = albedo.rgb * emission * 4.0 / shade * EMISSIVE_MULTIPLIER;

        float nightVisionLighting=nightVision * 0.25;

        vec3 minLighting = minLightCol * (1.0 - pow2(lightmap.y));
             minLighting *= ((isEyeInWater == 1) ? MINLIGHT_U_I : MINLIGHT_I);

        albedo *= sceneLighting + blockLighting + emissiveLighting + nightVisionLighting + minLighting;
        albedo *= shade;
	    albedo *= smoothLighting;

        #if defined GBUFFERS_HAND && defined HAND_BLOOM_REDUCTION
            float strenghtAlbedo = (albedo.r + albedo.g + albedo.b) / HAND_BLOOM_REDUCTION_STRENGTH;
            if (strenghtAlbedo > 1.0) albedo.rgb = albedo.rgb * max(2.0 - strenghtAlbedo, 0.34);
	    #endif

        #ifdef ENABLE_DARKNESS_EFFECT
		    #if MC_VERSION >= 11900
		        albedo *= 1.0 - clamp(darknessLightFactor * (2.0 - emission * 10000.0), 0.0, 1.0);
	        #endif
        #endif
}