// Copyright (c) 2021 The Vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use heck::SnakeCase;
use indexmap::IndexMap;
use regex::Regex;
use std::{
    collections::{hash_map::Entry, HashMap},
    io::Write,
};
use vk_parse::{Extension, Type, TypeMember, TypeMemberMarkup, TypeSpec};

// This is not included in vk.xml, so it's added here manually
fn requires_features(name: &str) -> &'static [&'static str] {
    match name {
        "sparseImageInt64Atomics" => &["shaderImageInt64Atomics"],
        "sparseImageFloat32Atomics" => &["shaderImageFloat32Atomics"],
        "sparseImageFloat32AtomicAdd" => &["shaderImageFloat32AtomicAdd"],
        _ => &[],
    }
}

fn conflicts_features(name: &str) -> &'static [&'static str] {
    match name {
        "shadingRateImage" => &[
            "pipelineFragmentShadingRate",
            "primitiveFragmentShadingRate",
            "attachmentFragmentShadingRate",
        ],
        "fragmentDensityMap" => &[
            "pipelineFragmentShadingRate",
            "primitiveFragmentShadingRate",
            "attachmentFragmentShadingRate",
        ],
        "pipelineFragmentShadingRate" => &["shadingRateImage", "fragmentDensityMap"],
        "primitiveFragmentShadingRate" => &["shadingRateImage", "fragmentDensityMap"],
        "attachmentFragmentShadingRate" => &["shadingRateImage", "fragmentDensityMap"],
        _ => &[],
    }
}

fn required_by_extensions(name: &str) -> &'static [&'static str] {
    match name {
        "shaderDrawParameters" => &["VK_KHR_shader_draw_parameters"],
        "drawIndirectCount" => &["VK_KHR_draw_indirect_count"],
        "samplerMirrorClampToEdge" => &["VK_KHR_sampler_mirror_clamp_to_edge"],
        "descriptorIndexing" => &["VK_EXT_descriptor_indexing"],
        "samplerFilterMinmax" => &["VK_EXT_sampler_filter_minmax"],
        "shaderOutputViewportIndex" => &["VK_EXT_shader_viewport_index_layer"],
        "shaderOutputLayer" => &["VK_EXT_shader_viewport_index_layer"],
        _ => &[],
    }
}

pub fn write<W: Write>(
    writer: &mut W,
    types: &HashMap<&str, (&Type, Vec<&str>)>,
    extensions: &IndexMap<&str, &Extension>,
) {
    write!(writer, "crate::device::features::features! {{").unwrap();

    for feat in make_vulkano_features(types) {
        write!(writer, "\n\t{} => {{", feat.member).unwrap();
        write_doc(writer, &feat);
        write!(writer, "\n\t\tffi_name: {},", feat.ffi_name).unwrap();
        write!(
            writer,
            "\n\t\tffi_members: [{}],",
            feat.ffi_members.join(", ")
        )
        .unwrap();
        write!(
            writer,
            "\n\t\trequires_features: [{}],",
            feat.requires_features.join(", ")
        )
        .unwrap();
        write!(
            writer,
            "\n\t\tconflicts_features: [{}],",
            feat.conflicts_features.join(", ")
        )
        .unwrap();
        write!(
            writer,
            "\n\t\trequired_by_extensions: [{}],",
            feat.required_by_extensions.join(", ")
        )
        .unwrap();
        write!(writer, "\n\t}},").unwrap();
    }

    write!(
        writer,
        "\n}}\n\ncrate::device::features::features_ffi! {{\n\tapi_version,\n\tdevice_extensions,\n\tinstance_extensions,"
    )
    .unwrap();

    for ffi in make_vulkano_features_ffi(types, extensions) {
        write!(writer, "\n\t{} => {{", ffi.member).unwrap();
        write!(writer, "\n\t\tty: {},", ffi.ty).unwrap();
        write!(
            writer,
            "\n\t\tprovided_by: [{}],",
            ffi.provided_by.join(", ")
        )
        .unwrap();
        write!(writer, "\n\t\tconflicts: [{}],", ffi.conflicts.join(", ")).unwrap();
        write!(writer, "\n\t}},").unwrap();
    }

    write!(writer, "\n}}").unwrap();
}

#[derive(Clone, Debug)]
struct VulkanoFeature {
    member: String,
    vulkan_doc: String,
    ffi_name: String,
    ffi_members: Vec<String>,
    requires_features: Vec<String>,
    conflicts_features: Vec<String>,
    required_by_extensions: Vec<String>,
}

fn make_vulkano_features(types: &HashMap<&str, (&Type, Vec<&str>)>) -> Vec<VulkanoFeature> {
    let mut features = HashMap::new();
    std::iter::once(&types["VkPhysicalDeviceFeatures"])
        .chain(sorted_structs(types).into_iter())
        .filter(|(ty, _)| {
            ty.name.as_ref().map(|s| s.as_str()) == Some("VkPhysicalDeviceFeatures")
                || ty.structextends.as_ref().map(|s| s.as_str())
                    == Some("VkPhysicalDeviceFeatures2,VkDeviceCreateInfo")
        })
        .for_each(|(ty, _)| {
            let vulkan_ty_name = ty.name.as_ref().unwrap();

            let ty_name = if vulkan_ty_name == "VkPhysicalDeviceFeatures" {
                "features_vulkan10.features".to_owned()
            } else {
                ffi_member(vulkan_ty_name)
            };

            members(ty).into_iter().for_each(|name| {
                let member = name.to_snake_case();
                match features.entry(member.clone()) {
                    Entry::Vacant(entry) => {
                        let requires_features = requires_features(name);
                        let conflicts_features = conflicts_features(name);
                        let required_by_extensions = required_by_extensions(name);

                        entry.insert(VulkanoFeature {
                            member: member.clone(),
                            vulkan_doc: format!("{}.html#features-{}", vulkan_ty_name, name),
                            ffi_name: member,
                            ffi_members: vec![ty_name.to_owned()],
                            requires_features: requires_features
                                .into_iter()
                                .map(|&s| s.to_snake_case())
                                .collect(),
                            conflicts_features: conflicts_features
                                .into_iter()
                                .map(|&s| s.to_snake_case())
                                .collect(),
                            required_by_extensions: required_by_extensions
                                .iter()
                                .map(|vk_name| vk_name.strip_prefix("VK_").unwrap().to_snake_case())
                                .collect(),
                        });
                    }
                    Entry::Occupied(entry) => {
                        entry.into_mut().ffi_members.push(ty_name.to_owned());
                    }
                };
            });
        });

    let mut names: Vec<_> = features.values().map(|feat| feat.member.clone()).collect();
    names.sort_unstable();
    names
        .into_iter()
        .map(|name| features.remove(&name).unwrap())
        .collect()
}

fn write_doc<W>(writer: &mut W, feat: &VulkanoFeature)
where
    W: Write,
{
    write!(writer, "\n\t\tdoc: \"\n\t\t\t- [Vulkan documentation](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/{})", feat.vulkan_doc).unwrap();

    if !feat.requires_features.is_empty() {
        let links: Vec<_> = feat
            .requires_features
            .iter()
            .map(|ext| format!("[`{}`](crate::device::Features::{0})", ext))
            .collect();
        write!(
            writer,
            "\n\t\t\t- Requires feature{}: {}",
            if feat.requires_features.len() > 1 {
                "s"
            } else {
                ""
            },
            links.join(", ")
        )
        .unwrap();
    }

    if !feat.required_by_extensions.is_empty() {
        let links: Vec<_> = feat
            .required_by_extensions
            .iter()
            .map(|ext| format!("[`{}`](crate::device::DeviceExtensions::{0})", ext))
            .collect();
        write!(
            writer,
            "\n\t\t\t- Required by device extension{}: {}",
            if feat.required_by_extensions.len() > 1 {
                "s"
            } else {
                ""
            },
            links.join(", ")
        )
        .unwrap();
    }

    if !feat.conflicts_features.is_empty() {
        let links: Vec<_> = feat
            .conflicts_features
            .iter()
            .map(|ext| format!("[`{}`](crate::device::Features::{0})", ext))
            .collect();
        write!(
            writer,
            "\n\t\t\t- Conflicts with feature{}: {}",
            if feat.conflicts_features.len() > 1 {
                "s"
            } else {
                ""
            },
            links.join(", ")
        )
        .unwrap();
    }

    write!(writer, "\n\t\t\",").unwrap();
}

#[derive(Clone, Debug)]
struct VulkanoFeatureFfi {
    member: String,
    ty: String,
    provided_by: Vec<String>,
    conflicts: Vec<String>,
}

fn make_vulkano_features_ffi<'a>(
    types: &'a HashMap<&str, (&Type, Vec<&str>)>,
    extensions: &IndexMap<&'a str, &Extension>,
) -> Vec<VulkanoFeatureFfi> {
    let mut feature_included_in: HashMap<&str, Vec<&str>> = HashMap::new();
    sorted_structs(types)
        .into_iter()
        .map(|(ty, provided_by)| {
            let name = ty.name.as_ref().unwrap();
            let provided_by = provided_by
                .iter()
                .map(|provided_by| {
                    if let Some(version) = provided_by.strip_prefix("VK_VERSION_") {
                        format!("api_version >= crate::Version::V{}", version)
                    } else {
                        format!(
                            "{}_extensions.{}",
                            extensions[provided_by].ext_type.as_ref().unwrap().as_str(),
                            provided_by
                                .strip_prefix("VK_")
                                .unwrap()
                                .to_ascii_lowercase()
                        )
                    }
                })
                .collect();
            let mut conflicts = vec![];
            members(ty)
                .into_iter()
                .for_each(|member| match feature_included_in.entry(member) {
                    Entry::Vacant(entry) => {
                        entry.insert(vec![name]);
                    }
                    Entry::Occupied(entry) => {
                        let conflicters = entry.into_mut();
                        conflicters.iter().for_each(|conflicter| {
                            let conflicter = ffi_member(conflicter);
                            if !conflicts.contains(&conflicter) {
                                conflicts.push(conflicter);
                            }
                        });
                        conflicters.push(name);
                    }
                });

            VulkanoFeatureFfi {
                member: ffi_member(name),
                ty: name.strip_prefix("Vk").unwrap().to_owned(),
                provided_by,
                conflicts,
            }
        })
        .collect()
}

fn sorted_structs<'a>(
    types: &'a HashMap<&str, (&'a Type, Vec<&'a str>)>,
) -> Vec<&'a (&'a Type, Vec<&'a str>)> {
    let mut structs: Vec<_> = types
        .values()
        .filter(|(ty, _)| {
            ty.structextends.as_ref().map(|s| s.as_str())
                == Some("VkPhysicalDeviceFeatures2,VkDeviceCreateInfo")
        })
        .collect();
    let regex = Regex::new(r"^VkPhysicalDeviceVulkan\d+Features$").unwrap();
    structs.sort_unstable_by_key(|&(ty, provided_by)| {
        let name = ty.name.as_ref().unwrap();
        (
            !regex.is_match(name),
            if let Some(version) = provided_by
                .iter()
                .find_map(|s| s.strip_prefix("VK_VERSION_"))
            {
                let (major, minor) = version.split_once('_').unwrap();
                major.parse::<i32>().unwrap() << 22 | minor.parse::<i32>().unwrap() << 12
            } else if provided_by
                .iter()
                .find(|s| s.starts_with("VK_KHR_"))
                .is_some()
            {
                i32::MAX - 2
            } else if provided_by
                .iter()
                .find(|s| s.starts_with("VK_EXT_"))
                .is_some()
            {
                i32::MAX - 1
            } else {
                i32::MAX
            },
            name,
        )
    });

    structs
}

fn ffi_member(ty_name: &str) -> String {
    let ty_name = ty_name
        .strip_prefix("VkPhysicalDevice")
        .unwrap()
        .to_snake_case();
    let (base, suffix) = ty_name.rsplit_once("_features").unwrap();
    format!("features_{}{}", base, suffix)
}

fn members(ty: &Type) -> Vec<&str> {
    if let TypeSpec::Members(members) = &ty.spec {
        members
            .iter()
            .filter_map(|member| {
                if let TypeMember::Definition(def) = member {
                    let name = def.markup.iter().find_map(|markup| match markup {
                        TypeMemberMarkup::Name(name) => Some(name.as_str()),
                        _ => None,
                    });
                    if name != Some("sType") && name != Some("pNext") {
                        return name;
                    }
                }
                None
            })
            .collect()
    } else {
        vec![]
    }
}
