using System;
namespace AcDream.App.UI.Layout;
///
/// Snapshot of all character data the Character window report uses.
/// Passed to as a provider delegate
/// so the window can be rebound to live data in GameWindow or a static
/// fixture in the UI Studio.
///
/// Field names and retail property ids confirmed from
/// gmCharacterInfoUI::UpdatePlayerBirthAgeDeaths (0x004b8cb0),
/// UpdateEnduranceInfo (0x004b8eb0),
/// UpdateInnateAttributeInfo (0x004b87e0),
/// UpdateFakeSkills (0x004b8930),
/// UpdateAugmentations (0x004b9000), and
/// UpdateLoad (0x004b8a20).
///
public sealed class CharacterSheet
{
// ── Identity ──────────────────────────────────────────────────────────────
/// Character name (first line of the report).
public string Name { get; init; } = string.Empty;
/// Character level.
public int Level { get; init; }
/// Race string, e.g. "Aluvian". Null = omit.
public string? Race { get; init; }
/// Heritage string, e.g. "Aluvian Heritage". Null = omit.
public string? Heritage { get; init; }
/// Title string, e.g. "the Adventurer". Null = omit.
public string? Title { get; init; }
// ── Experience / PK (gmStatManagementUI::UpdateExperience 0x004f0a70,
// UpdatePKStatus 0x004f00a0) — the Attributes-tab header strip ──────────
/// Total accrued experience (retail PropertyInt64 1). Header value
/// element 0x10000235 (m_pTotalXPText).
public long TotalXp { get; init; }
/// Experience remaining to the next level. Header value element
/// 0x10000238 (m_pXPToLevelText).
public long XpToNextLevel { get; init; }
/// XP-to-next-level meter fill, 0..1 (retail (cur−base)/(cap−base)).
/// Drives the header meter 0x10000236 (m_pXPToLevelMeter).
public float XpFraction { get; init; }
/// PK status display string, e.g. "Non-Player Killer". Header element
/// 0x10000233 (m_pPKStatusText). Null = omit.
public string? PkStatus { get; init; }
// ── Birth / age / deaths (UpdatePlayerBirthAgeDeaths 0x004b8cb0) ─────────
/// Formatted birth date string (retail InqInt(0x62) → strftime).
/// Null = omit the birth line.
public string? BirthDate { get; init; }
/// Formatted play-time duration (retail InqInt(0x7d) → QueryDuration).
/// Null = omit the age line.
public string? PlayTime { get; init; }
/// Total deaths (retail InqInt(0x2b) = NumDeaths).
public int Deaths { get; init; }
// ── Vitals (UpdateEnduranceInfo 0x004b8eb0) ─────────────────────────────
public int HealthCurrent { get; init; }
public int HealthMax { get; init; }
public int StaminaCurrent { get; init; }
public int StaminaMax { get; init; }
public int ManaCurrent { get; init; }
public int ManaMax { get; init; }
// ── Innate attributes (UpdateInnateAttributeInfo 0x004b87e0) ────────────
// InqAttribute order: 1,2,4,3,5,6 = Strength, Endurance, Quickness, Coordination, Focus, Self.
public int Strength { get; init; }
public int Endurance { get; init; }
public int Quickness { get; init; }
public int Coordination { get; init; }
public int Focus { get; init; }
public int Self { get; init; }
// ── Skills (UpdateFakeSkills 0x004b8930) ────────────────────────────────
// Retail InqInt(0xb5) = SkillCredits; InqInt(0xc0) = AvailableSkillCredits.
// InqInt(0x18) = available skill credits — footer 0x10000245 in the Attributes tab.
public int UnspentSkillCredits { get; init; }
public int SpecializedSkillCredits { get; init; }
///
/// Available (unspent) skill credits shown in the Attributes tab footer State-A.
/// Retail InqInt(0x18) — gmStatManagementUI::DisplayDefaultFooter (0x0049cde0).
/// Element 0x10000243 (footer line-1 value in the studio's 3-line layout).
///
public int SkillCredits { get; init; }
///
/// Unassigned (banked) experience points.
/// Retail InqInt64(2) — shown in footer line-2 in State-A display.
/// Element 0x10000245 (footer line-2 value).
///
public long UnassignedXp { get; init; }
// ── Attribute raise costs (ExperienceToAttributeLevel, gmAttributeUI::PostInit) ──
// Retail formula: ExperienceToAttributeLevel(value + 1) − ExperienceToAttributeLevel(value).
// We store pre-computed per-attribute costs for the fixture; cost == 0 → attribute is
// at max or not trainable (raise button ghosted/hidden). Ordered to match AttrRows
// (Strength, Endurance, Coordination, Quickness, Focus, Self, Health, Stamina, Mana).
// Source: gmAttributeUI::AttributeInfoRegion::Update (0x004f1910) + CM_Train::Event_TrainAttribute.
///
/// XP cost to raise each of the 9 attributes/vitals by 1, in retail display order:
/// [0]=Strength, [1]=Endurance, [2]=Coordination, [3]=Quickness, [4]=Focus, [5]=Self,
/// [6]=Health, [7]=Stamina, [8]=Mana.
/// Cost 0 means the attribute is at max (raise button ghosted).
///
public long[] AttributeRaiseCosts { get; init; } = Array.Empty();
// ── Augmentations (UpdateAugmentations 0x004b9000) ─────────────────────
// Retail InqInt(0x162) = AugmentationStat; string-switch 1..0xb.
/// Augmentation name from the switch in UpdateAugmentations (0x004b9000),
/// e.g. "Swords", "Two Handed Weapons". Null = "None".
public string? AugmentationName { get; init; }
// ── Burden / load (UpdateLoad 0x004b8a20) ───────────────────────────────
// Retail InqLoad + EncumbranceCapacity(Strength, AugEncumbrance).
public int BurdenCurrent { get; init; }
public int BurdenMax { get; init; }
}