use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum BuildingTypeSourceKind {
    Bca,
    Bty,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BuildingTypeSourceFile {
    pub file_name: String,
    pub raw_stem: String,
    pub canonical_stem: String,
    pub source_kind: BuildingTypeSourceKind,
    #[serde(default)]
    pub byte_len: Option<usize>,
    #[serde(default)]
    pub bca_selector_probe: Option<BuildingTypeBcaSelectorProbe>,
    #[serde(default)]
    pub bty_header_probe: Option<BuildingTypeBtyHeaderProbe>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BuildingTypeSourceEntry {
    pub canonical_stem: String,
    pub raw_stems: Vec<String>,
    pub source_kinds: Vec<BuildingTypeSourceKind>,
    pub file_names: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BuildingTypeBcaSelectorProbe {
    pub byte_0xb8: u8,
    pub byte_0xb8_hex: String,
    pub byte_0xb9: u8,
    pub byte_0xb9_hex: String,
    pub byte_0xba: u8,
    pub byte_0xba_hex: String,
    pub byte_0xbb: u8,
    pub byte_0xbb_hex: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BuildingTypeBtyHeaderProbe {
    pub type_id: u32,
    pub type_id_hex: String,
    pub name_0x04: String,
    pub name_0x22: String,
    pub name_0x40: String,
    pub name_0x5e: String,
    pub name_0x7c: String,
    pub name_0x9a: String,
    pub byte_0xb8: u8,
    pub byte_0xb8_hex: String,
    pub byte_0xb9: u8,
    pub byte_0xb9_hex: String,
    pub byte_0xba: u8,
    pub byte_0xba_hex: String,
    pub dword_0xbb: u32,
    pub dword_0xbb_hex: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BuildingTypeBcaSelectorPatternSummary {
    pub byte_len: usize,
    pub byte_0xb8_hex: String,
    pub byte_0xb9_hex: String,
    pub byte_0xba_hex: String,
    pub byte_0xbb_hex: String,
    pub file_count: usize,
    pub sample_file_names: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BuildingTypeNamedBindingComparison {
    pub bindings_path: String,
    pub named_binding_count: usize,
    pub shared_canonical_stem_count: usize,
    pub binding_only_canonical_stems: Vec<String>,
    pub source_only_canonical_stems: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BuildingTypeRecoveredTableSummary {
    pub recovered_style_themes: Vec<String>,
    pub recovered_source_kinds: Vec<String>,
    pub present_style_station_entries: Vec<String>,
    pub present_standalone_entries: Vec<String>,
    pub recovered_source_family_summaries: Vec<BuildingTypeRecoveredSourceFamilySummary>,
    pub bare_port_warehouse_files: Vec<String>,
    pub nonzero_bty_header_dword_summaries: Vec<BuildingTypeBtyHeaderDwordSummary>,
    pub nonzero_bty_header_name_0x40_summaries: Vec<BuildingTypeBtyHeaderNameSummary>,
    pub nonzero_bty_header_name_0x5e_summaries: Vec<BuildingTypeBtyHeaderNameSummary>,
    pub nonzero_bty_header_name_0x7c_summaries: Vec<BuildingTypeBtyHeaderNameSummary>,
    pub nonzero_bty_header_alias_selector_summaries: Vec<BuildingTypeBtyHeaderAliasSelectorSummary>,
    pub bty_header_name_0x5e_dword_summaries: Vec<BuildingTypeBtyHeaderNameDwordSummary>,
    pub bty_name_0x5e_bca_selector_summaries: Vec<BuildingTypeBtyNameBcaSelectorSummary>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BuildingTypeBtyHeaderDwordSummary {
    pub dword_0xbb: u32,
    pub dword_0xbb_hex: String,
    pub file_count: usize,
    pub sample_file_names: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BuildingTypeRecoveredSourceFamilySummary {
    pub canonical_stem: String,
    pub sample_raw_stem: String,
    pub has_bca_pair: bool,
    pub type_id_hex: String,
    pub name_0x40: String,
    pub name_0x5e: String,
    pub name_0x7c: String,
    pub dword_0xbb_hex: String,
    #[serde(default)]
    pub byte_0xba_hex: Option<String>,
    #[serde(default)]
    pub byte_0xbb_hex: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BuildingTypeBtyHeaderNameSummary {
    pub header_offset_hex: String,
    pub header_value: String,
    pub file_count: usize,
    pub sample_file_names: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BuildingTypeBtyHeaderNameDwordSummary {
    pub header_offset_hex: String,
    pub header_value: String,
    pub dword_0xbb: u32,
    pub dword_0xbb_hex: String,
    pub file_count: usize,
    pub sample_file_names: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BuildingTypeBtyHeaderAliasSelectorSummary {
    pub name_0x40: String,
    pub name_0x5e: String,
    pub name_0x7c: String,
    pub dword_0xbb: u32,
    pub dword_0xbb_hex: String,
    pub byte_0xb8_hex: String,
    pub byte_0xb9_hex: String,
    pub byte_0xba_hex: String,
    pub byte_0xbb_hex: String,
    pub file_count: usize,
    pub sample_file_names: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BuildingTypeBtyNameBcaSelectorSummary {
    pub header_offset_hex: String,
    pub header_value: String,
    pub dword_0xbb: u32,
    pub dword_0xbb_hex: String,
    pub byte_0xba_hex: String,
    pub byte_0xbb_hex: String,
    pub file_count: usize,
    pub sample_file_names: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BuildingTypeSourceReport {
    pub directory_path: String,
    pub bca_file_count: usize,
    pub bty_file_count: usize,
    pub unique_canonical_stem_count: usize,
    pub bca_selector_pattern_count: usize,
    #[serde(default)]
    pub named_binding_comparison: Option<BuildingTypeNamedBindingComparison>,
    pub recovered_table_summary: BuildingTypeRecoveredTableSummary,
    pub notes: Vec<String>,
    pub bca_selector_patterns: Vec<BuildingTypeBcaSelectorPatternSummary>,
    pub files: Vec<BuildingTypeSourceFile>,
    pub entries: Vec<BuildingTypeSourceEntry>,
}
