#pragma once

// clang-format off: Order of includes matters here

// #include <d3d9.h>
#include "Game/IAsset.h"

#include "T5_Assets.h"

// clang-format on

namespace T5
{
    enum XAssetType
    {
        ASSET_TYPE_XMODELPIECES,
        ASSET_TYPE_PHYSPRESET,
        ASSET_TYPE_PHYSCONSTRAINTS,
        ASSET_TYPE_DESTRUCTIBLEDEF,
        ASSET_TYPE_XANIMPARTS,
        ASSET_TYPE_XMODEL,
        ASSET_TYPE_MATERIAL,
        ASSET_TYPE_TECHNIQUE_SET,
        ASSET_TYPE_IMAGE,
        ASSET_TYPE_SOUND,
        ASSET_TYPE_SOUND_PATCH,
        ASSET_TYPE_CLIPMAP,
        ASSET_TYPE_CLIPMAP_PVS,
        ASSET_TYPE_COMWORLD,
        ASSET_TYPE_GAMEWORLD_SP,
        ASSET_TYPE_GAMEWORLD_MP,
        ASSET_TYPE_MAP_ENTS,
        ASSET_TYPE_GFXWORLD,
        ASSET_TYPE_LIGHT_DEF,
        ASSET_TYPE_UI_MAP,
        ASSET_TYPE_FONT,
        ASSET_TYPE_MENULIST,
        ASSET_TYPE_MENU,
        ASSET_TYPE_LOCALIZE_ENTRY,
        ASSET_TYPE_WEAPON,
        ASSET_TYPE_WEAPONDEF,
        ASSET_TYPE_WEAPON_VARIANT,
        ASSET_TYPE_SNDDRIVER_GLOBALS,
        ASSET_TYPE_FX,
        ASSET_TYPE_IMPACT_FX,
        ASSET_TYPE_AITYPE,
        ASSET_TYPE_MPTYPE,
        ASSET_TYPE_MPBODY,
        ASSET_TYPE_MPHEAD,
        ASSET_TYPE_CHARACTER,
        ASSET_TYPE_XMODELALIAS,
        ASSET_TYPE_RAWFILE,
        ASSET_TYPE_STRINGTABLE,
        ASSET_TYPE_PACK_INDEX,
        ASSET_TYPE_XGLOBALS,
        ASSET_TYPE_DDL,
        ASSET_TYPE_GLASSES,
        ASSET_TYPE_EMBLEMSET,

        ASSET_TYPE_COUNT
    };

    enum SubAssetType
    {
        SUB_ASSET_TYPE_TECHNIQUE,
        SUB_ASSET_TYPE_VERTEX_DECL,
        SUB_ASSET_TYPE_VERTEX_SHADER,
        SUB_ASSET_TYPE_PIXEL_SHADER,
        SUB_ASSET_TYPE_ACCURACY_GRAPH,
        SUB_ASSET_TYPE_FLAME_TABLE,

        SUB_ASSET_TYPE_COUNT
    };

    struct ScriptStringList
    {
        int count;
        const char** strings;
    };

    struct XAsset
    {
        XAssetType type;
        XAssetHeader header;
    };

    struct XAssetList
    {
        ScriptStringList stringList;
        int assetCount;
        XAsset* assets;
    };

    struct cspField_t
    {
        const char* szName;
        int iOffset;
        int iFieldType;
    };

    enum csParseFieldType_t
    {
        CSPFT_STRING,
        CSPFT_STRING_MAX_STRING_CHARS,
        CSPFT_STRING_MAX_QPATH,
        CSPFT_STRING_MAX_OSPATH,
        CSPFT_INT,
        CSPFT_BOOL,
        CSPFT_QBOOLEAN,
        CSPFT_FLOAT,
        CSPFT_MILLISECONDS,
        CSPFT_FX,
        CSPFT_XMODEL,
        CSPFT_MATERIAL,
        CSPFT_MATERIAL_STREAM,
        CSPFT_PHYS_PRESET,
        CSPFT_SCRIPT_STRING,

        CSPFT_NUM_BASE_FIELD_TYPES
    };

    enum weapFieldType_t
    {
        WFT_WEAPONTYPE = CSPFT_NUM_BASE_FIELD_TYPES,
        WFT_WEAPONCLASS,
        WFT_OVERLAYRETICLE,
        WFT_PENETRATE_TYPE,
        WFT_IMPACT_TYPE,
        WFT_STANCE,
        WFT_PROJ_EXPLOSION,
        WFT_OFFHAND_CLASS,
        WFT_OFFHAND_SLOT,
        WFT_ANIMTYPE,
        WFT_ACTIVE_RETICLE_TYPE,
        WFT_GUIDED_MISSILE_TYPE,
        WFT_BOUNCE_SOUND,
        WFT_STICKINESS,
        WFT_ROTATETYPE,
        WFT_OVERLAYINTERFACE,
        WFT_INVENTORYTYPE,
        WFT_FIRETYPE,
        WFT_CLIPTYPE,
        WFT_AMMOCOUNTER_CLIPTYPE,
        WFT_ICONRATIO_HUD,
        WFT_ICONRATIO_AMMOCOUNTER,
        WFT_ICONRATIO_KILL,
        WFT_ICONRATIO_DPAD,
        WFT_ICONRATIO_INDICATOR,
        WFT_HIDETAGS,
        WFT_EXPLOSION_TAG,
        WFT_NOTETRACKSOUNDMAP,
        WFT_ANIM_NAME,

        WFT_NUM_FIELD_TYPES
    };

    enum VehicleFieldType
    {
        VFT_TYPE = CSPFT_NUM_BASE_FIELD_TYPES,
        VFT_CAMERAMODE,
        VFT_BOOSTMODE,
        VFT_TRACTION_TYPE,
        VFT_MPH_TO_INCHES_PER_SECOND,
        VFT_POUNDS_TO_GAME_MASS,
        VFT_SCR_STRING,
        VFT_TEAM,
        VFT_KEY_BINDING,
        VFT_GRAPH,

        VFT_NUM
    };

    enum constraintsFieldType_t
    {
        CFT_TYPE = CSPFT_NUM_BASE_FIELD_TYPES,

        CFT_NUM_FIELD_TYPES
    };

    struct AccuracyGraph
    {
        vec2_t* graphKnots;
        int graphKnotCount;
    };

    using AssetPhysPreset = Asset<ASSET_TYPE_PHYSPRESET, PhysPreset>;
    using AssetPhysConstraints = Asset<ASSET_TYPE_PHYSCONSTRAINTS, PhysConstraints>;
    using AssetDestructibleDef = Asset<ASSET_TYPE_DESTRUCTIBLEDEF, DestructibleDef>;
    using AssetXAnim = Asset<ASSET_TYPE_XANIMPARTS, XAnimParts>;
    using AssetXModel = Asset<ASSET_TYPE_XMODEL, XModel>;
    using AssetMaterial = Asset<ASSET_TYPE_MATERIAL, Material>;
    using AssetTechniqueSet = Asset<ASSET_TYPE_TECHNIQUE_SET, MaterialTechniqueSet>;
    using AssetImage = Asset<ASSET_TYPE_IMAGE, GfxImage>;
    using AssetSoundBank = Asset<ASSET_TYPE_SOUND, SndBank>;
    using AssetSoundPatch = Asset<ASSET_TYPE_SOUND_PATCH, SndPatch>;
    using AssetClipMap = Asset<ASSET_TYPE_CLIPMAP, clipMap_t>;
    using AssetClipMapPvs = Asset<ASSET_TYPE_CLIPMAP_PVS, clipMap_t>;
    using AssetComWorld = Asset<ASSET_TYPE_COMWORLD, ComWorld>;
    using AssetGameWorldSp = Asset<ASSET_TYPE_GAMEWORLD_SP, GameWorldSp>;
    using AssetGameWorldMp = Asset<ASSET_TYPE_GAMEWORLD_MP, GameWorldMp>;
    using AssetMapEnts = Asset<ASSET_TYPE_MAP_ENTS, MapEnts>;
    using AssetGfxWorld = Asset<ASSET_TYPE_GFXWORLD, GfxWorld>;
    using AssetLightDef = Asset<ASSET_TYPE_LIGHT_DEF, GfxLightDef>;
    using AssetFont = Asset<ASSET_TYPE_FONT, Font_s>;
    using AssetMenuList = Asset<ASSET_TYPE_MENULIST, MenuList>;
    using AssetMenu = Asset<ASSET_TYPE_MENU, menuDef_t>;
    using AssetLocalize = Asset<ASSET_TYPE_LOCALIZE_ENTRY, LocalizeEntry>;
    using AssetWeapon = Asset<ASSET_TYPE_WEAPON, WeaponVariantDef>;
    using AssetSoundDriverGlobals = Asset<ASSET_TYPE_SNDDRIVER_GLOBALS, SndDriverGlobals>;
    using AssetFx = Asset<ASSET_TYPE_FX, FxEffectDef>;
    using AssetImpactFx = Asset<ASSET_TYPE_IMPACT_FX, FxImpactTable>;
    using AssetRawFile = Asset<ASSET_TYPE_RAWFILE, RawFile>;
    using AssetStringTable = Asset<ASSET_TYPE_STRINGTABLE, StringTable>;
    using AssetPackIndex = Asset<ASSET_TYPE_PACK_INDEX, PackIndex>;
    using AssetXGlobals = Asset<ASSET_TYPE_XGLOBALS, XGlobals>;
    using AssetDDL = Asset<ASSET_TYPE_DDL, ddlRoot_t>;
    using AssetGlasses = Asset<ASSET_TYPE_GLASSES, Glasses>;
    using AssetEmblemSet = Asset<ASSET_TYPE_EMBLEMSET, EmblemSet>;

    using SubAssetTechnique = SubAsset<SUB_ASSET_TYPE_TECHNIQUE, MaterialTechnique>;
    using SubAssetVertexDecl = SubAsset<SUB_ASSET_TYPE_VERTEX_DECL, MaterialVertexDeclaration>;
    using SubAssetVertexShader = SubAsset<SUB_ASSET_TYPE_VERTEX_SHADER, MaterialVertexShader>;
    using SubAssetPixelShader = SubAsset<SUB_ASSET_TYPE_PIXEL_SHADER, MaterialPixelShader>;
    using SubAssetAccuracyGraph = SubAsset<SUB_ASSET_TYPE_ACCURACY_GRAPH, AccuracyGraph>;
    using SubAssetFlameTable = SubAsset<SUB_ASSET_TYPE_FLAME_TABLE, FlameTable>;
} // namespace T5

DEFINE_ASSET_NAME_ACCESSOR(T5::AssetPhysPreset, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetPhysConstraints, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetDestructibleDef, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetXAnim, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetXModel, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetMaterial, info.name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetTechniqueSet, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetImage, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetSoundBank, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetSoundPatch, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetClipMap, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetClipMapPvs, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetComWorld, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetGameWorldSp, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetGameWorldMp, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetMapEnts, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetGfxWorld, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetLightDef, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetFont, fontName);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetMenuList, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetMenu, window.name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetLocalize, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetWeapon, szInternalName);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetSoundDriverGlobals, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetFx, name);
DEFINE_ASSET_NAME_ACCESSOR_SINGLETON(T5::AssetImpactFx, "ImpactFx");
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetRawFile, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetStringTable, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetPackIndex, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetXGlobals, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetDDL, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetGlasses, name);
DEFINE_ASSET_NAME_ACCESSOR_SINGLETON(T5::AssetEmblemSet, "EmblemSet");
