use clap::Parser;
use indexmap::{IndexMap, IndexSet};
use rustdoc_types::{Crate, Item, ItemEnum, Visibility};
use serde::Deserialize;
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
pub struct Args {
    #[clap(short, long, value_parser)]
    pub json: Vec<String>,
    #[clap(short, long, value_parser)]
    pub config: String,
    #[clap(long)]
    pub print_errors: bool,
}
#[derive(Deserialize, Debug)]
pub struct Config {
    #[serde(skip_deserializing, default)]
    pub types: IndexMap<String, Newtype>,
    #[serde(rename = "types")]
    pub types_: Vec<Newtype>,
    pub imports: String,
    pub other: String,
    pub lua_api_defaults: String,
    pub primitives: IndexSet<String>,
    pub manual_lua_types: Vec<ManualLuaType>,
}
#[derive(Deserialize, Debug)]
pub struct ManualLuaType {
    pub name: String,
    #[serde(default)]
    pub dont_process: bool,
    #[serde(default)]
    pub proxy_name: String,
    #[serde(default)]
    pub include_global_proxy: bool,
    #[serde(default)]
    pub use_dummy_proxy: bool,
}
#[derive(Deserialize, Debug, Hash, PartialEq, Eq)]
pub struct Newtype {
    #[serde(rename = "type")]
    pub type_: String,
    pub doc: Option<String>,
    #[serde(default)]
    pub source: Source,
    #[serde(default)]
    pub lua_methods: Vec<String>,
    #[serde(default)]
    pub derive_flags: Vec<String>,
    #[serde(default)]
    pub import_path: String,
    #[serde(default)]
    pub traits: Vec<TraitMethods>,
}
#[derive(Deserialize, Debug, PartialEq, Eq, Hash, Default)]
pub struct TraitMethods {
    pub name: String,
    pub import_path: String,
}
#[derive(Deserialize, Debug, PartialEq, Eq, Hash)]
pub struct Source(pub String);
impl Default for Source {
    fn default() -> Self {
        Self("bevy".to_string())
    }
}
impl Newtype {
    pub fn matches_result(&self, item: &Item, source: &Crate) -> bool {
        match &item.inner {
            ItemEnum::Struct(s) => {
                if !s.generics.params.is_empty() {
                    return false;
                }
            }
            ItemEnum::Enum(_) => {}
            _ => return false,
        };
        if source.external_crates.contains_key(&item.crate_id) {
            return false;
        };
        matches!(item.visibility, Visibility::Public)
    }
}