#ifndef _SITHSURFACE_H
#define _SITHSURFACE_H

#include "types.h"
#include "globals.h"
#include "Raster/rdFace.h"

#define sithSurface_HideSectorAdjoin_ADDR (0x004E5A10)
#define sithSurface_ShowSectorAdjoin_ADDR (0x004E5A30)
#define sithSurface_AllocWorldSurfaces_ADDR (0x004E5A50)
#define sithSurface_sub_4E5AD0_ADDR (0x004E5AD0)
#define sithSurface_FreeWorldSurfaces_ADDR (0x004E5B40)
#define sithSurface_ReadSurfacesListText_ADDR (0x004E5C00)
#define sithSurface_ValidateSurfacePointer_ADDR (0x004E6190)
#define sithSurface_ValidateWorldSurfaces_ADDR (0x004E61B0)
#define sithSurface_HandleThingImpact_ADDR (0x004E61F0)
#define sithSurface_GetCenterPoint_ADDR (0x004E6250)
#define sithSurface_SyncSurface_ADDR (0x004E6330)
#define sithSurface_SyncSurfaces_ADDR (0x004E6360)
#define sithSurface_sub_4E63B0_ADDR (0x004E63B0)
#define sithSurface_Startup_ADDR (0x004EF900)
#define sithSurface_Shutdown_ADDR (0x004EF950)
#define sithSurface_Open_ADDR (0x004EF960)
#define sithSurface_Startup2_ADDR (0x004EF970)
#define sithSurface_Startup3_ADDR (0x004EF9C0)
#define sithSurface_StopAnim_ADDR (0x004EFA10)
#define sithSurface_GetSurfaceAnim_ADDR (0x004EFAC0)
#define sithSurface_SlideWall_ADDR (0x004EFB20)
#define sithSurface_SlideHorizonSky_ADDR (0x004EFFF0)
#define sithSurface_sub_4F00A0_ADDR (0x004F00A0)
#define sithSurface_SurfaceAnim_ADDR (0x004F0180)
#define sithSurface_MaterialAnim_ADDR (0x004F02C0)
#define sithSurface_SurfaceLightAnim_ADDR (0x004F03F0)
#define sithSurface_SetSectorLight_ADDR (0x004F04A0)
#define sithSurface_SetThingLight_ADDR (0x004F0560)
#define sithSurface_Tick_ADDR (0x004F0630)
#define sithSurface_GetRdSurface_ADDR (0x004F09F0)
#define sithSurface_DetachThing_ADDR (0x004F0A30)
#define sithSurface_GetByIdx_ADDR (0x004F0AA0)
#define sithSurface_Alloc_ADDR (0x004F0AF0)
#define sithSurface_SyncFull_ADDR (0x004F0B50)
#define sithSurface_ScrollSky_ADDR (0x004F0BC0)

#define SITH_SURFACE_HORIZONSKY (0x200)
#define SITH_SURFACE_CEILINGSKY (0x400)

#ifdef TARGET_TWL
extern uint8_t sithSurface_skyColorGuess;
#endif

enum SithSurfaceFlag
{
    SITH_SURFACE_FLOOR = 0x1,
    SITH_SURFACE_COG_LINKED = 0x2,
    SITH_SURFACE_HAS_COLLISION = 0x4,
    SITH_SURFACE_AI_CAN_WALK_ON_FLOOR = 0x8, // from jkdf2 docs
    SITH_SURFACE_DOUBLE_TEXTURE_SCALE = 0x10,
    SITH_SURFACE_HALF_TEXTURE_SCALE = 0x20,
    SITH_SURFACE_EIGHT_TEXTURE_SCALE = 0x40,
    SITH_SURFACE_80 = 0x80, // Jones specific: AETHERIUM
    SITH_SURFACE_HORIZON_SKY = 0x200,
    SITH_SURFACE_CEILING_SKY = 0x400,
    SITH_SURFACE_SCROLLING = 0x800,
    SITH_SURFACE_ICY = 0x1000, // Jones specific: KILL_FLOOR
    SITH_SURFACE_VERYICY = 0x2000, // Jones specific: CLIMBABLE
    SITH_SURFACE_MAGSEALED = 0x4000, // Jones specific: TRACK
    SITH_SURFACE_CHANGED = 0x8000,
    SITH_SURFACE_METAL = 0x10000,
    SITH_SURFACE_WATER = 0x20000,
    SITH_SURFACE_PUDDLE = 0x40000,
    SITH_SURFACE_EARTH = 0x80000,
    SITH_SURFACE_VERYDEEPWATER = 0x100000,
    SITH_SURFACE_200000 = 0x200000,
    SITH_SURFACE_400000 = 0x400000,
    SITH_SURFACE_800000 = 0x800000,
    SITH_SURFACE_1000000 = 0x1000000,

    /*SITH_SURFACE_EARTH = 0x80000, // Jones specific
    SITH_SURFACE_WEB = 0x100000, // Jones specific
    SITH_SURFACE_LAVA = 0x200000, // Jones specific
    SITH_SURFACE_SNOW = 0x400000, // Jones specific
    SITH_SURFACE_WOOD = 0x800000, // Jones specific
    SITH_SURFACE_LEDGE = 0x1000000, // Jones specific
    SITH_SURFACE_WATER_CLIMBOUT_LEDGE = 0x2000000, // Jones specific
    SITH_SURFACE_QUARTER_SURFACE_SCALE = 0x4000000, // Jones specific
    SITH_SURFACE_QUADRUPLE_SURFACE_SCALE = 0x8000000, // Jones specific
    SITH_SURFACE_WHIP_AIM = 0x10000000, // Jones specific
    SITH_SURFACE_ECHO = 0x20000000, // Jones specific
    SITH_SURFACE_WOOD_ECHO = 0x40000000, // Jones specific
    SITH_SURFACE_EARTH_ECHO = 0x80000000, // Jones specific
    */
};

enum SithSurfaceAdjoinFlag
{
    SITHSURF_ADJOIN_VISIBLE = 0x1,
    SITHSURF_ADJOIN_ALLOW_MOVEMENT = 0x2, // ADJOIN_MOVE
    SITHSURF_ADJOIN_ALLOW_SOUND = 0x4,
    SITHSURF_ADJOIN_ALLOW_PLAYER_ONLY = 0x8,
    SITHSURF_ADJOIN_ALLOW_AI_ONLY = 0x10,
    SITHSURF_ADJOIN_SET_BY_SECTOR = 0x20,
    SITHSURF_ADJOIN_40 = 0x40,
    SITHSURF_ADJOIN_80 = 0x80,
};

int sithSurface_Startup();
void sithSurface_Shutdown();
int sithSurface_Open();
int sithSurface_ValidateWorldSurfaces(SithWorld *pWorld);
int sithSurface_ReadSurfacesListText(SithWorld *pWorld);
int sithSurface_ValidateSurfacePointer(SithSurface *pSurf);
void sithSurface_HideSectorAdjoin(SithSurfaceAdjoin *pAdjoin);
void sithSurface_ShowSectorAdjoin(SithSurfaceAdjoin *pAdjoin);
rdSurface* sithSurface_SurfaceAnim(SithSurface *parent, flex_t a2, uint16_t flags);
int sithSurface_Startup2();
int sithSurface_Startup3();
void sithSurface_SetSectorLight(SithSector *sector, flex_t extraLight, flex_t a3, int a4);
int sithSurface_AllocWorldSurfaces(SithWorld *pWorld, int numSurfaces);
int sithSurface_AllocWorldAdjoins(SithWorld *pWorld, int numAdjoins);
void sithSurface_FreeWorldSurfaces(SithWorld *pWorld);
MATH_FUNC void sithSurface_Tick(flex_t deltaSecs);
MATH_FUNC void sithSurface_ScrollSky(rdSurface *surface, int flags, flex_t deltaSecs, uint8_t a4);
int sithSurface_StopAnim(rdSurface *surface);
uint32_t sithSurface_GetSurfaceAnim(SithSurface *surface);
rdSurface* sithSurface_SurfaceLightAnim(SithSurface *surface, flex_t a2, flex_t a3);
MATH_FUNC rdSurface* sithSurface_SlideWall(SithSurface *surface, rdVector3 *a2);
rdSurface* sithSurface_MaterialAnim(rdMaterial *material, flex_t a2, int a3);
void sithSurface_DetachThing(SithSurface *a1, rdVector3 *out);
int sithSurface_GetCenterPoint(SithSurface *pSurface, rdVector3 *centerpoint);
rdSurface* sithSurface_SlideHorizonSky(int flags, rdVector2 *a2);
rdSurface* sithSurface_sub_4F00A0(SithThing *thing, flex_t a2, uint32_t a3);
rdSurface* sithSurface_SetThingLight(SithThing *thing, flex_t a2, flex_t a3, int a4);
void sithSurface_HandleThingImpact(SithSurface *pSurf, SithThing *pThing, flex_t damage, int damageType);
rdSurface* sithSurface_GetRdSurface(SithSurface *surface);
rdSurface* sithSurface_GetByIdx(int idx);
void sithSurface_SyncFull(int mpFlags);
rdSurface* sithSurface_Alloc();
SithSurface* sithSurface_sub_4E63B0(int idx);
void sithSurface_SyncSurface(SithSurface *pSurface);
void sithSurface_SyncSurfaces();

//static void (*sithSurface_Shutdown)() = (void*)sithSurface_Shutdown_ADDR;
//static int (*sithSurface_Startup)() = (void*)sithSurface_Startup_ADDR;
//static int (*_sithSurface_Load)(SithWorld*) = (void*)sithSurface_ReadSurfacesListText_ADDR;
//static void (__cdecl *sithSurface_HandleThingImpact)(SithSurface *pMeshCollided, SithThing *pThingCollided, flex_t damage, int damageType) = (void*)sithSurface_HandleThingImpact_ADDR;
//static int* (*_sithSurface_SurfaceAnim)(void*, flex_t, int) = (void*)sithSurface_SurfaceAnim_ADDR;
//static int* (*sithSurface_MaterialAnim)(void*, flex_t, int) = (void*)sithSurface_MaterialAnim_ADDR;
//static rdSurface* (*sithSurface_GetByIdx)(int) = (void*)sithSurface_GetByIdx_ADDR;
//static int (*sithSurface_StopAnim)(rdSurface *a1) = (void*)sithSurface_StopAnim_ADDR;
//static rdSurface* (__cdecl *sithSurface_GetRdSurface)(SithSurface *a1) = (void*)sithSurface_GetRdSurface_ADDR;
//static int (*sithSurface_GetSurfaceAnim)(SithSurface *a1) = (void*)sithSurface_GetSurfaceAnim_ADDR;
//static rdSurface* (*sithSurface_SetThingLight)(SithThing *a1, flex_t a2, flex_t a3, int a4) = (void*)sithSurface_SetThingLight_ADDR;
//static rdSurface* (*sithSurface_sub_4F00A0)(SithThing *a1, flex_t a2, int a3) = (void*)sithSurface_sub_4F00A0_ADDR;
//static void (*sithSurface_FreeWorldSurfaces)(SithWorld* world) = (void*)sithSurface_FreeWorldSurfaces_ADDR;
//static void (*_sithSurface_Tick)(flex_t time) = (void*)sithSurface_Tick_ADDR;
//static rdSurface* (*sithSurface_SlideHorizonSky)(int a1, rdVector2 *a2) = (void*)sithSurface_SlideHorizonSky_ADDR;
//static rdSurface* (*sithSurface_SurfaceLightAnim)(SithSurface *surface, flex_t a2, flex_t a3) = (void*)sithSurface_SurfaceLightAnim_ADDR;
//static rdSurface* (*sithSurface_SlideWall)(SithSurface *surface, rdVector3 *a2) = (void*)sithSurface_SlideWall_ADDR;
//static uint32_t (*sithSurface_SyncSurface)(SithSurface *a1) = (void*)sithSurface_SyncSurface_ADDR;
//static void (*sithSurface_DetachThing)(SithSurface *a1, rdVector3 *out) = (void*)sithSurface_DetachThing_ADDR;
//static void (*sithSurface_ScrollSky)(rdSurface *surface, int a2, flex_t a3, int a4) = (void*)sithSurface_ScrollSky_ADDR;
//static int (*sithSurface_GetCenterPoint)(SithSurface *a1, rdVector3 *a2) = (void*)sithSurface_GetCenterPoint_ADDR;

//static void (*sithSurface_SyncFull)(int mpFlags) = (void*)sithSurface_SyncFull_ADDR;

#endif // _SITHSURFACE_H
