#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
    
    decode=pow(decode,2.)*5.;
    #ifdef LIGHT_JITTER
    decode*=jitter1*jitter2*jitter3;
    #endif
    decode+=pow(decode,.4)*.1;
    
    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.-.95*rainStrength);
    vec3 sceneLighting=mix(ambientCol,lightCol,fullShadow*shadowMult);
    sceneLighting*=lightmap.y*lightmap.y*lightmap.y;
    
    float shadowTime=worldTime;
    shadowTime-=floor(shadowTime/24000)*24000;
    if(shadowTime<12800){
        shadowTime=clamp((12800-shadowTime)/400,0.,1.);
    }else if(shadowTime<23200){
        if(shadowTime<18000)shadowTime=clamp((shadowTime-12800)/400,0.,1.);
        if(shadowTime>18000)shadowTime=clamp((23200-shadowTime)/400,0.,1.);
    }else{
        shadowTime=clamp((shadowTime-23200)/400,0.,1.);
    }
    fullShadow*=clamp(pow(shadowTime,2),0.,1.);
    
    #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
    
    vec3 sceneLighting=netherColSqrt.rgb*.1;
    #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.0, 0.4941, 0.0235);
        }
        #endif
    }
    #endif
    
    float newLightmap=pow(lightmap.x,20.)*(EMISSIVE_BRIGHTNESS+.5)+lightmap.x*.7;

    handTorchLightmap=CurveBlockLight(handTorchLightmap);
    newLightmap=CurveBlockLight(newLightmap);
    
    vec3 blockLighting=max(blocklightCol*sqrt(newLightmap),handLightCol * sqrt(handTorchLightmap));
    
    float minLighting=(.009*screenBrightness+.001)*(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
}