-- =============================================================================
-- ETB — Data/ModelCameras.lua
-- =============================================================================
-- Per-slot / per-weapon-type camera framing harvested from the native MoP
-- Classic Appearances wardrobe (Interface 50504), confirmed via ModelProbe's
-- click-driven sweep + grab (each value agreed across all 18 native cells).
--
-- The native cells are DressUpModel frames. Framing is applied with manual
-- SetPosition / SetFacing / SetCameraDistance (SetCameraID does NOT exist on the
-- model in this client). Distance is a constant 2.9416 for every slot.
--
-- Usage by the model-view feature:
--   local cam = ETB.ModelCameras.Get(key)            -- key = armor slot or weapon-type
--   model:SetPosition(cam.pos[1], cam.pos[2], cam.pos[3])
--   model:SetFacing(cam.facing)
--   model:SetCameraDistance(cam.dist)
--
-- Armor models use SetUnit("player") (framing zooms to the body region).
-- Weapon models are bodiless (no SetUnit); SetItemAppearance floats the weapon.
-- =============================================================================

local ADDON_NAME, NS = ...
local ETB = NS.ETB

local DIST = 2.9416

local CAM = {
    -- ARMOR (framed on the player body; 11/11 confirmed) ----------------------
    head      = { pos = { 3.4518,  0.0789, -1.7632 }, facing = -0.5447, dist = DIST },
    shoulder  = { pos = { 3.3487, -0.1645, -1.5724 }, facing = -0.3349, dist = DIST },
    back      = { pos = { 3.1776,  0.0066, -1.1711 }, facing = -2.6480, dist = DIST },
    chest     = { pos = { 3.2237,  0.0197, -1.3750 }, facing = -0.3100, dist = DIST },
    shirt     = { pos = { 3.2237,  0.0197, -1.3750 }, facing = -0.3100, dist = DIST },
    tabard    = { pos = { 3.2566,  0.0263, -1.2961 }, facing = -0.2280, dist = DIST },
    wrist     = { pos = { 3.4357,  0.1579, -1.0592 }, facing =  0.8455, dist = DIST },
    hands     = { pos = { 3.2749, -0.1118, -0.9737 }, facing = -0.8167, dist = DIST },
    waist     = { pos = { 3.2405,  0.0132, -1.1250 }, facing =  0.0082, dist = DIST },
    legs      = { pos = { 2.9079, -0.0132, -0.7171 }, facing = -0.0447, dist = DIST },
    feet      = { pos = { 3.1513,  0.0132, -0.2303 }, facing = -0.4778, dist = DIST },

    -- WEAPONS (bodiless / floating; 15/15 confirmed) -------------------------
    one_handed_axes   = { pos = {  0.3026, -0.0724, -0.0329 }, facing =  1.5043, dist = DIST },
    one_handed_swords = { pos = {  0.0000, -0.0066, -0.0395 }, facing =  1.4200, dist = DIST },
    one_handed_maces  = { pos = {  0.9145, -0.0592, -0.0461 }, facing =  1.4400, dist = DIST },
    daggers           = { pos = {  1.4408, -0.0066, -0.0197 }, facing =  1.4300, dist = DIST },
    fist_weapons      = { pos = {  0.5000,  0.0395, -0.0132 }, facing =  1.5089, dist = DIST },
    two_handed_axes   = { pos = {  0.2500, -0.2039, -0.2368 }, facing =  1.4400, dist = DIST },
    two_handed_swords = { pos = { -0.9737, -0.0461, -0.1053 }, facing =  1.3996, dist = DIST },
    two_handed_maces  = { pos = {  0.7500, -0.1974, -0.2368 }, facing =  1.4900, dist = DIST },
    staves            = { pos = {  0.5000, -0.3092, -0.4145 }, facing =  1.5300, dist = DIST },
    polearms          = { pos = { -0.7500, -0.2434, -0.2763 }, facing =  1.4700, dist = DIST },
    guns              = { pos = { -0.2237, -0.0461,  0.0000 }, facing =  1.0400, dist = DIST },
    wands             = { pos = {  1.7500, -0.0132, -0.0263 }, facing =  1.4300, dist = DIST },
    shields           = { pos = {  0.7500,  0.0197, -0.0066 }, facing = -1.3750, dist = DIST },
    held_in_off_hand  = { pos = {  1.0000, -0.0197, -0.0263 }, facing =  1.3600, dist = DIST },
    bows              = { pos = { -1.0461,  0.0592, -0.0658 }, facing = -7.5200, dist = DIST },
    crossbows         = { pos = { -0.1316, -0.0526,  0.0197 }, facing =  2.4171, dist = DIST },
}

-- Inventory-type → armor key (for resolving an item's slot to a camera).
local INVTYPE_TO_KEY = {
    INVTYPE_HEAD = "head", INVTYPE_SHOULDER = "shoulder", INVTYPE_CLOAK = "back",
    INVTYPE_CHEST = "chest", INVTYPE_ROBE = "chest", INVTYPE_BODY = "shirt",
    INVTYPE_TABARD = "tabard", INVTYPE_WRIST = "wrist", INVTYPE_HAND = "hands",
    INVTYPE_WAIST = "waist", INVTYPE_LEGS = "legs", INVTYPE_FEET = "feet",
}

-- Weapon subclassID (classID == 2) → camera key. MoP Classic subclass ids.
local WEAPON_SUBCLASS = {
    [0]  = "one_handed_axes",   [1]  = "two_handed_axes",
    [2]  = "bows",              [3]  = "guns",
    [4]  = "one_handed_maces",  [5]  = "two_handed_maces",
    [6]  = "polearms",          [7]  = "one_handed_swords",
    [8]  = "two_handed_swords", [10] = "staves",
    [13] = "fist_weapons",      [15] = "daggers",
    [18] = "crossbows",         [19] = "wands",
}

ETB.ModelCameras = {
    cameras = CAM,
    invTypeToKey = INVTYPE_TO_KEY,
    weaponSubclass = WEAPON_SUBCLASS,
    dist = DIST,

    -- Returns the camera for a key, falling back to the head framing so a model
    -- is never left at a degenerate (0,0,0 / dist 0) camera.
    Get = function(key)
        return (key and CAM[key]) or CAM.head
    end,

    -- Resolve an armor inventory type (e.g. "INVTYPE_HEAD") to its camera.
    ForInvType = function(invType)
        return CAM[INVTYPE_TO_KEY[invType or ""] or "head"] or CAM.head
    end,

    -- Resolve an itemID to (cameraKey, bodiless). bodiless == true means render
    -- with no player body (weapons, shields, held-in-off-hand float); false
    -- means SetUnit("player") so armor frames on the body region.
    ResolveKey = function(itemID)
        if not itemID then return "head", false end
        local _, _, _, equipLoc, _, classID, subclassID = GetItemInfoInstant(itemID)
        if equipLoc == "INVTYPE_SHIELD" then return "shields", true end
        if equipLoc == "INVTYPE_HOLDABLE" then return "held_in_off_hand", true end
        local armorKey = INVTYPE_TO_KEY[equipLoc or ""]
        if armorKey then return armorKey, false end
        if classID == 2 then
            local wk = WEAPON_SUBCLASS[subclassID or -1]
            if wk then return wk, true end
        end
        return "head", false
    end,
}
