#ifndef _SQMOD_EVENT_BASIC_HPP_
#define _SQMOD_EVENT_BASIC_HPP_

// ------------------------------------------------------------------------------------------------
#include "Common.hpp"
#include "Shared.hpp"

// ------------------------------------------------------------------------------------------------
#include <chrono>

// ------------------------------------------------------------------------------------------------
namespace SqMod {

/* ------------------------------------------------------------------------------------------------
 * ...
*/
class BasicEvent
{
protected:

    // --------------------------------------------------------------------------------------------
    typedef std::chrono::time_point< std::chrono::steady_clock > TimePoint;

public:

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    BasicEvent();

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    BasicEvent(SQInt32 type);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    BasicEvent(SQInt32 type, bool suspended);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    BasicEvent(const BasicEvent &) = delete;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    BasicEvent(BasicEvent &&) = delete;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    ~BasicEvent();

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    BasicEvent & operator = (const BasicEvent &) = delete;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    BasicEvent & operator = (BasicEvent &&) = delete;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    bool operator == (const BasicEvent & o) const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    bool operator != (const BasicEvent & o) const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    bool operator < (const BasicEvent & o) const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    bool operator > (const BasicEvent & o) const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    bool operator <= (const BasicEvent & o) const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    bool operator >= (const BasicEvent & o) const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    operator SQInt32 () const
    {
        return m_Type;
    }

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    operator bool () const
    {
        return (m_Type != EVT_UNKNOWN && m_Type < EVT_COUNT);
    }

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    operator ! () const
    {
        return (m_Type == EVT_UNKNOWN || m_Type >= EVT_COUNT);
    }

    /* --------------------------------------------------------------------------------------------
      * ...
     */
    void VMClose();

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    SQInt32 Cmp(const BasicEvent & o) const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    const SQChar * GetName() const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    const SQChar * GetTag() const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SetTag(const SQChar * tag);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    SqObj & GetData();

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SetData(SqObj & data);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    SQInt32 GetType() const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SetType(SQInt32 type);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    SQInteger GetIdle() const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SetIdle(SQInteger millis);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    bool IsIdle() const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    SQInt32 GetStride() const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SetStride(SQInt32 stride);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    SQInt32 GetIgnore() const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SetIgnore(SQInt32 ignore);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    SQInt32 GetPrimary() const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SetPrimary(SQInt32 subset);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    SQInt32 GetSecondary() const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SetSecondary(SQInt32 subset);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    bool GetSuspended() const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SetSuspended(bool toggle);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    Function GetOnTrigger() const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SetOnTrigger(Function & func);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SetOnTrigger_Env(SqObj & env, Function & func);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    bool Compatible(SQInt32 type) const;

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void BlipCreated(SQInt32 blip, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void CheckpointCreated(SQInt32 checkpoint, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void KeybindCreated(SQInt32 keybind, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ObjectCreated(SQInt32 object, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PickupCreated(SQInt32 pickup, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerCreated(SQInt32 player, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SphereCreated(SQInt32 sphere, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SpriteCreated(SQInt32 sprite, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void TextdrawCreated(SQInt32 textdraw, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void VehicleCreated(SQInt32 vehicle, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void BlipDestroyed(SQInt32 blip, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void CheckpointDestroyed(SQInt32 checkpoint, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void KeybindDestroyed(SQInt32 keybind, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ObjectDestroyed(SQInt32 object, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PickupDestroyed(SQInt32 pickup, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerDestroyed(SQInt32 player, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SphereDestroyed(SQInt32 sphere, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SpriteDestroyed(SQInt32 sprite, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void TextdrawDestroyed(SQInt32 textdraw, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void VehicleDestroyed(SQInt32 vehicle, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void BlipCustom(SQInt32 blip, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void CheckpointCustom(SQInt32 checkpoint, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void KeybindCustom(SQInt32 keybind, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ObjectCustom(SQInt32 object, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PickupCustom(SQInt32 pickup, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerCustom(SQInt32 player, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SphereCustom(SQInt32 sphere, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SpriteCustom(SQInt32 sprite, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void TextdrawCustom(SQInt32 textdraw, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void VehicleCustom(SQInt32 vehicle, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerAway(SQInt32 player, bool status);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerGameKeys(SQInt32 player, SQInt32 previous, SQInt32 current);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerRename(SQInt32 player, const SQChar * previous, const SQChar * current);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerRequestClass(SQInt32 player, SQInt32 offset);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerRequestSpawn(SQInt32 player);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerSpawn(SQInt32 player);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerStartTyping(SQInt32 player);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerStopTyping(SQInt32 player);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerChat(SQInt32 player, const SQChar * message);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerCommand(SQInt32 player, const SQChar * command);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerMessage(SQInt32 player, SQInt32 receiver, const SQChar * message);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerHealth(SQInt32 player, SQFloat previous, SQFloat current);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerArmour(SQInt32 player, SQFloat previous, SQFloat current);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerWeapon(SQInt32 player, SQInt32 previous, SQInt32 current);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerMove(SQInt32 player, const Vector3 & previous, const Vector3 & current);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerWasted(SQInt32 player, SQInt32 reason);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerKilled(SQInt32 player, SQInt32 killer, SQInt32 reason, SQInt32 body_part);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerTeamKill(SQInt32 player, SQInt32 killer, SQInt32 reason, SQInt32 body_part);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerSpectate(SQInt32 player, SQInt32 target);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerCrashreport(SQInt32 player, const SQChar * report);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerBurning(SQInt32 player, bool state);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerCrouching(SQInt32 player, bool state);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerState(SQInt32 player, SQInt32 previous, SQInt32 current);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PlayerAction(SQInt32 player, SQInt32 previous, SQInt32 current);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void StateNone(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void StateNormal(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void StateShooting(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void StateDriver(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void StatePassenger(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void StateEnterDriver(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void StateEnterPassenger(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void StateExitVehicle(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void StateUnspawned(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ActionNone(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ActionNormal(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ActionAiming(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ActionShooting(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ActionJumping(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ActionLieDown(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ActionGettingUp(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ActionJumpVehicle(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ActionDriving(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ActionDying(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ActionWasted(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ActionEmbarking(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ActionDisembarking(SQInt32 player, SQInt32 previous);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void VehicleRespawn(SQInt32 vehicle);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void VehicleExplode(SQInt32 vehicle);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void VehicleHealth(SQInt32 vehicle, SQFloat previous, SQFloat current);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void VehicleMove(SQInt32 vehicle, const Vector3 & previous, const Vector3 &current);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PickupRespawn(SQInt32 pickup);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void KeybindKeyPress(SQInt32 player, SQInt32 keybind);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void KeybindKeyRelease(SQInt32 player, SQInt32 keybind);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void VehicleEmbarking(SQInt32 player, SQInt32 vehicle, SQInt32 slot);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void VehicleEmbarked(SQInt32 player, SQInt32 vehicle, SQInt32 slot);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void VehicleDisembark(SQInt32 player, SQInt32 vehicle);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PickupClaimed(SQInt32 player, SQInt32 pickup);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void PickupCollected(SQInt32 player, SQInt32 pickup);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ObjectShot(SQInt32 player, SQInt32 object, SQInt32 weapon);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ObjectBump(SQInt32 player, SQInt32 object);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void CheckpointEntered(SQInt32 player, SQInt32 checkpoint);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void CheckpointExited(SQInt32 player, SQInt32 checkpoint);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SphereEntered(SQInt32 player, SQInt32 sphere);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void SphereExited(SQInt32 player, SQInt32 sphere);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ServerFrame(SQFloat delta);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ServerStartup();

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ServerShutdown();

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void InternalCommand(SQInt32 type, const SQChar * text);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void LoginAttempt(const SQChar * name, const SQChar * pass, const SQChar * addr);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void CustomEvent(SQInt32 group, SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void WorldOption(SQInt32 option, Object & value);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void WorldToggle(SQInt32 option, bool value);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void ScriptReload(SQInt32 header, Object & payload);

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void LogMessage(SQInt32 type, const SQChar * message);

protected:

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    bool Trigger();

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void Attach();

    /* --------------------------------------------------------------------------------------------
     * ...
    */
    void Detach();

private:

    // --------------------------------------------------------------------------------------------
    SQInt32             m_Type;

    // --------------------------------------------------------------------------------------------
    SQInt32             m_Stride;
    SQInt32             m_Ignore;

    // --------------------------------------------------------------------------------------------
    SQInt32             m_Primary;
    SQInt32             m_Secondary;

    // --------------------------------------------------------------------------------------------
    TimePoint           m_Idle;

    // --------------------------------------------------------------------------------------------
    Function            m_OnTrigger;

    // --------------------------------------------------------------------------------------------
    SqTag               m_Tag;
    SqObj               m_Data;

    // --------------------------------------------------------------------------------------------
    bool                m_Suspended;
};

} // Namespace:: SqMod

#endif // _SQMOD_EVENT_BASIC_HPP_