#include <trx/core/math.h>
#include <trx/core/utils.h>
#include <trx/game/creature.h>
#include <trx/game/game.h>
#include <trx/game/game_buf.h>
#include <trx/game/items/carrier.h>
#include <trx/game/lara.h>
#include <trx/game/objects/common.h>
#include <trx/game/pathing.h>
#include <trx/game/savegame.h>

// clang-format off
#define M_HIT_POINTS 18
// clang-format on

typedef enum {
    M_STATE_EMPTY,
    M_STATE_STOP,
    M_STATE_DEATH,
} M_STATE;

static bool M_CanDropItems(const ITEM *const item)
{
    return item->hit_points <= 0 || item->is_finished;
}

static void M_Initialise(const int16_t item_num)
{
    ITEM *const item = Item_Get(item_num);
    item->touch_bits = 0;
    item->mesh_bits = 0xFFFF87FF;
}

static void M_Control(const int16_t item_num)
{
    ITEM *const item = Item_Get(item_num);
    int16_t head = 0;

    if (Item_IsTriggerActive(item)) {
        if (!LOT_EnableBaddieAI(item_num, true)) {
            return;
        }
        Item_SetVisible(item, true);
    }

    if (item->current_anim_state == M_STATE_STOP) {
        const ITEM *const lara_item = Lara_GetItem();
        head =
            Math_Atan(
                lara_item->pos.z - item->pos.z, lara_item->pos.x - item->pos.x)
            - item->rot.y;
        CLAMP(head, -FRONT_ARC, FRONT_ARC);

        if (item->hit_points <= 0 || item->touch_bits) {
            item->goal_anim_state = M_STATE_DEATH;
        }
    }

    Creature_Head(item, head);
    Item_Animate(item);

    if (item->is_finished) {
        // The mummy topples when Lara touches it, rather than taking damage.
        Item_TakeFatalDamage(item, Lara_GetItem());
        Item_RemoveSimulated(item_num);
        Carrier_TestItemDrops(item_num);
    }
}

static void M_Setup(OBJECT *const obj)
{
    if (!obj->loaded) {
        return;
    }

    obj->initialise_func = M_Initialise;
    obj->control_func = M_Control;
    obj->collision_func = Object_Collision;
    obj->can_drop_items_func = M_CanDropItems;

    obj->leaves_corpse = true;
    obj->save_flags = true;
    obj->save_hitpoints = true;
    obj->save_anim = true;

    Object_GetBone(obj, 2)->rot.y = true;
    OBJECT_PROPERTIES(obj, ITEM_PROPERTY_MAX_HIT_POINTS(M_HIT_POINTS));
}

REGISTER_OBJECT(O_MUMMY, M_Setup)
