use anyhow::Result;
use byteorder::{LittleEndian, ReadBytesExt};
use serde::{Deserialize, Serialize};
use std::io::{Cursor, Read};
use std::path::Path;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HueEntry {
    pub id: u32,
    pub name: String,
    /// 32 colors as RGBA u32 values.
    pub colors: Vec<u32>,
}

/// Read all hues from hues.mul.
/// Format: 375 blocks × 8 hues = 3000 hues.
/// Each hue: 32×u16 colors + u16 tableStart + u16 tableEnd + 20-byte name.
pub fn read_hues(hues_path: &Path) -> Result<Vec<HueEntry>> {
    let data = std::fs::read(hues_path)?;
    let mut cursor = Cursor::new(&data);
    let mut hues = Vec::new();

    for block in 0..375u32 {
        // Block header (4 bytes, skip)
        let _header = cursor.read_u32::<LittleEndian>()?;

        for h in 0..8u32 {
            let id = block * 8 + h;
            let mut raw_colors = [0u16; 32];
            for c in raw_colors.iter_mut() {
                *c = cursor.read_u16::<LittleEndian>()?;
            }
            let _table_start = cursor.read_u16::<LittleEndian>()?;
            let _table_end = cursor.read_u16::<LittleEndian>()?;

            let mut name_buf = [0u8; 20];
            cursor.read_exact(&mut name_buf)?;
            let name = String::from_utf8_lossy(&name_buf)
                .trim_end_matches('\0')
                .to_string();

            let colors = raw_colors
                .iter()
                .map(|&c| {
                    let r = ((c >> 10) & 0x1F) as u32;
                    let g = ((c >> 5) & 0x1F) as u32;
                    let b = (c & 0x1F) as u32;
                    let r = (r << 3) | (r >> 2);
                    let g = (g << 3) | (g >> 2);
                    let b = (b << 3) | (b >> 2);
                    (r << 24) | (g << 16) | (b << 8) | 0xFF
                })
                .collect();

            hues.push(HueEntry { id, name, colors });
        }
    }

    Ok(hues)
}
