use super::names::parse_inline_ascii_name;
use super::read::read_u32_le;
use super::types::WinHeaderWord;

pub(super) const WIN_COMMON_HEADER_LEN: usize = 0x50;
pub(super) const WIN_INLINE_RESOURCE_OFFSET: usize = 0x50;

pub(super) struct CommonHeaderAnalysis {
    pub shared_header_words: Vec<WinHeaderWord>,
    pub matches_observed_common_signature: bool,
    pub inline_root_resource_name: Option<String>,
    pub inline_root_resource_offset: Option<usize>,
    pub inline_root_resource_offset_hex: Option<String>,
}

pub(super) fn analyze_common_header(bytes: &[u8]) -> CommonHeaderAnalysis {
    let header_offsets = [
        0x00usize, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34,
        0x38, 0x3c, 0x40, 0x44, 0x48, 0x4c,
    ];
    let shared_header_words = header_offsets
        .iter()
        .map(|offset| {
            let value = read_u32_le(bytes, *offset).expect("validated common header length");
            WinHeaderWord {
                offset: *offset,
                offset_hex: format!("0x{offset:02x}"),
                value,
                value_hex: format!("0x{value:08x}"),
            }
        })
        .collect::<Vec<_>>();

    let matches_observed_common_signature = read_u32_le(bytes, 0x00) == Some(0x0000_07d0)
        && read_u32_le(bytes, 0x04) == Some(0)
        && read_u32_le(bytes, 0x08) == Some(0)
        && read_u32_le(bytes, 0x0c) == Some(0x8000_0000)
        && read_u32_le(bytes, 0x10) == Some(0x8000_003f)
        && read_u32_le(bytes, 0x14) == Some(0x0000_003f)
        && read_u32_le(bytes, 0x34) == Some(0x0007_d100)
        && read_u32_le(bytes, 0x38) == Some(0x0007_d200)
        && read_u32_le(bytes, 0x40) == Some(0x000b_b800)
        && read_u32_le(bytes, 0x48) == Some(0x000b_b900);

    let inline_root_resource_name = parse_inline_ascii_name(bytes, WIN_INLINE_RESOURCE_OFFSET);
    let inline_root_resource_offset = inline_root_resource_name
        .as_ref()
        .map(|_| WIN_INLINE_RESOURCE_OFFSET + 1);
    let inline_root_resource_offset_hex =
        inline_root_resource_offset.map(|offset| format!("0x{offset:04x}"));

    CommonHeaderAnalysis {
        shared_header_words,
        matches_observed_common_signature,
        inline_root_resource_name,
        inline_root_resource_offset,
        inline_root_resource_offset_hex,
    }
}
