import package::shared::{VertexInput, VertexOutput, sample_shadow_map, flowmap_path_lighting_with_shadow, all_spotlights_lighting, uniforms, blue_noise_texture, blue_noise_sampler};

@vertex
fn vs_main(input: VertexInput) -> VertexOutput {
    var output: VertexOutput;

    let instance_model = mat4x4<f32>(
        input.instance_model_0,
        input.instance_model_1,
        input.instance_model_2,
        input.instance_model_3
    );

    let world_pos = instance_model * vec4<f32>(input.position, 1.0);
    output.world_position = world_pos.xyz;
    output.clip_position = uniforms.projection * uniforms.view * world_pos;

    let normal_matrix = mat3x3<f32>(
        instance_model[0].xyz,
        instance_model[1].xyz,
        instance_model[2].xyz
    );
    output.world_normal = normalize(normal_matrix * input.normal);

    output.light_space_position = uniforms.light_view_projection * world_pos;
    output.dissolve_amount = 0.0;

    return output;
}

@fragment
fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
    let shadow = sample_shadow_map(input.light_space_position);

    let debug = 0u;

    if debug == 3u {
        return vec4<f32>(shadow, shadow, shadow, 1.0);
    }

    if debug == 2u {
        let proj_coords = input.light_space_position.xyz / input.light_space_position.w;
        return vec4<f32>(proj_coords.x, proj_coords.y, proj_coords.z, 1.0);
    }

    if debug == 1u {
        let proj_coords = input.light_space_position.xyz / input.light_space_position.w;
        let ndc_coords = proj_coords * vec3<f32>(0.5, -0.5, 1.0) + vec3<f32>(0.5, 0.5, 0.0);
        let in_bounds = ndc_coords.x >= 0.0 && ndc_coords.x <= 1.0 &&
                       ndc_coords.y >= 0.0 && ndc_coords.y <= 1.0 &&
                       ndc_coords.z >= 0.0 && ndc_coords.z <= 1.0;
        if in_bounds {
            return vec4<f32>(ndc_coords.x, ndc_coords.y, ndc_coords.z, 1.0);
        } else {
            return vec4<f32>(0.0, 0.0, 0.0, 1.0);
        }
    }

    let tile_scale = 4.0;
    let flowmap_strokes = flowmap_path_lighting_with_shadow(input.world_position, input.clip_position, input.world_normal, tile_scale, shadow);
    let spotlight_strokes = all_spotlights_lighting(input.world_position, input.clip_position, input.world_normal, tile_scale, shadow);
    // let brightness = max(flowmap_strokes, spotlight_strokes);
    let brightness = 0.0;

    return vec4<f32>(brightness, brightness, brightness, 1.0);
}
