#include "../utils.h"
#include "../factory_objects.h"
#include "../resources.h"
#include "../camera.h"

typedef struct actor_checkpoint_s
{
    object_t *self_object;
    sprite_t *sprite;
    vector_t  position;
    bool      up;
} actor_checkpoint_t;

static void _Actor_Checkpoint_CreateAnimations(actor_checkpoint_t *actor)
{
    Sprite_AnimationAdd(actor->sprite, "idle", 8);
    Sprite_AnimationAdd(actor->sprite, "up", 5);
    Sprite_AnimationAddFrame(actor->sprite, "idle", Utils_GetRect(0,   0, 24, 24));
    Sprite_AnimationAddFrame(actor->sprite, "idle", Utils_GetRect(24,  0, 24, 24));
    Sprite_AnimationAddFrame(actor->sprite, "idle", Utils_GetRect(48,  0, 24, 24));
    Sprite_AnimationAddFrame(actor->sprite, "idle", Utils_GetRect(72,  0, 24, 24));
    Sprite_AnimationAddFrame(actor->sprite, "idle", Utils_GetRect(96,  0, 24, 24));
    Sprite_AnimationAddFrame(actor->sprite, "idle", Utils_GetRect(120, 0, 24, 24));

    Sprite_AnimationAddFrame(actor->sprite, "up", Utils_GetRect(0,   24, 24, 24));
    Sprite_AnimationAddFrame(actor->sprite, "up", Utils_GetRect(24,  24, 24, 24));
    Sprite_AnimationAddFrame(actor->sprite, "up", Utils_GetRect(48,  24, 24, 24));
    Sprite_AnimationAddFrame(actor->sprite, "up", Utils_GetRect(72,  24, 24, 24));
    Sprite_AnimationAddFrame(actor->sprite, "up", Utils_GetRect(96,  24, 24, 24));
    Sprite_AnimationAddFrame(actor->sprite, "up", Utils_GetRect(120, 24, 24, 24));
}

static void _Actor_Checkpoint_GetInfo(actor_checkpoint_t *actor, object_info_t *info)
{
    if (actor == NULL)
        return;

    if (info == NULL)
        return;

    info->box_rect       = Utils_GetRect(0, 0, 72, 72);
    info->collision_rect = Utils_GetRect(0, 0, 48, 72);
    info->position       = actor->position;

    if (actor->sprite != NULL)
    {
        info->box_rect.x = actor->position.x - actor->sprite->origin.x;
        info->box_rect.y = actor->position.y - actor->sprite->origin.y;

        info->collision_rect.x = actor->position.x - 24;
        info->collision_rect.y = actor->position.y - actor->sprite->origin.y;
    }

    info->collision_cell_ul = Utils_GetPoint(0, 0);
    info->collision_cell_br = Utils_GetPoint(0, 0);
}

static void _Actor_Checkpoint_Collision(actor_checkpoint_t *actor, void *actor_collision, actor_type_t actor_type)
{
    if (actor == NULL)
        return;

    if (actor_collision == NULL)
        return;

    if (actor_type == AT_ROBO)
    {
        if (!actor->up)
        {
            actor->up = true;

            Actor_Robo_ConnectCheckpoint(actor_collision, actor);

            Sprite_AnimationPlay(actor->sprite, "up", false);
        }
    }
}

static void _Actor_Checkpoint_Update(actor_checkpoint_t *actor, float dt)
{
    if (actor == NULL)
        return;

    if (actor->up)
    {
        if (Sprite_IsNameCurrentAnimation(actor->sprite, "up"))
        {
            if (Sprite_IsEndCurrentAnimation(actor->sprite))
                Sprite_AnimationPlay(actor->sprite, "idle", true);
        }
    }

    Sprite_Update(actor->sprite);
}

static void _Actor_Checkpoint_Draw(SDL_Renderer *renderer, actor_checkpoint_t *actor)
{
    if (actor == NULL)
        return;

    if (actor->sprite != NULL)
    {
        Sprite_Draw(renderer, actor->sprite, actor->position);
    }
}

static void _Actor_Checkpoint_Free(actor_checkpoint_t *actor)
{
    if (actor == NULL)
        return;

    Sprite_Free(actor->sprite);

    free(actor);

    actor = NULL;
}

void Actor_Checkpoint_Create(object_t *object, float x, float y)
{
    if (object != NULL)
    {
        actor_checkpoint_t *actor = (actor_checkpoint_t*)malloc(sizeof(actor_checkpoint_t));

        actor->self_object = object;

        FactoryObjects_SetActor(object, (void*)actor, AT_CHECKPOINT, OLAY_TILES);

        FactoryObjects_SetFunc(object, _Actor_Checkpoint_GetInfo,   OFUNC_GETINFO);
        FactoryObjects_SetFunc(object, _Actor_Checkpoint_Collision, OFUNC_COLLISION);
        FactoryObjects_SetFunc(object, _Actor_Checkpoint_Update,    OFUNC_UPDATE);
        FactoryObjects_SetFunc(object, _Actor_Checkpoint_Draw,      OFUNC_DRAW);
        FactoryObjects_SetFunc(object, _Actor_Checkpoint_Free,      OFUNC_FREE);

        actor->sprite   = Sprite_Create(Utils_GetPoint(36, 36), 72, 72, checkpointTex);
        actor->position = Utils_GetVector(x, y);
        actor->up       = false;

        _Actor_Checkpoint_CreateAnimations(actor);

        Sprite_AnimationPlay(actor->sprite, "up", false);
        Sprite_AnimationStop(actor->sprite);
    }
}

void Actor_Checkpoint_LowerFlag(actor_checkpoint_t *actor)
{
    if (actor == NULL)
        return;

    actor->up = false;

    Sprite_AnimationPlay(actor->sprite, "up", false);
    Sprite_AnimationStop(actor->sprite);
}

vector_t Actor_Checkpoint_GetPosition(actor_checkpoint_t *actor)
{
    vector_t result = Utils_GetVector(0, 0);

    if (actor != NULL)
        result = actor->position;

    return result;
}
