#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 NdotL,float quarterNdotU,
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.-shadowMapBias);
    shadowPos=DistortShadow(shadowPos,distortFactor);
    
    float doShadow=float(
        shadowPos.x>0.&&shadowPos.x<1.&&
        shadowPos.y>0.&&shadowPos.y<1.
    );
    
    #ifdef OVERWORLD
    doShadow*=float(lightmap.y>.001);
    #endif
    
    if((NdotL>0.||foliage>.5)){
        if(doShadow>.5){
            float NdotLm=NdotL*.99+.01;
            
            float biasFactor=sqrt(1.-NdotLm*NdotLm)/NdotLm;
            float distortBias=distortFactor*shadowDistance/256.;
            distortBias*=8.*distortBias;
            
            float bias=(distortBias*biasFactor+.05)/shadowMapResolution;
            float offset=1./shadowMapResolution;
            
            if(foliage>.5){
                bias=.0002;
                offset=.0007;
            }
            
            shadow=GetShadow(shadowPos,bias,offset);
            
        }else shadow=vec3(lightmap.y);
    }
    shadow*=parallaxShadow;
    
    vec3 fullShadow=shadow*max(NdotL,foliage);
    
    #ifdef OVERWORLD
    float shadowMult=1.*(1.0 - 0.9*rainStrength);
    
    #ifdef LIGHT_JUMP_FIX
	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);
	}
	fullShadow *= clamp(shadowTime*shadowTime, 0.0, 1.0);
	#endif

    #ifndef SUNLIGHT_LEAK_FIX
    ambientCol *= lightmap.y * lightmap.y * lightmap.y;
	#endif

    vec3 lightingCol = pow(lightCol, vec3(1.0 + sunVisibility));
    vec3 sceneLighting = mix(ambientCol, lightingCol, fullShadow * shadowMult);

    #ifdef SUNLIGHT_LEAK_FIX
    sceneLighting*=lightmap.y*lightmap.y*lightmap.y;
    #endif
#endif

    #ifdef END
    vec3 sceneLighting=endCol*(.075*fullShadow+.05);
    #endif
    
    if(foliage>.5){
        float VdotL=clamp(dot(normalize(viewPos.xyz),lightVec),0.,1.);
        float subsurface=pow(VdotL,25.)*(1.-rainStrength);
        sceneLighting*=3.*fullShadow*subsurface+1.;
    }
    #else
    #ifdef NETHER
	#if MC_VERSION <= 11600
	#else
	if (quarterNdotU < 0.5625) quarterNdotU = 0.5625 + (0.4 - quarterNdotU * 0.7111111111111111);
	#endif
    //vec3 sceneLighting=netherColSqrt.rgb*.1;
    vec3 sceneLighting = netherCol.rgb * (1 - pow(length(fogColor / 3), 0.25)) /** NETHER_I*/ * (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;

    handTorchLightmap=CurveBlockLight(handTorchLightmap);
    newLightmap=CurveBlockLight(newLightmap);
    
    vec3 blockLighting=max(blocklightCol*sqrt(newLightmap),handLightCol * sqrt(handTorchLightmap));

    float minLighting=.000000000001+(MIN_LIGHT*.0035*(screenBrightness*.08+.01))*(1.-eBS);
        
    vec3 emissiveLighting=albedo.rgb*(emissive*4./quarterNdotU);
    
    float nightVisionLighting=nightVision*.25;
    
    albedo*=sceneLighting+blockLighting+emissiveLighting+nightVisionLighting+minLighting;
    albedo*=pow(quarterNdotU,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*1.25;
    #endif
    
    desatAmount=clamp(desatAmount,DESATURATION_FACTOR*.4,1.);
    desatColor*=1.-desatAmount;
    
    albedo.rgb=mix(GetLuminance(albedo.rgb)*desatColor,albedo.rgb,desatAmount);
    #endif
}