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

typedef struct actor_wallfirer_s
{
    object_t *self_object;
    sprite_t *sprite;
    vector_t  position;
    int       direction;
    int       sleep_reload;
} actor_wallfirer_t;

static void _Actor_Wallfirer_CreateAnimations(actor_wallfirer_t *actor)
{
    Sprite_AnimationAdd(actor->sprite, "up", 8);
    Sprite_AnimationAdd(actor->sprite, "right", 8);
    Sprite_AnimationAdd(actor->sprite, "down", 8);
    Sprite_AnimationAdd(actor->sprite, "left", 8);
    Sprite_AnimationAddFrame(actor->sprite, "up", Utils_GetRect(48, 0, 16, 16));
    Sprite_AnimationAddFrame(actor->sprite, "right", Utils_GetRect(0, 0, 16, 16));
    Sprite_AnimationAddFrame(actor->sprite, "down", Utils_GetRect(16, 0, 16, 16));
    Sprite_AnimationAddFrame(actor->sprite, "left", Utils_GetRect(32, 0, 16, 16));
}

static void _Actor_Wallfirer_GetInfo(actor_wallfirer_t *actor, object_info_t *info)
{
    if (actor == NULL)
        return;

    if (info == NULL)
        return;

    info->box_rect       = Utils_GetRect(0, 0, 0, 0);
    info->collision_rect = Utils_GetRect(0, 0, 0, 0);
    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->box_rect.w = actor->sprite->width;
        info->box_rect.h = actor->sprite->height;
    }

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

static void _Actor_Wallfirer_Update(actor_wallfirer_t *actor, float dt)
{
    if (actor == NULL)
        return;

    actor->sleep_reload++;

    if (actor->sleep_reload > 300)
    {
        actor->sleep_reload = 0;

        float fireball_x = actor->position.x;
        float fireball_y = actor->position.y;

        switch(actor->direction)
        {
            case 0  : fireball_y = actor->position.y - 34; break;
            case 1  : fireball_x = actor->position.x + 34; break;
            case 2  : fireball_y = actor->position.y + 34; break;
            case 3  : fireball_x = actor->position.x - 34; break;
        }

        object_t *object = FactoryObjects_Create();
        Actor_Fireball_Create(object, actor->direction, fireball_x, fireball_y);
    }

    Sprite_Update(actor->sprite);
}

static void _Actor_Wallfirer_Draw(SDL_Renderer *renderer, actor_wallfirer_t *actor)
{
    if (actor == NULL)
        return;

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

static void _Actor_Wallfirer_Free(actor_wallfirer_t *actor)
{
    if (actor == NULL)
        return;

    Sprite_Free(actor->sprite);

    free(actor);

    actor = NULL;
}

void Actor_Wallfirer_Create(object_t *object, int direction, float x, float y)
{
    if (object != NULL)
    {
        actor_wallfirer_t *actor = (actor_wallfirer_t*)malloc(sizeof(actor_wallfirer_t));

        actor->self_object = object;

        FactoryObjects_SetActor(object, (void*)actor, AT_WALLFIRER, OLAY_ENEMYES);

        FactoryObjects_SetFunc(object, _Actor_Wallfirer_GetInfo, OFUNC_GETINFO);
        FactoryObjects_SetFunc(object, _Actor_Wallfirer_Update,  OFUNC_UPDATE);
        FactoryObjects_SetFunc(object, _Actor_Wallfirer_Draw,    OFUNC_DRAW);
        FactoryObjects_SetFunc(object, _Actor_Wallfirer_Free,    OFUNC_FREE);

        actor->sprite       = Sprite_Create(Utils_GetPoint(24, 24), 48, 48, wallfirerTex);
        actor->position     = Utils_GetVector(x, y);
        actor->direction    = direction;
        actor->sleep_reload = 0;

        _Actor_Wallfirer_CreateAnimations(actor);

        switch(actor->direction)
        {
            case 0  : Sprite_AnimationPlay(actor->sprite, "up", true);    break;
            case 1  : Sprite_AnimationPlay(actor->sprite, "right", true); break;
            case 2  : Sprite_AnimationPlay(actor->sprite, "down", true);  break;
            case 3  : Sprite_AnimationPlay(actor->sprite, "left", true);  break;
            default : Sprite_AnimationPlay(actor->sprite, "up", true);    break;
        }
    }
}
