/**
 * Манекен — эталонная модель для рига и анимации (docs/plan.md, трек 6).
 * Деревянный болванчик 9×16×4 (~1.6 тайла UNIT=10 — персонаж мельче строений,
 * но силуэт читается: голова, торс, руки/ноги 2×2). Палитра — параметр:
 * у героя и NPC свои цвета (по умолчанию — деревянный болванчик). Части
 * известны при генерации, поэтому привязка к костям передаётся явно
 * (bindNearest здесь не нужен: торс рядом с плечами и Voronoi по pivot
 * отнёс бы его к рукам).
 */
import { VoxelGrid } from '../voxel/grid';
import { encodeModel } from './format';
import type { VoxelModel } from './format';
import { makeRig } from '../animation/rig';
import type { VoxelRig } from '../animation/rig';

// Слоты арт-библии: как в генераторах деревьев/валунов
const TORSO = 4;  // R1 — тёмное дерево / плащ
const LEG = 6;    // P4 — камень / штаны
const HEAD = 7;   // P6 — свет / голова
const ARM = 8;    // R2 — ржавчина / рукава

export const MANNEQUIN_BONES = ['root', 'legL', 'legR', 'armL', 'armR'] as const;
export type MannequinBone = (typeof MANNEQUIN_BONES)[number];

/** Палитра персонажа: цвет слота модели (по умолчанию — дерево). */
export interface MannequinPalette {
    torso?: string;
    legs?: string;
    head?: string;
    arms?: string;
}

export interface Mannequin {
    model: VoxelModel;
    rig: VoxelRig;
}

/** Детерминированный манекен с ригой: root → legL/legR/armL/armR. */
export function mannequin(palette: MannequinPalette = {}): Mannequin {
    const g = new VoxelGrid(9, 16, 4);
    // привязка: индекс вокселя → индекс кости (root=0, legL=1, legR=2, armL=3, armR=4)
    const binding = new Array<number>(g.data.length).fill(-1);
    const put = (x: number, y: number, z: number, slot: number, bone: number): void => {
        g.set(x, y, z, slot);
        binding[x + g.sx * (y + g.sy * z)] = bone;
    };
    // ноги: колонны 2×2 (x2..3 и x5..6), y=0..5 — между ними просвет
    for (let y = 0; y <= 5; y++)
        for (let z = 1; z <= 2; z++)
            for (let dx = 0; dx <= 1; dx++) {
                put(2 + dx, y, z, LEG, 1);
                put(5 + dx, y, z, LEG, 2);
            }
    // торс: x=2..6, y=6..11; голова: x=3..5, y=12..15 (куб на плечах)
    for (let y = 6; y <= 11; y++)
        for (let z = 1; z <= 2; z++)
            for (let x = 2; x <= 6; x++) put(x, y, z, TORSO, 0);
    for (let y = 12; y <= 15; y++)
        for (let z = 1; z <= 2; z++)
            for (let x = 3; x <= 5; x++) put(x, y, z, HEAD, 0);
    // руки: колонны 2×2 по бокам торса, y=6..11 (свободно висят)
    for (let y = 6; y <= 11; y++)
        for (let z = 1; z <= 2; z++)
            for (let dx = 0; dx <= 1; dx++) {
                put(0 + dx, y, z, ARM, 3);
                put(7 + dx, y, z, ARM, 4);
            }
    const model = encodeModel(g, {
        4: palette.torso ?? '#5c3b2e',
        6: palette.legs ?? '#5b5b66',
        7: palette.head ?? '#94949e',
        8: palette.arms ?? '#82503a',
    });
    const rig = makeRig(
        [
            { name: 'root', parent: -1, pivot: [4.5, 0, 2] },   // земля, центр пят
            { name: 'legL', parent: 0, pivot: [3, 6, 2] },      // бедро левой
            { name: 'legR', parent: 0, pivot: [6, 6, 2] },      // бедро правой
            { name: 'armL', parent: 0, pivot: [1, 12, 2] },     // плечо левой
            { name: 'armR', parent: 0, pivot: [8, 12, 2] },     // плечо правой
        ],
        model,
        binding,
    );
    return { model, rig };
}