use super::*;

pub fn validate_surface_evaluator(source: &str) -> Result<(), String> {
    if !source.contains("fn evaluate(") {
        return Err("surface WGSL must define `fn evaluate(`".into());
    }
    for forbidden in [
        "@group",
        "@binding",
        "@vertex",
        "@fragment",
        "@compute",
        "var<",
        "rayQuery",
        "dpdx",
        "dpdy",
        "fwidth",
        "discard",
        "Barrier",
        "subgroup",
        "textureStore",
        "atomic",
    ] {
        if source.contains(forbidden) {
            return Err(format!(
                "surface WGSL uses forbidden construct `{forbidden}`"
            ));
        }
    }
    let validation_source = format!("{EVALUATOR_VALIDATION_PRELUDE}\n{source}");
    let module = naga::front::wgsl::parse_str(&validation_source)
        .map_err(|error| format!("surface WGSL syntax error: {error}"))?;
    naga::valid::Validator::new(
        naga::valid::ValidationFlags::all(),
        naga::valid::Capabilities::empty(),
    )
    .validate(&module)
    .map_err(|error| format!("surface WGSL validation error: {error}"))?;
    Ok(())
}

pub(super) const EVALUATOR_VALIDATION_PRELUDE: &str = r#"
struct SurfaceInput {
    uv0: vec2<f32>,
    world_position: vec3<f32>,
    world_normal: vec3<f32>,
}
struct SurfaceParams { lanes: array<vec4<f32>, 16>, }
struct SurfaceSamples { values: array<vec4<f32>, 8>, }
struct Surface {
    base_color: vec4<f32>,
    normal_ts: vec3<f32>,
    emissive: vec3<f32>,
    metallic: f32,
    perceptual_roughness: f32,
    reflectance: f32,
    occlusion: f32,
    model: u32,
}
fn surface_default() -> Surface {
    var surface: Surface;
    surface.base_color = vec4<f32>(1.0);
    surface.normal_ts = vec3<f32>(0.0, 0.0, 1.0);
    surface.emissive = vec3<f32>(0.0);
    surface.metallic = 0.0;
    surface.perceptual_roughness = 0.5;
    surface.reflectance = 0.5;
    surface.occlusion = 1.0;
    surface.model = 0u;
    return surface;
}
"#;

pub fn compose_surface_shader(evaluator: &str) -> String {
    format!(
        "{}\n{}\n{}",
        include_str!("../surface_header.wgsl"),
        evaluator,
        include_str!("../surface_footer.wgsl")
    )
}
