#ifndef UTILITY_H_INCLUDED
#define UTILITY_H_INCLUDED

#include <trng_core.h>
#include <cstdlib>

#define FL_HOLD_FT		  1
#define FL_THROW_FT		  32
#define FL_DRAW_FT		  39
#define FL_IGNITE_FT	  23
#define FL_2HOLD_FT		  15
#define FL_HOLD_F		  0
#define FL_THROW_F		  (FL_HOLD_F+FL_HOLD_FT)
#define FL_DRAW_F		  (FL_THROW_F+FL_THROW_FT)
#define FL_IGNITE_F		  (FL_DRAW_F+FL_DRAW_FT)
#define FL_2HOLD_F		  (FL_IGNITE_F+FL_IGNITE_FT)
#define FL_END_F		  (FL_2HOLD_F+FL_2HOLD_FT)
#define FL_DRAWGOTIT_F	  (13+FL_DRAW_F)
#define FL_PICKUP_F		  (58+FL_PICKINGUP_F)
#define FL_THROWRELEASE_F (20+FL_THROW_F)
#define FL_THROW_FRAMES	  32

enum ControlVehicles
{
    IN_ACTION, // accel one
    IN_FORWARD,
    IN_BACKWARD,
    IN_LEFT,
    IN_RIGHT,
    IN_SLOW,
    IN_SPACE,
    IN_LEFT_RIGHT,
    IN_UP_DOWN,
    IN_JUMP,
    IN_ROLL,
    IN_LOOK
};

enum VehicleID
{
    VEH_SNOWMOBILE = 1,
    VEH_QUAD,
    VEH_MINECART,
    VEH_UW_PROPELLER,
    VEH_BOAT,
    VEH_KAYAK,
    VEH_CANNON_CRASHSITE,
    VEH_JEEP,
    VEH_MOTORBIKE,
    VEH_MOTORBOAT,      // TRNG Command (Dont Use it !!)
    VEH_RUBBERBOA,      // TRNG Command (Dont Use it !!)
    VEH_MECHWARRIOR,    // TRNG Command (Dont Use it !!)
    VEH_NUMBER,
};

enum FloorSoundID
{
    FS_MUD,
    FS_SNOW,
    FS_SAND,
    FS_GRAVEL,
    FS_ICE,
    FS_WATER,
    FS_STONE,
    FS_WOOD,
    FS_METAL,
    FS_MARBLE,
    FS_GRASS,
    FS_CONCRETE,
    FS_OLD_WOOD,
    FS_OLD_METAL
};


class Utility
{
private:
    class Footstep
    {
    private:
        //MudID, SnowID, SandID, GravelID, IceID, WaterID, StoneID, WoodID, MetalID, MarbleID, GrassID, ConcreteID, OldWoodID, OldMetalID
        struct FootstepID
        {
            short mud;
            short snow;
            short sand;
            short gravel;
            short ice;
            short water;
            short stone;
            short wood;
            short metal;
            short marble;
            short grass;
            short concrete;
            short old_wood;
            short old_metal;
        };
        FootstepID footstep, footstep_default;
        bool isFootstepCustomizeExist();
        short getCustomizeFootstep(FloorSoundID sound_id);
        void setCustomizeFootstep(FloorSoundID sound_id);

    public:
        void initialiseFootstep();
        void setFootstep(FloorSoundID sound_id, short newID);
        short getFootstep(FloorSoundID sound_id);
    };

    class ConvertToCHAR
    {
        public:
            LPSTR FootstepToCHAR(FloorSoundID sound_id);
            LPSTR GunTypeToCHAR(short value);
            LPSTR WaterStatusToCHAR(short value);
            LPSTR FlareAgeToCHAR(short value);
            LPSTR WeaponBackItemToCHAR(short value);
    };

    bool getSnowmobileControl(ControlVehicles control);

    class FindClass
    {
    private:

    public:
        void Statics(ITEM_INFO* item, int *pStaticIndex, int *pStaticRoom);
        // return the moveables on the slot_number only !
        ITEM_INFO* Moveables(ITEM_INFO* item, short slot_number, int distance);
        // return all entities (with hit_points is different from NOT_TARGETABLE and NULL)
        ITEM_INFO* Entity(ITEM_INFO* item, short slot_number, int distance);
        // return all moveable (pushblock) item
        ITEM_INFO* PushBlock(ITEM_INFO* item);
    };

public:
    Footstep FootstepSFX;
    ConvertToCHAR Convert;
    FindClass Search;

    // only usable in InitialiseSlot() !!
    void EnableZone(short object, CREATURE_INFO* creature);
    // if the plugin exist and activated return true !
    bool getPlugin(LPSTR name);
    short getLinks(int tsu_links_flags, int link_type);
    short getObjects(int tsu_objects_flags);
    void jmn_PopMatrix();
    int getRelativeAnimation(ITEM_INFO* item);
    int getRelativeFrame(ITEM_INFO* item);
    bool getPluginAimingStatus();
    bool getPluginAiming(int TSU_flags);
    void ShootAtLara(FX_INFO* fx);
    void DrawMuzzleFlash_LightAndSmoke(ITEM_INFO* item, BITE_INFO *bite);
    int EnemyShot(ITEM_INFO *item, AI_INFO *info, BITE_INFO *bite, short torso_angle, int damage);
    short getObjectAttribute(int slot_id, int attribute_type);
    short getObjectProperty(int slot_id, int property_type);
    short getObjectOption(int slot_id, int option_type);
    short getObjectMeshswap(int slot_id, int mesh_id, int meshswap_type);
	short getObjectSprite(int slot_id, int sprite_type);
    bool getVehicleControl(VehicleID id, ControlVehicles control);
    bool getFloorSound(ITEM_INFO* item, FloorSoundID sound_id_to_get);
    int getSnowmobileSound(short SNOW_flags);
    void checkWaterHeight_Vehicles(ITEM_INFO* item, void(*SkidooExplode)(ITEM_INFO *current_vehicle));
    template<typename R> R convertTo(std::string value);
    bool Inv_RequestItem(short slot);
    void Inv_RemoveItem(short slot);
    bool IsVaultEnabled(short object, int vault);
	void AddPoison(short poison);
	short GetPoison();

    bool isFolderExists(LPCSTR folder_name);
    bool isFileExists(LPCSTR file_name);
    void createFolders(LPCSTR folder_name);
};

void draw_flare(void);
void undraw_flare(void);
void DrawAnimatingItemCustom(ITEM_INFO* item);

template<typename R>
inline R Utility::convertTo(std::string value)
{
    R result;
    result = (R)atoi(value.c_str());
    return (R)result;
}

class WeaponParser
{
public:
    // first
    void Initialize();

    /// middle
    void setName(LPCSTR name);
    void setLock(short ymin, short ymax, short xmin, short xmax);
    void setLeft(short ymin, short ymax, short xmin, short xmax);
    void setRight(short ymin, short ymax, short xmin, short xmax);
    void setAimSpeed(short value);
    void setShotAccuracy(short value);
    void setGunHeight(short value);
    void setTargetDistance(short value);
    void setDamage(char value);
    void setRecoilFrame(char value);
    void setFlashTime(char value);
    void setDrawFrame(char value);
    void setSampleNumber(short value);

    // end
    void Save(LPCSTR file_name);

    // other
    void setComment(LPCSTR contents);
};

extern Utility Utils;
extern WeaponParser WeapParser;

int MapToFirst(int value, int size);
void RotateItem(short* orientation);
void GetBaddieTarget(short item_number, bool is_monk);
DWORD DecodeTimer(WORD Timer, WORD Extra);

#endif