//! Cubism Model 加载与管理
//!
//! 封装 moc3 读取 → revive → model 初始化 → 参数更新 → drawable 数据提取。

use super::core_ffi::{
    alloc_aligned, AlignedBuffer, CubismCore, CsmVector2, CSM_ALIGNOF_MOC, CSM_ALIGNOF_MODEL,
};
use anyhow::{anyhow, Context, Result};
use std::path::Path;

/// 一个 drawable 的渲染所需数据快照
#[derive(Clone)]
pub struct DrawableSnapshot {
    /// 在 Core drawable 数组中的原始索引（用于查 mask 引用）
    pub index: usize,
    pub texture_index: i32,
    pub draw_order: i32,
    pub render_order: i32,
    pub opacity: f32,
    pub blend_mode: i32,
    pub constant_flags: u8,
    pub dynamic_flags: u8,
    pub vertex_positions: Vec<[f32; 2]>,
    pub vertex_uvs: Vec<[f32; 2]>,
    pub indices: Vec<u16>,
    pub multiply_color: [f32; 4],
    pub screen_color: [f32; 4],
    /// 本 drawable 依赖的 mask drawable 索引（空表示无遮罩）
    pub mask_indices: Vec<i32>,
    pub mask_counts: i32,
}

/// Canvas 信息
#[derive(Clone, Copy, Debug, Default)]
pub struct CanvasInfo {
    pub size: [f32; 2],
    pub origin: [f32; 2],
    pub pixels_per_unit: f32,
}

/// 参数信息
pub struct ParameterInfo {
    pub id: String,
    pub min_value: f32,
    pub max_value: f32,
    pub default_value: f32,
}

/// 活跃的 Cubism Model
pub struct CubismModel {
    /// Core 句柄（保持引用防止 .so 卸载）
    _core: std::sync::Arc<CubismCore>,
    /// moc3 原始数据（对齐 64）
    _moc_buf: AlignedBuffer,
    /// moc 指针
    moc: *mut std::ffi::c_void,
    /// model 内存（对齐 16）
    _model_buf: AlignedBuffer,
    /// model 指针
    model: *mut std::ffi::c_void,
    /// 参数数量
    pub param_count: usize,
    /// 参数 ID 列表（与 Core 内部顺序一致）
    pub param_ids: Vec<String>,
    /// 参数索引映射（id → index）
    pub param_index: std::collections::HashMap<String, usize>,
    /// Part 数量
    pub part_count: usize,
    /// Part ID 列表（与 Core 内部顺序一致）
    pub part_ids: Vec<String>,
    /// Part 索引映射（id → index）
    pub part_index: std::collections::HashMap<String, usize>,
    /// drawable 数量
    pub drawable_count: usize,
    /// canvas 信息
    pub canvas: CanvasInfo,
}

// model 指针可跨线程发送（渲染线程独占使用）
unsafe impl Send for CubismModel {}

impl CubismModel {
    /// 从 moc3 文件加载 model
    pub fn load(core: std::sync::Arc<CubismCore>, moc3_path: &Path) -> Result<Self> {
        let moc_data = std::fs::read(moc3_path)
            .with_context(|| format!("读取 moc3 失败: {}", moc3_path.display()))?;

        // 分配 64 对齐内存
        let mut moc_buf = alloc_aligned(moc_data.len(), CSM_ALIGNOF_MOC)?;
        unsafe {
            std::ptr::copy_nonoverlapping(moc_data.as_ptr(), moc_buf.as_ptr(), moc_data.len());
        }

        // 检查一致性
        let valid = unsafe {
            (core.csm_has_moc_consistency)(moc_buf.as_mut_void(), moc_data.len() as u32)
        };
        if valid != 1 {
            return Err(anyhow!("moc3 一致性检查失败（文件损坏或版本不支持）"));
        }

        // Revive moc
        let moc = unsafe {
            (core.csm_revive_moc_in_place)(moc_buf.as_mut_void(), moc_data.len() as u32)
        };
        if moc.is_null() {
            return Err(anyhow!("csmReviveMocInPlace 返回空指针"));
        }

        // 获取 model 所需大小
        let model_size = unsafe { (core.csm_get_sizeof_model)(moc) };
        if model_size == 0 {
            return Err(anyhow!("csmGetSizeofModel 返回 0"));
        }

        // 分配 16 对齐内存
        let mut model_buf = alloc_aligned(model_size as usize, CSM_ALIGNOF_MODEL)?;
        let model = unsafe {
            (core.csm_initialize_model_in_place)(
                moc,
                model_buf.as_mut_void(),
                model_size,
            )
        };
        if model.is_null() {
            return Err(anyhow!("csmInitializeModelInPlace 返回空指针"));
        }

        // 读取参数信息
        let param_count = unsafe { (core.csm_get_parameter_count)(model) } as usize;
        let param_ids_ptr = unsafe { (core.csm_get_parameter_ids)(model) };
        let mut param_ids = Vec::with_capacity(param_count);
        let mut param_index = std::collections::HashMap::new();
        for i in 0..param_count {
            let id = unsafe {
                super::core_ffi::cstr_ptr_to_string(*param_ids_ptr.add(i))
                    .unwrap_or_default()
            };
            param_index.insert(id.clone(), i);
            param_ids.push(id);
        }

        // 读取 part 信息（Pose 会按 PartOpacity 切换互斥部件，如 Haru 的两组手臂）
        let part_count = unsafe { (core.csm_get_part_count)(model) } as usize;
        let part_ids_ptr = unsafe { (core.csm_get_part_ids)(model) };
        let mut part_ids = Vec::with_capacity(part_count);
        let mut part_index = std::collections::HashMap::new();
        for i in 0..part_count {
            let id = unsafe {
                super::core_ffi::cstr_ptr_to_string(*part_ids_ptr.add(i))
                    .unwrap_or_default()
            };
            part_index.insert(id.clone(), i);
            part_ids.push(id);
        }

        // 读取 drawable 数量
        let drawable_count = unsafe { (core.csm_get_drawable_count)(model) } as usize;

        // 读取 canvas 信息
        let mut size = CsmVector2::default();
        let mut origin = CsmVector2::default();
        let mut ppu = 0.0f32;
        unsafe {
            (core.csm_read_canvas_info)(model, &mut size, &mut origin, &mut ppu);
        }

        let canvas = CanvasInfo {
            size: [size.x, size.y],
            origin: [origin.x, origin.y],
            pixels_per_unit: ppu,
        };

        println!(
            "[Live2D] 模型加载成功: 参数={} part={} drawable={} canvas={:?} origin=({:.1},{:.1})x{:.0}ppu",
            param_count, part_count, drawable_count, canvas.size, canvas.origin[0], canvas.origin[1], canvas.pixels_per_unit
        );

        Ok(Self {
            _core: core,
            _moc_buf: moc_buf,
            moc,
            _model_buf: model_buf,
            model,
            param_count,
            param_ids,
            param_index,
            part_count,
            part_ids,
            part_index,
            drawable_count,
            canvas,
        })
    }

    /// 获取参数最小值
    pub fn param_min_values(&self, core: &CubismCore) -> Vec<f32> {
        unsafe {
            let p = (core.csm_get_parameter_minimum_values)(self.model);
            std::slice::from_raw_parts(p, self.param_count).to_vec()
        }
    }

    /// 获取参数最大值
    pub fn param_max_values(&self, core: &CubismCore) -> Vec<f32> {
        unsafe {
            let p = (core.csm_get_parameter_maximum_values)(self.model);
            std::slice::from_raw_parts(p, self.param_count).to_vec()
        }
    }

    /// 获取参数默认值
    pub fn param_default_values(&self, core: &CubismCore) -> Vec<f32> {
        unsafe {
            let p = (core.csm_get_parameter_default_values)(self.model);
            std::slice::from_raw_parts(p, self.param_count).to_vec()
        }
    }

    /// 获取参数值缓冲区（可读写）
    pub fn param_values_mut(&self, core: &CubismCore) -> &mut [f32] {
        unsafe {
            let p = (core.csm_get_parameter_values)(self.model);
            std::slice::from_raw_parts_mut(p, self.param_count)
        }
    }

    /// 按参数 ID 设置值
    pub fn set_param(&self, core: &CubismCore, id: &str, value: f32) -> bool {
        if let Some(&idx) = self.param_index.get(id) {
            self.set_param_by_index(core, idx, value);
            true
        } else {
            false
        }
    }

    /// 按参数索引设置值
    pub fn set_param_by_index(&self, core: &CubismCore, index: usize, value: f32) {
        if index < self.param_count {
            let slice = self.param_values_mut(core);
            slice[index] = value;
        }
    }

    /// 按参数 ID 获取值
    pub fn get_param(&self, core: &CubismCore, id: &str) -> Option<f32> {
        let idx = *self.param_index.get(id)?;
        self.get_param_by_index(core, idx)
    }

    /// 按参数索引获取值
    pub fn get_param_by_index(&self, core: &CubismCore, index: usize) -> Option<f32> {
        if index >= self.param_count {
            return None;
        }
        let slice = self.param_values_mut(core);
        Some(slice[index])
    }

    /// 将所有参数重置为默认值
    pub fn reset_to_default(&self, core: &CubismCore) {
        let defaults = self.param_default_values(core);
        let slice = self.param_values_mut(core);
        for (i, v) in defaults.into_iter().enumerate() {
            slice[i] = v;
        }
    }

    /// 获取 PartOpacity 缓冲区（可读写）
    pub fn part_opacities_mut(&self, core: &CubismCore) -> &mut [f32] {
        unsafe {
            let p = (core.csm_get_part_opacities)(self.model);
            std::slice::from_raw_parts_mut(p, self.part_count)
        }
    }

    /// 按 Part ID 获取索引
    pub fn part_index(&self, id: &str) -> Option<usize> {
        self.part_index.get(id).copied()
    }

    /// 按 Part 索引设置 opacity
    pub fn set_part_opacity_by_index(&self, core: &CubismCore, index: usize, opacity: f32) {
        if index < self.part_count {
            let slice = self.part_opacities_mut(core);
            slice[index] = opacity.clamp(0.0, 1.0);
        }
    }

    /// 按 Part 索引获取 opacity
    pub fn get_part_opacity_by_index(&self, core: &CubismCore, index: usize) -> Option<f32> {
        if index >= self.part_count {
            return None;
        }
        let slice = self.part_opacities_mut(core);
        Some(slice[index])
    }

    /// 更新 model（应用参数变化，重新计算顶点/不透明度等）
    pub fn update(&self, core: &CubismCore) {
        unsafe { (core.csm_update_model)(self.model) };
    }

    /// 重置动态标志
    pub fn reset_dynamic_flags(&self, core: &CubismCore) {
        unsafe { (core.csm_reset_drawable_dynamic_flags)(self.model) };
    }

    /// 获取所有 drawable 的渲染数据快照（按 render order 排序）
    pub fn drawable_snapshots(&self, core: &CubismCore) -> Vec<DrawableSnapshot> {
        let count = self.drawable_count;
        unsafe {
            let render_orders = (core.csm_get_render_orders)(self.model);
            let texture_indices = (core.csm_get_drawable_texture_indices)(self.model);
            let draw_orders = (core.csm_get_drawable_draw_orders)(self.model);
            let opacities = (core.csm_get_drawable_opacities)(self.model);
            let blend_modes = (core.csm_get_drawable_blend_modes)(self.model);
            let const_flags = (core.csm_get_drawable_constant_flags)(self.model);
            let dyn_flags = (core.csm_get_drawable_dynamic_flags)(self.model);
            let mask_counts = (core.csm_get_drawable_mask_counts)(self.model);
            let vertex_counts = (core.csm_get_drawable_vertex_counts)(self.model);
            let vertex_positions = (core.csm_get_drawable_vertex_positions)(self.model);
            let vertex_uvs = (core.csm_get_drawable_vertex_uvs)(self.model);
            let index_counts = (core.csm_get_drawable_index_counts)(self.model);
            let indices = (core.csm_get_drawable_indices)(self.model);
            let multiply_colors = (core.csm_get_drawable_multiply_colors)(self.model);
            let screen_colors = (core.csm_get_drawable_screen_colors)(self.model);
            let masks = (core.csm_get_drawable_masks)(self.model);

            // 先收集每个 drawable 的原始索引
            let mut items: Vec<(usize, i32)> = (0..count)
                .map(|i| (i, *render_orders.add(i)))
                .collect();
            // 按 render_order 升序排列
            items.sort_by_key(|&(_, ro)| ro);

            items
                .into_iter()
                .map(|(i, ro)| {
                    let vc = *vertex_counts.add(i) as usize;
                    let ic = *index_counts.add(i) as usize;
                    let vp = *vertex_positions.add(i);
                    let vu = *vertex_uvs.add(i);
                    let idx = *indices.add(i);

                    let mut verts = Vec::with_capacity(vc);
                    let mut uvs = Vec::with_capacity(vc);
                    for v in 0..vc {
                        let p = *vp.add(v);
                        let u = *vu.add(v);
                        verts.push([p.x, p.y]);
                        uvs.push([u.x, u.y]);
                    }
                    let mut idx_vec = Vec::with_capacity(ic);
                    for k in 0..ic {
                        idx_vec.push(*idx.add(k));
                    }

                    let mc = *multiply_colors.add(i);
                    let sc = *screen_colors.add(i);

                    // 取出本 drawable 的 mask 索引列表
                    let mk = *mask_counts.add(i) as usize;
                    let mut mask_indices: Vec<i32> = Vec::with_capacity(mk);
                    if mk > 0 {
                        let mptr = *masks.add(i);
                        for k in 0..mk {
                            mask_indices.push(*mptr.add(k));
                        }
                    }

                    DrawableSnapshot {
                        index: i,
                        texture_index: *texture_indices.add(i),
                        draw_order: *draw_orders.add(i),
                        render_order: ro,
                        opacity: *opacities.add(i),
                        blend_mode: *blend_modes.add(i),
                        constant_flags: *const_flags.add(i),
                        dynamic_flags: *dyn_flags.add(i),
                        vertex_positions: verts,
                        vertex_uvs: uvs,
                        indices: idx_vec,
                        multiply_color: [mc.x, mc.y, mc.z, mc.w],
                        screen_color: [sc.x, sc.y, sc.z, sc.w],
                        mask_indices,
                        mask_counts: mk as i32,
                    }
                })
                .collect()
        }
    }
}
