#ifndef FIGHT_PLAYER_H
#define FIGHT_PLAYER_H

#include "state_machine.h"
#include "mirror.h"
#include "behaviour_entity.h"
#include "animation_sprite.h"
#include "vmath.h"
#include "transform.h"
#include "player_input.h"
#include "rigidbody.h"
#include "collider.h"
#include "typeclass_helpers.h"

extern const Vector PLAYER_SPEED;

typedef struct PlayerInputFrame {
    float time;
    Vector direction;
    int light;
    int heavy;
    int jump;
    float facing;
} PlayerInputFrame;

typedef struct Player {
    Transform transform;
    float height;

    RigidBody* rigidbody;
    Collider* physicsCollider;
    Collider* hitbox;

    float verticalVelocity;

    PlayerInput* playerInput;

    Vector moveInput;
    int attackInput;
    int jumpInput;
    size_t animationTriggers;

    int facing;

    Sprite* sprite;

    AnimationSprite* idle;
    AnimationSprite* walk;
    AnimationSprite* jump;
    AnimationSprite* jab_a;
    AnimationSprite* jab_b;
    AnimationSprite* kick_a;
    AnimationSprite* air_heavy;
    AnimationSprite* slide;

    StateMachine* animationStateMachine;

    AnimationSprite* currentAnimation;

    float pushInputTimer;
    List inputLog;
    PlayerInputFrame nextInputFrame;
} Player;

Player* MakePlayer();
Player* SpawnPlayer(Vector location);
void DestroyPlayer(Player* self);

void PlayerStart(Player* self);
void PlayerUpdate(Player* self, float deltaTime);
void PlayerDraw(Player* self);

void PlayerHorizontalInput(Player* self, InputEvent value);
void PlayerVerticalInput(Player* self, InputEvent value);
void PlayerJumpInput(Player* self, InputEvent value);
void PlayerLightAttackInput(Player* self, InputEvent value);
void PlayerHeavyAttackInput(Player* self, InputEvent value);

void PlayerOnCollision(Player* self, Collision collision);
void PlayerOnOverlap(Player* self, Collider* other);

Transform* PlayerGetTransform(Player* self);
RigidBody* PlayerGetRigidBody(Player* self);

PlayerInputFrame* PlayerInputHistory(Player* self);

int PlayerInputIsQuarterCircleForward(Player* self);

static long PlayerGetDepth(Player* self) { return (int)(-10-self->transform.position.y * 1000); }

DECL_REFLECT(Player);
decl_typeclass_impl(BehaviourEntity, Player)
decl_typeclass_impl(Drop, Player)
decl_typeclass_impl(Transformable, Player)
decl_typeclass_impl(PhysicsEntity, Player)

#endif // !FIGHT_PLAYER_H