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

vec3 DistortShadow(inout vec3 worldPos,float distortFactor){
    worldPos.xy/=distortFactor;
    worldPos.z*=.2;
    return worldPos*.5+.5;
}
#endif

float CurveBlockLight(float blockLight)
{
    float decode=pow(blockLight,1./.25);
    #ifdef LIGHT_JITTER
    const float speed=JITTER_SPEED;
    float jitter1=1.-sin(frameTimeCounter*1.4*speed+cos(frameTimeCounter*6.9*speed)-sin(frameTimeCounter*9.5*speed))*JITTER_STRENGHT1;
    float jitter2=1.-sin(frameTimeCounter*1.4*speed+cos(frameTimeCounter*3.*speed)-sin(frameTimeCounter*4.5*speed))*JITTER_STRENGHT2;
    float jitter3=1.-sin(frameTimeCounter*1.4*speed+cos(frameTimeCounter*1.5*speed)-sin(frameTimeCounter*2.5*speed))*JITTER_STRENGHT3;
    #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 emissive, float foliage) {

    #if defined OVERWORLD || defined END
    vec3 shadowPos = ToShadow(worldPos);

    float distb = sqrt(shadowPos.x * shadowPos.x + shadowPos.y * shadowPos.y);
    float distortFactor = distb * shadowMapBias + (1.0 - shadowMapBias);
    shadowPos = DistortShadow(shadowPos, distortFactor);

    float doShadow = float(
        shadowPos.x > 0.0 && shadowPos.x < 1.0 &&
        shadowPos.y > 0.0 && shadowPos.y < 1.0
    );

    #ifdef OVERWORLD
    doShadow *= float(lightmap.y > 0.001);
    #endif
    
    if ((NoL > 0.0 || foliage > 0.5)) {
        if (doShadow > 0.5) {
            float NoLm = NoL * 0.99 + 0.01;
            
            float biasFactor = sqrt(1.0 - NoLm * NoLm) / NoLm;
            float distortBias = distortFactor * shadowDistance / 256.0;
            distortBias *= 8.0 * distortBias;
            
            float bias = (distortBias * biasFactor + 0.05) / shadowMapResolution;
            float offset = 1.0 / shadowMapResolution;

            if (foliage > 0.5) {
                bias = 0.0002;
                offset = 0.0006;
            }
            
            shadow=GetShadow(shadowPos,bias,offset);
            
        }else shadow=vec3(lightmap.y);
    }
    shadow*=parallaxShadow;
    
    vec3 fullShadow = shadow * max(NoL, foliage);
    
    #ifdef OVERWORLD
    float shadowMult=1.*(1.0 - 0.9*rainStrength);

	float shadowTime = worldTime;
	shadowTime -= floor(shadowTime / 24000) * 24000;
	if (shadowTime < 12800) {
		shadowTime = clamp((12800 - shadowTime) / 400, 0.0, 1.0);
	} else if (shadowTime < 23200) {
		if (shadowTime < 18000) shadowTime = clamp((shadowTime - 12800) / 400, 0.0, 1.0);
		if (shadowTime > 18000) shadowTime = clamp((23200 - shadowTime) / 400, 0.0, 1.0);
	} else {
		shadowTime = clamp((shadowTime - 23200) / 400, 0.0, 1.0);
	}
	shadowMult *= clamp(shadowTime*shadowTime, 0.0, 1.0);

    ambientCol *= lightmap.y * lightmap.y * lightmap.y;

    vec3 lightingCol = pow(lightCol, vec3(1.0 + sunVisibility));
    vec3 sceneLighting = mix(ambientCol, lightCol, fullShadow * shadowMult);
         sceneLighting *= (4.0 - 3.0 * eBS) * lightmap.y * lightmap.y;
         sceneLighting *=lightmap.y*lightmap.y*lightmap.y;

#endif

    #ifdef END
    vec3 sceneLighting=endCol.rgb*(.1*fullShadow+.07);
    #endif
    
    if (foliage > 0.5) {
        float VoL = clamp(dot(normalize(viewPos.xyz), lightVec), 0.0, 1.0);
        float subsurface = pow(VoL, 25.0) * (1.0 - rainStrength);
        sceneLighting *= 3.0 * fullShadow * subsurface + 1.0;
    }
    #else
    #ifdef NETHER
	#if MC_VERSION <= 11600
	#else
    if (vanillaDiffuse < 0.5625) vanillaDiffuse = 0.5625 + (0.4 - vanillaDiffuse * 0.7111111111111111);
    #endif
    
    vec3 sceneLighting = netherCol.rgb * (1 - pow(length(fogColor / 3), 0.25)) * (screenBrightness*0.5 + 0.5);
    #else
	vec3 sceneLighting = vec3(0.0);
   
    #endif
    #endif

    float torchDist=length(worldPos);
    float handTorchLightmap=0.;
    vec3 handLightCol=vec3(0.1);
    
    #ifdef DYNAMIC_HAND_LIGHT
    if (heldItemId==13001||heldItemId2==13001||
        heldItemId==13002||heldItemId2==13002||
        heldItemId==13003||heldItemId2==13003||
        heldItemId==13004||heldItemId2==13004||
        heldItemId==13005||heldItemId2==13005||
        heldItemId==13006||heldItemId2==13006||
        heldItemId==13007||heldItemId2==13007){

        handTorchLightmap=clamp(1.-((torchDist-DIST_MAX_LIGHT)/(DIST_DECLINE-DIST_MAX_LIGHT)),0.,1.)*MAX_LIGHT;
        
        #ifdef COLORED_DYNAMIC_HAND_LIGHT
        
        if(heldItemId==13002||heldItemId2==13002)
        {
            handLightCol=vec3(.4863,.7686,.9882);
        }
        else if(heldItemId==13003||heldItemId2==13003)
        {
            handLightCol=vec3(0.8863, 0.0235, 0.0235);
        }
        else if(heldItemId==13004||heldItemId2==13004)
        {
            handLightCol=vec3(0.0, 0.1843, 1.0);
        }
        else if(heldItemId==13005||heldItemId2==13005)
        {
            handLightCol=vec3(0.0, 0.8549, 0.6667);
        }
        else if(heldItemId==13006||heldItemId2==13006)
        {
            handLightCol=vec3(0.9765, 0.3412, 1.0);
        }
        else if(heldItemId==13007||heldItemId2==13007)
        {
            handLightCol=vec3(0.0, 0.5255, 0.2824);
        }
        else if(heldItemId==13001||heldItemId2==13001)
        {
            handLightCol=vec3(1.,.3686,0.);
        }
        #endif
    }
    #endif
    
    //float newLightmap=pow(lightmap.x,10.)*(EMISSIVE_BRIGHTNESS+.5)+(lightmap.x*.7);
    float newLightmap  = pow(lightmap.x, 10.0) *(EMISSIVE_BRIGHTNESS+.5)+ max(lightmap.x - 0.1, 0.0) * (screenBrightness*0.25 + 0.9);
    handTorchLightmap=CurveBlockLight(handTorchLightmap);
    newLightmap=CurveBlockLight(newLightmap);

    #ifdef OVERWORLD
    #if SHINE_BLOCKLIGHTINGLIMITER == 0
    float newLightMap = newLightmap;
    #endif
    #if SHINE_BLOCKLIGHTINGLIMITER == 1
    float newLightMap = newLightmap * newLightmap;
    #endif

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

    float minLighting=.000000000001+(MIN_LIGHT*.0035*(screenBrightness*.08+.01))*(1.-eBS);
        
    vec3 emissiveColor = sqrt(albedo * length(albedo) + vec3(0.00001));
    vec3 emissiveLighting = emissiveColor * (emissive * 4.0 / vanillaDiffuse);
    
    float nightVisionLighting=nightVision*.25;
    
    albedo *= sceneLighting + blockLighting + emissiveLighting + nightVisionLighting + minLighting;
    albedo *=pow(vanillaDiffuse,SHADING_STRENGTH)*(smoothLighting*smoothLighting);
    
    #ifdef DESATURATION
    #ifdef OVERWORLD
    float desatAmount=sqrt(max(sqrt(length(fullShadow/3.))*lightmap.y,lightmap.y))*
    sunVisibility*(1.-rainStrength*.4)+sqrt(lightmap.x+emissive);
    
    vec3 desatNight=lightNight/LIGHT_NI;
    vec3 desatWeather=weatherCol.rgb/weatherCol.a*.5;
    
    desatNight*=desatNight;desatWeather*=desatWeather;
    
    float desatNWMix=(1.-sunVisibility)*(1.-rainStrength);
    
    vec3 desatColor=mix(desatWeather,desatNight,desatNWMix);
    desatColor=mix(vec3(.1),desatColor,sqrt(lightmap.y))*10.;
    #endif
    
    #ifdef NETHER
    float desatAmount=sqrt(lightmap.x+emissive);
    
    vec3 desatColor=netherColSqrt.rgb/netherColSqrt.a;
    #endif
    
    #ifdef END
    float desatAmount=sqrt(lightmap.x+emissive);
    
    vec3 desatColor=endCol.rgb*1.25;
    #endif
    
    desatAmount=clamp(desatAmount,DESATURATION_FACTOR*.4,1.);
    desatColor*=1.-desatAmount;
    
    albedo=mix(GetLuminance(albedo)*desatColor,albedo,desatAmount);
    #endif
}