#ifndef PIXELDEFENSE_SYSTEMS_H
#define PIXELDEFENSE_SYSTEMS_H

#include <flecs.h>

#include "../components.h"
#include "../ai_actions.h"

typedef struct Game Game;

/**********************************
 * Utils
 **********************************/

bool entitySetPath(const ecs_entity_t entity, const Vector2 target, Game *game);

/**********************************
 * AI systems
 **********************************/

/*
 * 0: Game (singleton)
 * 1: BzBTState
 */
void updateAISystem(ecs_iter_t *it);

void setAIBehaviour(ecs_entity_t entity, const BzBTNode *root,
                    const AIBlackboard *blackboard);


/**********************************
 * Animation Systems
 **********************************/


/*
 * 1: Animation
 * 2: TextureRegion
 */
void updateAnimationState(ecs_iter_t *it);
/*
 * 0:
 * 1: Animation
 * 2: TextureRegion
 */
void updateAnimation(ecs_iter_t *it);

/*
 * 1: Easing
 */
void updateEasingSystem(ecs_iter_t *it);

/**********************************
 * Entity Systems
 **********************************/

/* Observer (for removing TargetPosition)
 * 0: Game (singleton) for object pool
 * 1: Path
 */
void entityPathRemove(ecs_iter_t *it);

/*
 * 0: Game (singleton) for entity map
 * 1: Position
 * 2: Size
 * 3: Velocity (only entities with velocity change position)
 * 4: SpatialGridID
 */
void entityUpdateSpatialID(ecs_iter_t *it);

/*
 * 0: Game (singleton) for collisions
 * 1: Position
 * 2: Velocity
 * 3: Steering
 * 4: Unit
 */
void entityUpdateKinematic(ecs_iter_t *it);

/*
 * 1: Position
 * 2: Velocity
 * 3: TargetPosition
 * 4: Steering
 */
void entityMoveToTarget(ecs_iter_t *it);

/*
 * 0: Game (singleton) for object pool
 * 1: Path
 */
void entityFollowPath(ecs_iter_t *it);

/*
 * 1. Position
 * 2. Velocity
 * 3. Rotation
 * 4. Orientation
 * 5. Arms
 */
void entityUpdateArms(ecs_iter_t *it);


/*
 * 1: Position
 * 2: Size
 */
void renderColliders(ecs_iter_t *it);

/*
 * 1: Position
 * 2: Orientation
 */
void renderOrientationDirection(ecs_iter_t *it);

/*
 * 1. Position
 * 2. Arm
 */
void renderArmPosition(ecs_iter_t *it);

/*
 * 1: Path
 */
void renderDebugPath(ecs_iter_t *it);

/**********************************
 * Event Systems
 **********************************/

i32  harvestEvent(ecs_entity_t entity, HarvestEvent event);
void depositEvent(ecs_entity_t entity, DepositEvent event);


/**********************************
 * Input systems
 **********************************/

/*
 * Task:
 * 0: Game (singleton)
 * 0: InputState (singleton)
 */
void updatePlayerInput();

/*
 * Task (rendering above ground):
 * 0: Game (singleton)
 * 0: InputState (singleton)
 */
void drawPlayerInputUIGround();

/*
 * Task (rendering on top):
 * 0: Game (singleton)
 * 0: InputState (singleton)
 */
void drawPlayerInputUI();

/**********************************
 * UI systems
 **********************************/

/**********************************
 * Utils
 **********************************/

Rectangle calculateEntityBounds(Position pos, Size size);
bool getEntityBounds(ecs_entity_t entity, Position *outPos, Size *outSize, Rectangle *outBounds);

/**********************************
 * MISC
 **********************************/

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

void setupSystems();

#endif //PIXELDEFENSE_SYSTEMS_H
