#include "systems.h"

#include "../game_state.h"

Rectangle calculateEntityBounds(Position pos, Size size) {
    return (Rectangle) {
            pos.x - size.x * 0.5f,
            pos.y - size.x * 0.5f,
            size.x, size.y
    };
}

bool getEntityBounds(ecs_entity_t entity, Position *outPos, Size *outSize, Rectangle *outBounds) {
    if (!ecs_is_alive(ECS, entity))
        return false;
    const Position *pos = ecs_get(ECS, entity, Position);
    if (!pos)
        return false;
    const Size *size = ecs_get(ECS, entity, Size);
    if (!size)
        return false;

    if (outPos) {
        *outPos = *pos;
    }
    if (outSize) {
        *outSize = *size;
    }
    if (outBounds) {
        *outBounds = (Rectangle) {
                pos->x - size->x * 0.5f,
                pos->y - size->y * 0.5f,
                size->x, size->y
        };
    }
    return true;
}

ecs_entity_t renderCollidersSystem;
ecs_entity_t renderOrientDirSystem;
ecs_entity_t renderArmPositionSystem;
ecs_entity_t renderDebugPathSystem;

ECS_DTOR(SpatialGridID, gridID, {
    Game *game = ecs_singleton_get_mut(ECS, Game);
    bzSpatialGridRemove(game->entityGrid, *gridID);
})
ECS_MOVE(SpatialGridID, dst, src, {
    *dst = *src;
})
ECS_DTOR(Path, path, {
    Game *game = ecs_singleton_get_mut(ECS, Game);
    BzObjectPool *pool = game->pools.pathData;

    PathData *cur = path[i].paths;
    while (cur) {
        bzObjectPoolRelease(pool, cur);
        cur = cur->next;
    }
})
ECS_MOVE(Path, dst, src, {
    *dst = *src;
})

ECS_DTOR(Arms, arms, {
    if (arms->primary) {
        ecs_delete(ECS, arms->primary);
        arms->primary = 0;
    }
    if (arms->secondary) {
        ecs_delete(ECS, arms->secondary);
        arms->secondary = 0;
    }

})
ECS_MOVE(Arms, dst, src, {
   *dst = *src;
})

ECS_DTOR(Building, building, {
    Vec2i pos = building->pos;
    Vec2i size = building->size;
    Game *game = ecs_singleton_get_mut(ECS, Game);
    bzTileMapSetCollisions(&game->map, false, pos.x, pos.y, size.x, size.y);
})
ECS_MOVE(Building, dst, src, {
    *dst = *src;
})

void setupSystems() {
    ecs_set_hooks(ECS, SpatialGridID, {
        .dtor = ecs_dtor(SpatialGridID),
        .move_dtor = ecs_move(SpatialGridID)
    });
    ecs_set_hooks(ECS, Path, {
        .dtor = ecs_dtor(Path),
        .move_dtor = ecs_move(Path)
    });
    ecs_set_hooks(ECS, Arms, {
        .dtor = ecs_dtor(Arms),
        .move_dtor = ecs_move(Arms)
    });
    ecs_set_hooks(ECS, Building, {
        .dtor = ecs_dtor(Building),
        .move_dtor = ecs_move(Building)
    });

    ECS_OBSERVER(ECS, entityPathRemove, EcsOnRemove, Path);

    ECS_SYSTEM(ECS, entityUpdateSpatialID, EcsOnUpdate, Position, Size, Velocity, SpatialGridID);
    ECS_SYSTEM(ECS, entityUpdateKinematic, EcsOnUpdate, Position, Velocity, Steering, Unit);

    ECS_SYSTEM(ECS, entityMoveToTarget, EcsOnUpdate, Position, Velocity, TargetPosition, Steering);
    ECS_SYSTEM(ECS, entityFollowPath, EcsOnUpdate, Path);
    ECS_SYSTEM(ECS, entityUpdateArms, EcsOnUpdate, Position, Velocity, Rotation, Orientation, Arms);

    ECS_SYSTEM(ECS, updateAISystem, EcsOnUpdate, BzBTState);

    ECS_SYSTEM(ECS, updateAnimationState, EcsOnUpdate, Animation, TextureRegion);
    ECS_SYSTEM(ECS, updateAnimation, EcsOnUpdate, Animation, TextureRegion);
    ECS_SYSTEM(ECS, updateEasingSystem, EcsOnUpdate, Easing, Position, Size, Rotation);

    ECS_SYSTEM(ECS, renderDebugPath, EcsOnUpdate, Path);

    ECS_SYSTEM(ECS, renderColliders, EcsOnUpdate, Position, Size);
    ECS_SYSTEM(ECS, renderOrientationDirection, EcsOnUpdate, Position, Orientation);
    ECS_SYSTEM(ECS, renderArmPosition, EcsOnUpdate, Position, Arm);

    renderDebugPathSystem = renderDebugPath;
    renderOrientDirSystem = renderOrientationDirection;
    renderArmPositionSystem = renderArmPosition;
    renderCollidersSystem = renderColliders;

    //ecs_enable(ECS, renderOrientDirSystem, false);
    //ecs_enable(ECS, renderArmPositionSystem, false);
}
