#pragma once

#include <filesystem>
#include <map>
#include <string>
#include <string_view>
#include <unordered_map>
#include <vector>

#include <glm/glm.hpp>

#include "../util/physfs.hpp"
#include "anm2.hpp"
#include "audio.hpp"
#include "font.hpp"
#include "texture.hpp"

#define GAME_SCHEMA_ELEMENT_TYPES(X)                                                                                   \
  X(Actions, ACTIONS)                                                                                                  \
  X(AlternateSpritesheet, ALTERNATE_SPRITESHEET)                                                                       \
  X(Animation, ANIMATION)                                                                                              \
  X(Animations, ANIMATIONS)                                                                                            \
  X(AnimationOverrides, ANIMATION_OVERRIDES)                                                                           \
  X(Anm2, ANM2)                                                                                                        \
  X(Area, AREA)                                                                                                        \
  X(Areas, AREAS)                                                                                                      \
  X(Blink, BLINK)                                                                                                      \
  X(Blip, BLIP)                                                                                                        \
  X(Bounce, BOUNCE)                                                                                                    \
  X(Categories, CATEGORIES)                                                                                            \
  X(Category, CATEGORY)                                                                                                \
  X(Character, CHARACTER)                                                                                              \
  X(CheatsActivated, CHEATS_ACTIVATED)                                                                                 \
  X(Chew, CHEW)                                                                                                        \
  X(Choice, CHOICE)                                                                                                    \
  X(Click, CLICK)                                                                                                      \
  X(Close, CLOSE)                                                                                                      \
  X(Collect, COLLECT)                                                                                                  \
  X(Color, COLOR)                                                                                                      \
  X(Colors, COLORS)                                                                                                    \
  X(Content, CONTENT)                                                                                                  \
  X(Cursor, CURSOR)                                                                                                    \
  X(DelayCharacter, DELAY_CHARACTER)                                                                                   \
  X(DelayCharacters, DELAY_CHARACTERS)                                                                                 \
  X(Dialogue, DIALOGUE)                                                                                                \
  X(Digest, DIGEST)                                                                                                    \
  X(Dispose, DISPOSE)                                                                                                  \
  X(Eat, EAT)                                                                                                          \
  X(EatArea, EAT_AREA)                                                                                                 \
  X(EatAreas, EAT_AREAS)                                                                                               \
  X(EatFull, EAT_FULL)                                                                                                 \
  X(Effect, EFFECT)                                                                                                    \
  X(Effects, EFFECTS)                                                                                                  \
  X(End, END)                                                                                                          \
  X(Enemy, ENEMY)                                                                                                      \
  X(Entries, ENTRIES)                                                                                                  \
  X(Entry, ENTRY)                                                                                                      \
  X(Event, EVENT)                                                                                                      \
  X(Events, EVENTS)                                                                                                    \
  X(ExpandArea, EXPAND_AREA)                                                                                           \
  X(ExpandAreas, EXPAND_AREAS)                                                                                         \
  X(Feed, FEED)                                                                                                        \
  X(FeedFull, FEED_FULL)                                                                                               \
  X(FinishFood, FINISH_FOOD)                                                                                           \
  X(Flavor, FLAVOR)                                                                                                    \
  X(Flavors, FLAVORS)                                                                                                  \
  X(Follower, FOLLOWER)                                                                                                \
  X(FoodTaken, FOOD_TAKEN)                                                                                             \
  X(FoodTakenFull, FOOD_TAKEN_FULL)                                                                                    \
  X(Frame, FRAME)                                                                                                      \
  X(Full, FULL)                                                                                                        \
  X(Grab, GRAB)                                                                                                        \
  X(Gurgle, GURGLE)                                                                                                    \
  X(Help, HELP)                                                                                                        \
  X(Home, HOME)                                                                                                        \
  X(Hover, HOVER)                                                                                                      \
  X(Hurt, HURT)                                                                                                        \
  X(Idle, IDLE)                                                                                                        \
  X(IdleFull, IDLE_FULL)                                                                                               \
  X(Info, INFO)                                                                                                        \
  X(InteractArea, INTERACT_AREA)                                                                                       \
  X(InteractAreas, INTERACT_AREAS)                                                                                     \
  X(InteractAreaTypes, INTERACT_AREA_TYPES)                                                                            \
  X(Inventory, INVENTORY)                                                                                              \
  X(Item, ITEM)                                                                                                        \
  X(Items, ITEMS)                                                                                                      \
  X(ItemSchema, ITEM_SCHEMA)                                                                                           \
  X(Kill, KILL)                                                                                                        \
  X(Layer, LAYER)                                                                                                      \
  X(LayerAnimation, LAYER_ANIMATION)                                                                                   \
  X(LayerAnimations, LAYER_ANIMATIONS)                                                                                 \
  X(Layers, LAYERS)                                                                                                    \
  X(LevelUp, LEVEL_UP)                                                                                                 \
  X(LevelUpReady, LEVEL_UP_READY)                                                                                      \
  X(LowCapacity, LOW_CAPACITY)                                                                                         \
  X(Menu, MENU)                                                                                                        \
  X(New, NEW)                                                                                                          \
  X(Null, NULL_)                                                                                                       \
  X(NullAnimation, NULL_ANIMATION)                                                                                     \
  X(NullAnimations, NULL_ANIMATIONS)                                                                                   \
  X(Nulls, NULLS)                                                                                                      \
  X(Open, OPEN)                                                                                                        \
  X(Pan, PAN)                                                                                                          \
  X(Particle, PARTICLE)                                                                                                \
  X(Particles, PARTICLES)                                                                                              \
  X(Play, PLAY)                                                                                                        \
  X(Player, PLAYER)                                                                                                    \
  X(Pool, POOL)                                                                                                        \
  X(PoolEntry, POOL_ENTRY)                                                                                             \
  X(Pools, POOLS)                                                                                                      \
  X(PostDigest, POST_DIGEST)                                                                                           \
  X(Random, RANDOM)                                                                                                    \
  X(Rarities, RARITIES)                                                                                                \
  X(Rarity, RARITY)                                                                                                    \
  X(Region, REGION)                                                                                                    \
  X(Release, RELEASE)                                                                                                  \
  X(Return, RETURN_)                                                                                                   \
  X(RootAnimation, ROOT_ANIMATION)                                                                                     \
  X(Save, SAVE)                                                                                                        \
  X(Select, SELECT)                                                                                                    \
  X(Settings, SETTINGS)                                                                                                \
  X(Sound, SOUND)                                                                                                      \
  X(Sounds, SOUNDS)                                                                                                    \
  X(Spritesheet, SPRITESHEET)                                                                                          \
  X(Spritesheets, SPRITESHEETS)                                                                                        \
  X(Stage, STAGE)                                                                                                      \
  X(Stages, STAGES)                                                                                                    \
  X(StageUp, STAGE_UP)                                                                                                 \
  X(Start, START)                                                                                                      \
  X(String, STRING)                                                                                                    \
  X(Strings, STRINGS)                                                                                                  \
  X(Summon, SUMMON)                                                                                                    \
  X(Talk, TALK)                                                                                                        \
  X(Text, TEXT)                                                                                                        \
  X(TextPlayback, TEXT_PLAYBACK)                                                                                       \
  X(Throw, THROW)                                                                                                      \
  X(Trigger, TRIGGER)                                                                                                  \
  X(Triggers, TRIGGERS)                                                                                                \
  X(Unknown, UNKNOWN)                                                                                                  \
  X(Upgrade, UPGRADE)                                                                                                  \
  X(UpgradeFail, UPGRADE_FAIL)                                                                                         \
  X(Warning, WARNING)                                                                                                  \
  X(Zoom, ZOOM)
#define GAME_SCHEMA_ELEMENT_FIELDS(X, DATA)                                                                            \
  X(DATA, MEMBER_ATTRIBUTE, airResistance, float, "Air Resistance", FLOAT,     \
    "AirResistance", "", "", airResistance)                                                                            \
  X(DATA, ATTRIBUTE, tint.a, void, "Alpha Tint", COLOR_RO,     \
    "AlphaTint", "", "", tint.a)                                                                                       \
  X(DATA, MEMBER_ATTRIBUTE, amplitude, float, "Amplitude", FLOAT, "Amplitude", "", "",           \
    amplitude)                                                                                                         \
  X(DATA, MEMBER_ATTRIBUTE, animation, std::string, "Animation", STRING, "Animation", "", "", animation)            \
  X(DATA, MEMBER_ATTRIBUTE, animationAppendID, std::string, "Append String For Animations", STRING, "AppendStringForAnimations", "", "", animationAppendID) \
  X(DATA, MEMBER_ATTRIBUTE, animationCursorActive, std::string, "Animation Cursor Active", STRING, "AnimationCursorActive", "", "",                      \
    animationCursorActive)                                                                                             \
  X(DATA, MEMBER_ATTRIBUTE, animationCursorHover, std::string, "Animation Cursor Hover", STRING, "AnimationCursorHover", "", "",                      \
    animationCursorHover)                                                                                              \
  X(DATA, MEMBER_ATTRIBUTE, anm2, std::string, "ANM2", STRING,    \
    "Anm2", "", "", anm2)                                                                                              \
  X(DATA, MEMBER_ATTRIBUTE, anm2RootPath, std::string, "ANM2 Root Path", STRING, "Anm2RootPath", "", "", anm2RootPath)              \
  X(DATA, MEMBER_ATTRIBUTE, areaID, int, "Area ID", INT_RW, "AreaID", "",    \
    "", areaID)                                                                                                        \
  X(DATA, MEMBER_ATTRIBUTE, atFrame, int, "At Frame", INT_RW, "AtFrame",  \
    "", "", atFrame)                                                                                                   \
  X(DATA, MEMBER_ATTRIBUTE, baseAnm2, std::string, "Base ANM2",       \
    STRING, "BaseAnm2", "", "", baseAnm2)                                                                              \
  X(DATA, MEMBER_ATTRIBUTE, blinkChance, float, "Blink Chance", FLOAT,     \
    "BlinkChance", "", "", blinkChance)                                                                                \
  X(DATA, MEMBER_ATTRIBUTE, blipDelayTicks, int, "Blip Delay Ticks", INT_RW, "BlipDelayTicks", "", "",              \
    blipDelayTicks)                                                                                                    \
  X(DATA, ATTRIBUTE, colorOffset.b, void, "Blue Offset",       \
    COLOR_RO, "BlueOffset", "", "", colorOffset.b)                                                                     \
  X(DATA, ATTRIBUTE, tint.b, void, "Blue Tint", COLOR_RO,      \
    "BlueTint", "", "", tint.b)                                                                                        \
  X(DATA, MEMBER_ATTRIBUTE, calories, float, "Calories", FLOAT, "Calories", "", "",   \
    calories)                                                                                                          \
  X(DATA, MEMBER_ATTRIBUTE, caloriesToKilogram, float, "Calories To Kilogram", FLOAT, "CaloriesToKilogram", "", "", caloriesToKilogram)     \
  X(DATA, MEMBER_ATTRIBUTE, capacityCalories, float, "Capacity Calories",     \
    FLOAT, "CapacityCalories", "", "", capacityCalories)                                                              \
  X(DATA, MEMBER_ATTRIBUTE, capacityBonus, float, "Capacity Bonus", FLOAT,   \
    "CapacityBonus", "", "", capacityBonus)                                                                            \
  X(DATA, MEMBER_ATTRIBUTE, capacityIfOverStuffedOnDigestBonus, float, "Capacity If Overstuffed On Digest Bonus", FLOAT, "CapacityIfOverStuffedOnDigestBonus", "", "",  \
    capacityIfOverStuffedOnDigestBonus)                                                                                \
  X(DATA, MEMBER_ATTRIBUTE, capacityMaxCalories, float, "Capacity Max Calories", \
    FLOAT, "CapacityMaxCalories", "", "", capacityMaxCalories)                                                        \
  X(DATA, MEMBER_ATTRIBUTE, capacityOverstuffedMultiplier, float, "Capacity Overstuffed Multiplier", FLOAT, "CapacityOverstuffedMultiplier", "", "",              \
    capacityOverstuffedMultiplier)                                                                                     \
  X(DATA, MEMBER_ATTRIBUTE, capacityMinCalories, float, "Capacity Min Calories", \
    FLOAT, "CapacityMinCalories", "", "", capacityMinCalories)                                                        \
  X(DATA, MEMBER_ATTRIBUTE, category, std::string, "Category", STRING,     \
    "Category", "", "", category)                                                                                      \
  X(DATA, MEMBER_ATTRIBUTE, character, std::string, "Character", STRING, "Character", "", "", character)             \
  X(DATA, MEMBER_ATTRIBUTE, chanceOnNewGame, float, "Chance On New Game", FLOAT, "ChanceOnNewGame", "", "", chanceOnNewGame)           \
  X(DATA, MEMBER_ATTRIBUTE, color, glm::vec3, "Color", VEC3, "ColorR", "ColorG", "ColorB", color)  \
  X(DATA, MEMBER_ATTRIBUTE, count, int, "Count", INT_RW, "Count", "", "", count)             \
  X(DATA, MEMBER_ATTRIBUTE, credits, std::string, "Credits",       \
    STRING, "Credits", "", "", credits)                                                                                \
  X(DATA, MEMBER_ATTRIBUTE, death, std::string, "Death", STRING, "Death", "",  \
    "", death)                                                                                                         \
  X(DATA, MEMBER_ATTRIBUTE, deathDialoguePoolID, std::string, "Death Dialogue Pool", STRING, "DeathDialoguePool", "", "", deathDialoguePoolID)               \
  X(DATA, MEMBER_ATTRIBUTE, delayTicks, int, "Delay Ticks", INT_RW,            \
    "DelayTicks", "", "", delayTicks)                                                                                 \
  X(DATA, MEMBER_ATTRIBUTE, defaultAnimation, std::string, "Default Animation", STRING, "DefaultAnimation", "", "",               \
    defaultAnimation)                                                                                                  \
  X(DATA, MEMBER_ATTRIBUTE, description, std::string, "Description", STRING,       \
    "Description", "", "", description)                                                                                \
  X(DATA, MEMBER_ATTRIBUTE, dialoguePoolID, std::string, "Dialogue Pool", STRING, "DialoguePool", "", "", dialoguePoolID)               \
  X(DATA, MEMBER_ATTRIBUTE, dialoguePoolIDFull, std::string, "Dialogue Pool Full", STRING, "DialoguePoolFull", "", "", dialoguePoolIDFull)          \
  X(DATA, MEMBER_ATTRIBUTE, digestionBonus, float, "Digestion Bonus",       \
    FLOAT, "DigestionBonus", "", "", digestionBonus)                                                                   \
  X(DATA, MEMBER_ATTRIBUTE, digestionBonusOnClick, float, "Digestion Bonus On Click", FLOAT, "DigestionBonusOnClick", "", "", digestionBonusOnClick)        \
  X(DATA, MEMBER_ATTRIBUTE, digestionBonusOnHover, float, "Digestion Bonus On Hover", FLOAT, "DigestionBonusOnHover", "", "", digestionBonusOnHover)        \
  X(DATA, MEMBER_ATTRIBUTE, digestionProgress, float, "Digestion Progress",       \
    FLOAT, "DigestionProgress", "", "", digestionProgress)                                                             \
  X(DATA, MEMBER_ATTRIBUTE, digestionRate, float, "Digestion Rate Per Second",        \
    FLOAT_PER_SECOND,                                                                                                  \
    "DigestionRatePerSecond", "", "", digestionRate)                                                                   \
  X(DATA, MEMBER_ATTRIBUTE, digestionRateMax, float, "Digestion Rate Per Second Max",                                                                                   \
    FLOAT_PER_SECOND, "DigestionRatePerSecondMax", "", "", digestionRateMax)                                           \
  X(DATA, MEMBER_ATTRIBUTE, digestionRateMin, float, "Digestion Rate Per Second Min",                                                                                   \
    FLOAT_PER_SECOND, "DigestionRatePerSecondMin", "", "", digestionRateMin)                                           \
  X(DATA, MEMBER_ATTRIBUTE, digestionTimer, int, "Digestion Timer", INT_RW,          \
    "DigestionTimer", "", "", digestionTimer)                                                                          \
  X(DATA, MEMBER_ATTRIBUTE, digestionTimerMax, int, "Digestion Timer Max", INT_RW,   \
    "DigestionTimerMax", "", "", digestionTimerMax)                                                                    \
  X(DATA, MEMBER_ATTRIBUTE, durability, int, "Durability", INT_RW, "Durability", \
    "", "", durability)                                                                                                \
  X(DATA, MEMBER_ATTRIBUTE, eatSpeedMultiplier, float, "Eat Speed Multiplier",     \
    FLOAT, "EatSpeedMultiplier", "", "", eatSpeedMultiplier)                                                          \
  X(DATA, MEMBER_ATTRIBUTE, eatSpeedBonus, float, "Eat Speed Bonus",     \
    FLOAT, "EatSpeedBonus", "", "", eatSpeedBonus)                                                                     \
  X(DATA, MEMBER_ATTRIBUTE, eatSpeedMaxMultiplier, float, "Eat Speed Max Multiplier", FLOAT, "EatSpeedMaxMultiplier", "", "", eatSpeedMaxMultiplier)                \
  X(DATA, MEMBER_ATTRIBUTE, eatSpeedMinMultiplier, float, "Eat Speed Min Multiplier", FLOAT, "EatSpeedMinMultiplier", "", "", eatSpeedMinMultiplier)                \
  X(DATA, MEMBER_ATTRIBUTE, end, int, "End", INT_RW, "End",    \
    "", "", end)                                                                                                       \
  X(DATA, MEMBER_ATTRIBUTE, event, std::string, "Event To Activate", STRING,                                                            \
    "EventToActivate", "", "", event)                                                                                  \
  X(DATA, MEMBER_ATTRIBUTE, eventID, int, "Event ID", INT_RW, "EventId", "",    \
    "", eventID)                                                                                                       \
  X(DATA, MEMBER_ATTRIBUTE, flavor, std::string, "Flavor", STRING, "Flavor", \
    "", "", flavor)                                                                                                    \
  X(DATA, MEMBER_ATTRIBUTE, font, std::string, "Font", STRING, "Font",  \
    "", "", font)                                                                                                      \
  X(DATA, MEMBER_ATTRIBUTE, fontRootPath, std::string, "Font Root Path", STRING, "FontRootPath", "", "", fontRootPath)              \
  X(DATA, MEMBER_ATTRIBUTE, frameNum, int, "Frame Number", INT_RW, "FrameNum",  \
    "", "", frameNum)                                                                                                  \
  X(DATA, MEMBER_ATTRIBUTE, frequency, float, "Frequency", \
    FLOAT, "Frequency", "", "", frequency)                                                                             \
  X(DATA, MEMBER_ATTRIBUTE, friction, float, "Friction", FLOAT, "Friction", "", \
    "", friction)                                                                                                      \
  X(DATA, MEMBER_ATTRIBUTE, gravity, float, "Gravity", FLOAT,          \
    "Gravity", "", "", gravity)                                                                                        \
  X(DATA, ATTRIBUTE, colorOffset.g, void, "Green Offset",      \
    COLOR_RO, "GreenOffset", "", "", colorOffset.g)                                                                    \
  X(DATA, ATTRIBUTE, tint.g, void, "Green Tint", COLOR_RO,     \
    "GreenTint", "", "", tint.g)                                                                                       \
  X(DATA, MEMBER_ATTRIBUTE, gurgleChanceFromCapacityMultiplier, float, "Gurgle Chance From Capacity Multiplier", FLOAT, "GurgleChanceFromCapacityMultiplier", "", "",       \
    gurgleChanceFromCapacityMultiplier)                                                                                \
  X(DATA, MEMBER_ATTRIBUTE, gurgleChance, float, "Gurgle Chance", FLOAT,      \
    "GurgleChance", "", "", gurgleChance)                                                                              \
  X(DATA, MEMBER_ATTRIBUTE, hitboxNull, std::string, "Hitbox Null",   \
    STRING, "HitboxNull", "", "", hitboxNull)                                                                          \
  X(DATA, MEMBER_ATTRIBUTE, hurtDialoguePoolID, std::string, "Hurt Dialogue Pool", STRING, "HurtDialoguePool", "", "", hurtDialoguePoolID)                  \
  X(DATA, MEMBER_ATTRIBUTE, iconGlyph, std::string, "Glyph From Icon Font", STRING, "GlyphFromIconFont", "", "", iconGlyph)             \
  X(DATA, MEMBER_ATTRIBUTE, iconsFont, std::string, "Icons Font",  \
    STRING, "IconsFont", "", "", iconsFont)                                                                            \
  X(DATA, MEMBER_ATTRIBUTE, id, int, "ID", INT_RO, "Id", "", "", id)                      \
  X(DATA, ATTRIBUTE, id, int, "ID", INT_RW, "ID", "", "", id)                             \
  X(DATA, MEMBER_ATTRIBUTE, idString, std::string, "Label", STRING, "Label", "", "", idString)       \
  X(DATA, MEMBER_ATTRIBUTE, idleString, std::string, "Idle", STRING, "Idle",    \
    "", "", idleString)                                                                                                \
  X(DATA, MEMBER_ATTRIBUTE, interpolated, bool, "Interpolated", BOOL, \
    "Interpolated", "", "", interpolated)                                                                              \
  X(DATA, MEMBER_ATTRIBUTE, isAlternateSpritesheet, bool, "Is Alternate Spritesheet", BOOL, "IsAlternateSpritesheet", "", "",                     \
    isAlternateSpritesheet)                                                                                            \
  X(DATA, MEMBER_ATTRIBUTE, isDigesting, bool, "Is Digesting",  \
    BOOL, "IsDigesting", "", "", isDigesting)                                                                          \
  X(DATA, MEMBER_ATTRIBUTE, isDisableTalk, bool, "Is Disable Talk", BOOL, "IsDisableTalk", "",  \
    "", isDisableTalk)                                                                                                 \
  X(DATA, MEMBER_ATTRIBUTE, isEdible, bool, "Is Edible", BOOL, "IsEdible", \
    "", "", isEdible)                                                                                                  \
  X(DATA, MEMBER_ATTRIBUTE, isHidden, bool, "Is Hidden",      \
    BOOL, "IsHidden", "", "", isHidden)                                                                                \
  X(DATA, MEMBER_ATTRIBUTE, isHold, bool, "Is Hold", BOOL, "IsHold",   \
    "", "", isHold)                                                                                                    \
  X(DATA, MEMBER_ATTRIBUTE, isPostgame, bool, "Is Postgame",      \
    BOOL, "IsPostgame", "", "", isPostgame)                                                                            \
  X(DATA, MEMBER_ATTRIBUTE, isToggleSpritesheet, bool, "Is Toggle Spritesheet", BOOL, "IsToggleSpritesheet", "", "", isToggleSpritesheet)      \
  X(DATA, MEMBER_ATTRIBUTE, isAudioMuted, bool, "Is Audio Muted", BOOL,               \
    "IsAudioMuted", "", "", isAudioMuted)                                                                             \
  X(DATA, MEMBER_ATTRIBUTE, isUseCharacterColor, bool, "Is Use Character Color", BOOL, "IsUseCharacterColor", "", "", isUseCharacterColor)    \
  X(DATA, MEMBER_ATTRIBUTE, layer, std::string, "Layer", STRING,        \
    "Layer", "", "", layer)                                                                                            \
  X(DATA, MEMBER_ATTRIBUTE, layerDestination, std::string, "Layer Destination", STRING, "LayerDestination", "", "", layerDestination)               \
  X(DATA, MEMBER_ATTRIBUTE, layerID, int, "Layer ID", INT_RW, "LayerId", "", "",     \
    layerID)                                                                                                           \
  X(DATA, MEMBER_ATTRIBUTE, layerSource, std::string, "Layer Source",        \
    STRING, "LayerSource", "", "", layerSource)                                                                        \
  X(DATA, MEMBER_ATTRIBUTE, lastCharacter, std::string, "Last Character", STRING, "LastCharacter", "", "", lastCharacter)                          \
  X(DATA, MEMBER_ATTRIBUTE, isLoop, bool, "Loop", BOOL, "Loop", "",    \
    "", isLoop)                                                                                                        \
  X(DATA, MEMBER_ATTRIBUTE, magnitude, float, "Magnitude", FLOAT,   \
    "Magnitude", "", "", magnitude)                                                                                    \
  X(DATA, MEMBER_ATTRIBUTE, measurementSystem, std::string, "Measurement System", STRING, "MeasurementSystem", "", "", measurementSystem)                \
  X(DATA, MEMBER_ATTRIBUTE, name, std::string, "Name", STRING,        \
    "Name", "", "", name)                                                                                              \
  X(DATA, MEMBER_ATTRIBUTE, next, std::string, "Next", STRING, "Next", "", \
    "", next)                                                                                                          \
  X(DATA, MEMBER_ATTRIBUTE, null, std::string, "Null", STRING, "Null",   \
    "", "", null)                                                                                                      \
  X(DATA, MEMBER_ATTRIBUTE, nullID, int, "Null ID", INT_RW, "NullId", "", "", nullID) \
  X(DATA, MEMBER_ATTRIBUTE, overrideTintLayer, std::string, "Override Tint Layer", STRING, "OverrideTintLayer", "", "", overrideTintLayer)       \
  X(DATA, MEMBER_ATTRIBUTE, path, std::string, "Path", STRING, "Path", "",  \
    "", path)                                                                                                          \
  X(DATA, MEMBER_ATTRIBUTE, period, float, "Period",       \
    FLOAT, "Period", "", "", period)                                                                                   \
  X(DATA, MEMBER_ATTRIBUTE, poolID, std::string, "Pool", STRING, "Pool", "",      \
    "", poolID)                                                                                                        \
  X(DATA, ATTRIBUTE, portrait.path, void, "Portrait",          \
    STRING_TARGET, "Portrait", "", "", portrait.path)                                                                  \
  X(DATA, MEMBER_ATTRIBUTE, position, glm::vec2, "Position", VEC2, "PositionX",       \
    "PositionY", "", position)                                                                                         \
  X(DATA, MEMBER_ATTRIBUTE, quantity, int, "Quantity", INT_RW, "Quantity", "", "",      \
    quantity)                                                                                                          \
  X(DATA, MEMBER_ATTRIBUTE, quantityMax, int, "Quantity Max", INT_RW,             \
    "QuantityMax", "", "", quantityMax)                                                                                \
  X(DATA, MEMBER_ATTRIBUTE, rarity, std::string, "Rarity", STRING, "Rarity", \
    "", "", rarity)                                                                                                    \
  X(DATA, ATTRIBUTE, colorOffset.r, void, "Red Offset",        \
    COLOR_RO, "RedOffset", "", "", colorOffset.r)                                                                      \
  X(DATA, ATTRIBUTE, tint.r, void, "Red Tint", COLOR_RO,       \
    "RedTint", "", "", tint.r)                                                                                         \
  X(DATA, MEMBER_ATTRIBUTE, regionID, int, "Region ID", INT_RW,         \
    "RegionId", "", "", regionID)                                                                                      \
  X(DATA, ATTRIBUTE, render.path, void, "Render",              \
    STRING_TARGET, "Render", "", "", render.path)                                                                      \
  X(DATA, MEMBER_ATTRIBUTE, rotation, float, "Rotation", FLOAT, "Rotation", "",    \
    "", rotation)                                                                                                      \
  X(DATA, MEMBER_ATTRIBUTE, rotationSpeed, float, "Rotation Speed", FLOAT, "RotationSpeed", \
    "", "", rotationSpeed)                                                                                             \
  X(DATA, MEMBER_ATTRIBUTE, rotationSpeedFriction, float, "Rotation Speed Friction", FLOAT, "RotationSpeedFriction", "", "", rotationSpeedFriction)               \
  X(DATA, MEMBER_ATTRIBUTE, rotationSpeedMax, float, "Rotation Speed Max", FLOAT,           \
    "RotationSpeedMax", "", "", rotationSpeedMax)                                                                      \
  X(DATA, MEMBER_ATTRIBUTE, rounding, float, "Button Rounding", FLOAT, "ButtonRounding", \
    "", "", rounding)                                                                                                  \
  X(DATA, MEMBER_ATTRIBUTE, scaleAdd, float, "Scale Multiplier Maximum", FLOAT,                                                                \
    "ScaleMultiplierMaximum", "", "", scaleAdd)                                                                        \
  X(DATA, MEMBER_ATTRIBUTE, scaleEffectAmplitude, float, "Scale Effect Amplitude", FLOAT, "ScaleEffectAmplitude", "", "", scaleEffectAmplitude)                 \
  X(DATA, MEMBER_ATTRIBUTE, scaleEffectCycles, float, "Scale Effect Cycles",   \
    FLOAT, "ScaleEffectCycles", "", "", scaleEffectCycles)                                                             \
  X(DATA, MEMBER_ATTRIBUTE, isShowRect, bool, "Show Rect",    \
    BOOL, "ShowRect", "", "", isShowRect)                                                                              \
  X(DATA, MEMBER_ATTRIBUTE, sound, std::string, "Sound", STRING, "Sound", "", "", \
    sound)                                                                                                             \
  X(DATA, MEMBER_ATTRIBUTE, soundRootPath, std::string, "Sound Root Path", STRING, "SoundRootPath", "", "", soundRootPath)           \
  X(DATA, MEMBER_ATTRIBUTE, spawn, std::string, "Spawn",        \
    STRING, "Spawn", "", "", spawn)                                                                                    \
  X(DATA, MEMBER_ATTRIBUTE, spawnChanceBase, float, "Spawn Chance Base",     \
    FLOAT, "SpawnChanceBase", "", "", spawnChanceBase)                                                                 \
  X(DATA, MEMBER_ATTRIBUTE, spawnChanceScoreBonus, float, "Spawn Chance Score Bonus", FLOAT, "SpawnChanceScoreBonus", "", "", spawnChanceScoreBonus)                  \
  X(DATA, MEMBER_ATTRIBUTE, spawnPadding, float, "Spawn Padding", FLOAT,               \
    "SpawnPadding", "", "", spawnPadding)                                                                              \
  X(DATA, MEMBER_ATTRIBUTE, speed, float, "Speed", FLOAT, "Speed", "", "", speed)             \
  X(DATA, MEMBER_ATTRIBUTE, speedGainBase, float, "Speed Gain Base",      \
    FLOAT, "SpeedGainBase", "", "", speedGainBase)                                                                     \
  X(DATA, MEMBER_ATTRIBUTE, speedGainScoreBonus, float, "Speed Gain Score Bonus",      \
    FLOAT, "SpeedGainScoreBonus", "", "", speedGainScoreBonus)                                                         \
  X(DATA, MEMBER_ATTRIBUTE, speedMax, float, "Speed Max", FLOAT, "SpeedMax", "", "", speedMax) \
  X(DATA, MEMBER_ATTRIBUTE, speedMin, float, "Speed Min", FLOAT, "SpeedMin", "", "", speedMin) \
  X(DATA, MEMBER_ATTRIBUTE, spritesheetID, int, "Spritesheet ID", INT_RW,      \
    "SpritesheetId", "", "", spritesheetID)                                                                            \
  X(DATA, MEMBER_ATTRIBUTE, start, int, "Start", INT_RW,     \
    "Start", "", "", start)                                                                                            \
  X(DATA, MEMBER_ATTRIBUTE, startTime, int, "Start Time", INT_RW, "StartTime",  \
    "", "", startTime)                                                                                                 \
  X(DATA, MEMBER_ATTRIBUTE, targetAcceleration, float, "Target Acceleration", FLOAT, "TargetAcceleration", "", "", targetAcceleration)                 \
  X(DATA, MEMBER_ATTRIBUTE, text, std::string, "Text", STRING,        \
    "Text", "", "", text)                                                                                              \
  X(DATA, MEMBER_ATTRIBUTE, texture, std::string, "Texture", STRING, \
    "Texture", "", "", texture)                                                                                        \
  X(DATA, MEMBER_ATTRIBUTE, textureRootPath, std::string, "Texture Root Path", STRING, "TextureRootPath", "", "", textureRootPath)     \
  X(DATA, MEMBER_ATTRIBUTE, thresholdKilograms, float, "Threshold Kilograms", FLOAT,  \
    "ThresholdKilograms", "", "", thresholdKilograms)                                                                  \
  X(DATA, MEMBER_ATTRIBUTE, ticksSurvived, int, "Ticks Survived", INT_RW,                \
    "TicksSurvived", "", "", ticksSurvived)                                                                            \
  X(DATA, MEMBER_ATTRIBUTE, timeTicks, float, "Time Ticks", FLOAT, "TimeTicks", \
    "", "", timeTicks)                                                                                                 \
  X(DATA, MEMBER_ATTRIBUTE, timeAfterHurt, int, "Time After Hurt", INT_RW,        \
    "TimeAfterHurt", "", "", timeAfterHurt)                                                                            \
  X(DATA, MEMBER_ATTRIBUTE, timeToActivateNewDialogueTicks, int, "Time To Activate New Dialogue Ticks", INT_RW, "TimeToActivateNewDialogueTicks", "", "",  \
    timeToActivateNewDialogueTicks)                                                                                         \
  X(DATA, MEMBER_ATTRIBUTE, title, std::string, "Title", STRING, "Title",  \
    "", "", title)                                                                                                     \
  X(DATA, MEMBER_ATTRIBUTE, totalCaloriesConsumed, float, "Total Calories Consumed", FLOAT, "TotalCaloriesConsumed", "", "", totalCaloriesConsumed)                \
  X(DATA, MEMBER_ATTRIBUTE, totalFoodItemsEaten, int, "Total Food Items Eaten",     \
    INT_RW, "TotalFoodItemsEaten", "", "", totalFoodItemsEaten)                                                        \
  X(DATA, MEMBER_ATTRIBUTE, typeString, std::string, "Type", STRING, "Type", "",   \
    "", typeString)                                                                                                    \
  X(DATA, MEMBER_ATTRIBUTE, upgradeCount, int, "Upgrade Count", INT_RW,     \
    "UpgradeCount", "", "", upgradeCount)                                                                              \
  X(DATA, MEMBER_ATTRIBUTE, upgradeID, std::string, "Upgrade ID",       \
    STRING, "UpgradeID", "", "", upgradeID)                                                                            \
  X(DATA, MEMBER_ATTRIBUTE, value, int, "Value", INT_RW, "Value", "", "", value)             \
  X(DATA, MEMBER_ATTRIBUTE, velocity, glm::vec2, "Velocity", VEC2, "VelocityX",       \
    "VelocityY", "", velocity)                                                                                         \
  X(DATA, MEMBER_ATTRIBUTE, isVisible, bool, "Visible", BOOL_FALSE,         \
    "Visible", "", "", isVisible)                                                                                      \
  X(DATA, MEMBER_ATTRIBUTE, volume, int, "Volume", INT_RW, "Volume", "", "", volume)          \
  X(DATA, MEMBER_ATTRIBUTE, weight, float, "Weight", FLOAT, "Weight", "", "",      \
    weight)                                                                                                            \
  X(DATA, MEMBER_ATTRIBUTE, weightKilograms, float, "Weight Kilograms", FLOAT,         \
    "WeightKilograms", "", "", weightKilograms)                                                                       \
  X(DATA, MEMBER_ATTRIBUTE, weightMaxKilograms, float, "Weight Max Kilograms", FLOAT,  \
    "WeightMaxKilograms", "", "", weightMaxKilograms)                                                                 \
  X(DATA, MEMBER_ATTRIBUTE, size, glm::vec2, "Size", VEC2, "Width", "Height", "", size)              \
  X(DATA, MEMBER_ATTRIBUTE, windowSize, glm::ivec2, "Window Size", IVEC2, "WindowW", "WindowH",  \
    "", windowSize)                                                                                                    \
  X(DATA, MEMBER_ATTRIBUTE, windowPosition, glm::vec2, "Window Position", VEC2, "WindowX",   \
    "WindowY", "", windowPosition)                                                                                     \
  X(DATA, MEMBER_ATTRIBUTE, crop, glm::vec2, "Crop", VEC2, "XCrop", "YCrop", "", crop)         \
  X(DATA, MEMBER_ATTRIBUTE, pivot, glm::vec2, "Pivot", VEC2, "XPivot", "YPivot", "", pivot)     \
  X(DATA, MEMBER_ATTRIBUTE, framePosition, glm::vec2, "Frame Position", VEC2,  \
    "XPosition", "YPosition", "", framePosition)                                                                       \
  X(DATA, MEMBER_ATTRIBUTE, scale, glm::vec2, "Scale", VEC2, "XScale", "YScale", "", scale)         \
  X(DATA, MEMBER_ATTRIBUTE, zoom, float, "Zoom", FLOAT, "Zoom", "", "", zoom)           \
  X(DATA, MEMBER, animationChew, std::string, "Animation Chew", NONE, "",  \
    "", "", animationChew)                                                                                             \
  X(DATA, MEMBER, animationClick, AnimationEntryCollection, "Animation Click", NONE, "", "", "", animationClick)                                \
  X(DATA, MEMBER, animationGrab, AnimationEntryCollection, "Animation Grab", NONE, "", "", "", animationGrab)                                  \
  X(DATA, MEMBER, animationHover, AnimationEntryCollection, "Animation Hover", NONE, "", "", "", animationHover)                                \
  X(DATA, MEMBER, animationIdle, AnimationEntryCollection, "Animation Idle", NONE, "", "", "", animationIdle)                                  \
  X(DATA, MEMBER, animationPan, AnimationEntryCollection, "Animation Pan", NONE, "", "", "", animationPan)                                    \
  X(DATA, MEMBER, animationReturn, AnimationEntryCollection, "Animation Return", NONE, "", "", "", animationReturn)                              \
  X(DATA, MEMBER, animationZoom, AnimationEntryCollection, "Animation Zoom", NONE, "", "", "", animationZoom)                                  \
  X(DATA, MEMBER, anm2Entry, Anm2Entry, "ANM2 Entry", NONE, "", "", "",     \
    anm2Entry)                                                                                                         \
  X(DATA, MEMBER, children, std::vector<int>, "Children", NONE, "", "",   \
    "", children)                                                                                                      \
  X(DATA, MEMBER, colorOffset, glm::vec3, "Color Offset", NONE,    \
    "", "", "", colorOffset)                                                                                           \
  X(DATA, MEMBER, fontEntry, FontEntry, "Font Entry", NONE, "", "", "",     \
    fontEntry)                                                                                                         \
  X(DATA, MEMBER, iconsFontEntry, FontEntry, "Icons Font Entry", NONE, \
    "", "", "", iconsFontEntry)                                                                                        \
  X(DATA, MEMBER, parent, int, "Parent", NONE, "", "",   \
    "", parent)                                                                                                        \
  X(DATA, MEMBER, portrait, TextureEntry, "Portrait", NONE, "", \
    "", "", portrait)                                                                                                  \
  X(DATA, MEMBER, render, TextureEntry, "Render", NONE, "", "",   \
    "", render)                                                                                                        \
  X(DATA, MEMBER, soundBlip, SoundEntryCollection, "Sound Blip", NONE, "", "", "", \
    soundBlip)                                                                                                         \
  X(DATA, MEMBER, soundBounce, SoundEntryCollection, "Sound Bounce", NONE, "",   \
    "", "", soundBounce)                                                                                               \
  X(DATA, MEMBER, soundCheatsActivated, SoundEntryCollection, "Sound Cheats Activated", NONE, "", "", "", soundCheatsActivated)                            \
  X(DATA, MEMBER, soundClose, SoundEntryCollection, "Sound Close", NONE, "", "",  \
    "", soundClose)                                                                                                    \
  X(DATA, MEMBER, soundCollect, SoundEntryCollection, "Sound Collect", NONE,    \
    "", "", "", soundCollect)                                                                                          \
  X(DATA, MEMBER, soundDigest, SoundEntryCollection, "Sound Digest", NONE, "",   \
    "", "", soundDigest)                                                                                               \
  X(DATA, MEMBER, soundDispose, SoundEntryCollection, "Sound Dispose", NONE,    \
    "", "", "", soundDispose)                                                                                          \
  X(DATA, MEMBER, soundEntries, SoundEntryCollection, "Sound Entries", NONE, "", "", "", soundEntries)                                  \
  X(DATA, MEMBER, soundEntry, SoundEntry, "Sound Entry", NONE, "", "", "", \
    soundEntry)                                                                                                        \
  X(DATA, MEMBER, soundGrab, SoundEntryCollection, "Sound Grab", NONE, "", "", "", \
    soundGrab)                                                                                                         \
  X(DATA, MEMBER, soundGurgle, SoundEntryCollection, "Sound Gurgle", NONE, "",   \
    "", "", soundGurgle)                                                                                               \
  X(DATA, MEMBER, soundHover, SoundEntryCollection, "Sound Hover", NONE, "", "",  \
    "", soundHover)                                                                                                    \
  X(DATA, MEMBER, soundKill, SoundEntryCollection, "Sound Kill", NONE, "", "", "", \
    soundKill)                                                                                                         \
  X(DATA, MEMBER, soundLevelUp, SoundEntryCollection, "Sound Level Up", NONE,  \
    "", "", "", soundLevelUp)                                                                                          \
  X(DATA, MEMBER, soundLevelUpReady, SoundEntryCollection, "Sound Level Up Ready", NONE, "", "", "", soundLevelUpReady)                                 \
  X(DATA, MEMBER, soundOpen, SoundEntryCollection, "Sound Open", NONE, "", "", "", \
    soundOpen)                                                                                                         \
  X(DATA, MEMBER, soundRelease, SoundEntryCollection, "Sound Release", NONE,    \
    "", "", "", soundRelease)                                                                                          \
  X(DATA, MEMBER, soundReturn, SoundEntryCollection, "Sound Return", NONE, "",   \
    "", "", soundReturn)                                                                                               \
  X(DATA, MEMBER, soundSelect, SoundEntryCollection, "Sound Select", NONE, "",   \
    "", "", soundSelect)                                                                                               \
  X(DATA, MEMBER, soundSummon, SoundEntryCollection, "Sound Summon", NONE, "",   \
    "", "", soundSummon)                                                                                               \
  X(DATA, MEMBER, soundThrow, SoundEntryCollection, "Sound Throw", NONE, "", "",  \
    "", soundThrow)                                                                                                    \
  X(DATA, MEMBER, soundUpgrade, SoundEntryCollection, "Sound Upgrade", NONE,    \
    "", "", "", soundUpgrade)                                                                                          \
  X(DATA, MEMBER, soundUpgradeFail, SoundEntryCollection, "Sound Upgrade Fail", NONE, "", "", "", soundUpgradeFail)                                 \
  X(DATA, MEMBER, textureEntry, TextureEntry, "Texture Entry", NONE, "", \
    "", "", textureEntry)                                                                                              \
  X(DATA, MEMBER, tint, glm::vec4, "Tint", NONE, "", "", "", tint)        \
  X(DATA, MEMBER, type, Type, "Type", NONE, "", "", "", type)

#define GAME_SCHEMA_ELEMENT_MEMBER_DISPATCH(DATA, CATEGORY, SYMBOL, TYPE, NAME, KIND, KEY, KEY_2, KEY_3, MEMBER)      \
  GAME_SCHEMA_ELEMENT_MEMBER_DISPATCH_##CATEGORY(DATA, SYMBOL, TYPE, NAME, KIND, KEY, KEY_2, KEY_3, MEMBER)
#define GAME_SCHEMA_ELEMENT_MEMBER_DISPATCH_MEMBER(DATA, SYMBOL, TYPE, NAME, KIND, KEY, KEY_2, KEY_3, MEMBER)         \
  DATA(SYMBOL, TYPE, NAME)
#define GAME_SCHEMA_ELEMENT_MEMBER_DISPATCH_MEMBER_ATTRIBUTE(DATA, SYMBOL, TYPE, NAME, KIND, KEY, KEY_2, KEY_3,        \
                                                             MEMBER)                                                   \
  DATA(SYMBOL, TYPE, NAME)
#define GAME_SCHEMA_ELEMENT_MEMBER_DISPATCH_ATTRIBUTE(DATA, SYMBOL, TYPE, NAME, KIND, KEY, KEY_2, KEY_3, MEMBER)
#define GAME_SCHEMA_ELEMENT_MEMBERS(X) GAME_SCHEMA_ELEMENT_FIELDS(GAME_SCHEMA_ELEMENT_MEMBER_DISPATCH, X)

#define GAME_SCHEMA_ELEMENT_ATTRIBUTE_DISPATCH(DATA, CATEGORY, SYMBOL, TYPE, NAME, KIND, KEY, KEY_2, KEY_3, MEMBER)   \
  GAME_SCHEMA_ELEMENT_ATTRIBUTE_DISPATCH_##CATEGORY(DATA, SYMBOL, TYPE, NAME, KIND, KEY, KEY_2, KEY_3, MEMBER)
#define GAME_SCHEMA_ELEMENT_ATTRIBUTE_DISPATCH_MEMBER(DATA, SYMBOL, TYPE, NAME, KIND, KEY, KEY_2, KEY_3, MEMBER)
#define GAME_SCHEMA_ELEMENT_ATTRIBUTE_DISPATCH_MEMBER_ATTRIBUTE(DATA, SYMBOL, TYPE, NAME, KIND, KEY, KEY_2, KEY_3,     \
                                                                MEMBER)                                                \
  DATA(KIND, KEY, KEY_2, KEY_3, MEMBER)
#define GAME_SCHEMA_ELEMENT_ATTRIBUTE_DISPATCH_ATTRIBUTE(DATA, SYMBOL, TYPE, NAME, KIND, KEY, KEY_2, KEY_3, MEMBER)   \
  DATA(KIND, KEY, KEY_2, KEY_3, MEMBER)
#define GAME_SCHEMA_ELEMENT_ATTRIBUTES(X) GAME_SCHEMA_ELEMENT_FIELDS(GAME_SCHEMA_ELEMENT_ATTRIBUTE_DISPATCH, X)

namespace game::resource::xml
{
  struct Schema
  {
    struct TextureEntry
    {
      std::string path{};
      Texture texture{};

      bool is_valid() const { return texture.is_valid(); }
    };

    struct SoundEntry
    {
      std::string path{};
      Audio sound{};
      float weight{};

      bool is_valid() const { return sound.is_valid(); }
    };

    struct FontEntry
    {
      std::string path{};
      Font font{};

      bool is_valid() const { return font.is_valid(); }
    };

    struct Anm2Entry
    {
      std::string path{};
      Anm2 anm2{};

      bool is_valid() const { return anm2.is_valid(); }
    };

    struct AnimationEntry
    {
      std::string animation{};
      float weight{};
    };

    struct AnimationEntryCollection : std::vector<AnimationEntry>
    {
      std::string* get();
    };

    struct SoundEntryCollection : std::vector<SoundEntry*>
    {
      const Audio* get() const;
      void play() const;
    };

    struct AreaEntry
    {
      Texture texture{};
      Anm2 anm2{};
      float gravity{};
      float friction{};
      float airResistance{};
    };

    struct Category
    {
      std::string name{};
      bool isEdible{};
    };

    struct Rarity
    {
      std::string name{};
      float weight{};
      bool isHidden{};
      Audio sound{};
    };

    struct Flavor
    {
      std::string name{};
    };

    struct ItemEntry
    {
      std::string name{};
      std::string description{};
      int categoryID{-1};
      int rarityID{-1};
      int flavorID{-1};
      bool isFlavor{};
      bool isCalories{};
      bool isCapacityBonus{};
      bool isDigestionBonus{};
      bool isEatSpeedBonus{};
      bool isGravity{};
      bool isDurability{};
      bool isColor{};
      bool isUpgradeID{};
      bool isUpgradeCount{};
      bool isToggleSpritesheet{};
      float calories{};
      float capacityBonus{};
      float digestionBonus{};
      float eatSpeedBonus{};
      float gravity{};
      int durability{};
      glm::vec3 color{};
      int upgradeID{-1};
      int upgradeCount{};
    };

    struct Element
    {
      enum Type
      {
#define GAME_SCHEMA_DECLARE_ELEMENT_TYPE(NAME, ENUM) ENUM,
        GAME_SCHEMA_ELEMENT_TYPES(GAME_SCHEMA_DECLARE_ELEMENT_TYPE)
#undef GAME_SCHEMA_DECLARE_ELEMENT_TYPE
      };

      struct MemberInfo
      {
        std::string_view symbol{};
        std::string_view type{};
        std::string_view name{};
      };

#define GAME_SCHEMA_DECLARE_ELEMENT_MEMBER(SYMBOL, TYPE, NAME) TYPE SYMBOL{};
      GAME_SCHEMA_ELEMENT_MEMBERS(GAME_SCHEMA_DECLARE_ELEMENT_MEMBER)
#undef GAME_SCHEMA_DECLARE_ELEMENT_MEMBER
      std::vector<std::string> attributeOrder{};

      inline static constexpr MemberInfo memberInfos[]{
#define GAME_SCHEMA_ELEMENT_MEMBER_INFO(SYMBOL, TYPE, NAME) {#SYMBOL, #TYPE, NAME},
          GAME_SCHEMA_ELEMENT_MEMBERS(GAME_SCHEMA_ELEMENT_MEMBER_INFO)
#undef GAME_SCHEMA_ELEMENT_MEMBER_INFO
      };

      Element()
      {
        tint = glm::vec4(1.0f);
        isVisible = true;
        type = UNKNOWN;
        parent = -1;
      }

      bool is_valid() const;
      bool is_last() const;
    };

    using Pool = std::vector<int>;

    std::vector<Element> elements{};
    bool isValid{};
    std::map<std::string, int> entryIDMap{};
    std::map<int, std::string> entryIDMapReverse{};
    std::map<std::string, int> poolMap{};
    std::unordered_map<std::string, int> categoryMap{};
    std::unordered_map<std::string, int> rarityMap{};
    std::unordered_map<std::string, int> flavorMap{};
    std::unordered_map<std::string, int> itemIDMap{};
    std::unordered_map<int, std::string> itemIDMapReverse{};
    std::unordered_map<int, std::vector<int>> itemPoolsByRarity{};
    std::vector<long long> entrySelectionOrder{};
    long long selectionCounter{};
    std::vector<AreaEntry> areas{};
    std::vector<Category> categories{};
    std::vector<Rarity> rarities{};
    std::vector<Flavor> flavors{};
    std::vector<ItemEntry> items{};
    std::vector<Anm2> anm2s{};
    std::vector<int> rarityIDs{};
    std::unordered_map<int, Pool> pools{};
    std::unordered_map<std::string, int> stringToIDMap{};
    std::unordered_map<int, std::string> idToStringMap{};
    std::unordered_map<Element::Type, std::vector<int>> elementsByType{};
    Anm2 baseAnm2{};
    Font font{};
    Font iconsFont{};
    int durability{2};
    int quantityMax{99};
    float rounding{};

    Schema() = default;
    Schema(const Schema&);
    Schema(Schema&&) noexcept;
    explicit Schema(const std::filesystem::path&);
    explicit Schema(const util::physfs::Path&);
    Schema& operator=(const Schema&);
    Schema& operator=(Schema&&) noexcept;

    bool load(const std::filesystem::path&);
    bool load(const util::physfs::Path&);
    bool load_archive(const std::filesystem::path&, const std::string& innerPath);
    void settings_default();
    void serialize(const std::filesystem::path&) const;
    bool is_valid() const;
    Element* root();
    const Element* root() const;
    Element& element_add(Element::Type type, int parent = -1);
    bool element_erase(int index);
    int element_insert_xml(const std::string& text, int parent, int beforeSibling = -1);
    bool element_move(int index, int parent, int beforeSibling = -1);
    std::string element_serialize(int index) const;
    Element* get(Element::Type type, int index = 0);
    const Element* get(Element::Type type, int index = 0) const;
    std::vector<Element*> get_all(Element::Type);
    std::vector<const Element*> get_all(Element::Type) const;
    Element* child_get(Element& element, Element::Type type, int index = 0);
    const Element* child_get(const Element& element, Element::Type type, int index = 0) const;
    std::vector<Element*> children_get(Element& element, Element::Type type);
    std::vector<const Element*> children_get(const Element& element, Element::Type type) const;
    Element* dialogue_entry_get(int id);
    Element* dialogue_entry_get(const std::string& id);
    Element* dialogue_entry_get(Element& reference);
    Element* dialogue_pool_entry_get(int poolID);
    Element* dialogue_pool_entry_get(const std::string& poolID);
    Element* dialogue_pool_entry_get(Element& reference);
    int dialogue_entry_id_get(const std::string& id) const;
    int dialogue_pool_id_get(const std::string& id) const;
    Element* item_get(int id);
    Element* item_get(const std::string& id);
    int item_id_get(const std::string& id) const;
    std::vector<int>* item_pool_get(int rarityID);
    void indices_refresh();
  };
}
