#ifndef _HPP_KUNGFLOW_UTILS
#define _HPP_KUNGFLOW_UTILS

#include "gaia/gaia.hpp"
using namespace gaia;

#include <fmod.h>

class Stadium;

void FMOD_CHECK(FMOD_RESULT result);


// physics stuff

Vector2 CalculatePhysicsMovement(const Vector2 &currentMovement, const Vector2 &desiredMovement, float maxChangeMPS, unsigned int elapsedTime_ms);
void ApplyGravity(float &zMovement, float gravity = 9.81f, unsigned int timeStep_ms = 10);
bool ApplyFloor(const Vector2 &position, float &zPosition, float &zMovement, const Stadium *stadium, float bounceFactor = 0.0f, bool *outOfBounds_ret = nullptr);
void ApplyFriction(Vector2 &movement, float crossSectionalArea = 1.0f, unsigned int timeStep_ms = 10);

struct Position3D {
  Vector2 position;
  float zPosition;
};
void CalculateTrajectory(const Vector2 &startPosition, float startZPosition, const Vector2 &targetPosition, float targetZPosition, float arcFactor, unsigned int iterations, std::vector<Position3D> &trajectory);

Vector2 GetQuantizedDirection(const Vector2 &inputDirection, float bias = 1.0f);
//bool CheckRectangleCollision(const Vector2 &position1, const Vector2 &scale1, const Vector2 &position2, const Vector2 &scale2);
bool CheckCircleCollision(const Vector2 &position1, float radius1, const Vector2 &position2, float radius2);
radian GetCappedAngle(radian oldAngle, radian newAngle, unsigned int time_ms, radian maxRadiansPerSecond);


// AI stuff

// forcefields consist of forcespots, representing a repelling or attracting force from a position, including linearity/etc parameters
enum e_DecayType {
  e_DecayType_Constant,
  e_DecayType_Variable
};

enum e_MagnetType {
  e_MagnetType_Attract,
  e_MagnetType_Repel
};

struct ForceSpot {
  ForceSpot() {
    exp = 1.0f;
  }
  Vector2 origin;
  e_MagnetType magnetType;
  e_DecayType decayType;
  float exp;
  float power;
  float scale; // scaled #meters until effect is almost decimated
};

Vector2 GetForceFieldMovement(const std::vector<ForceSpot> &forceField, const Vector2 &currentPos);

#endif
