#pragma once
#include <array>
#include <cmath>
#include <map>

#include "structs.h"
#include "utils.h"

class Player;
class WorldTile;

namespace Collision
{

	enum CollisionDirection {
		Top,
		Bottom,
		Left,
		Right
	};

	struct CollisionRect
	{
		CollisionRect() = default;
		CollisionRect(const Point2f& pos, const Point2f& size) : pos(pos), size(size) {}
		CollisionRect(const Point2f& pos, const Point2f& size, const Point2f& vel) : pos(pos), size(size), vel(vel) {}
		Point2f pos;
		Point2f size;
		Point2f vel;

		std::map<CollisionDirection, CollisionRect*> ContactMap{};
	};

	struct TileCollisionRect : virtual public CollisionRect
	{
		TileCollisionRect(const Point2f& pos, const Point2f& size, WorldTile* tile);
		WorldTile* tile;

		bool Contains(Point2f point2_f) {
			return utils::IsPointInRect(point2_f, Rectf{ pos.x, pos.y, size.x, size.y });
		}

		Collision::CollisionRect getCollisionRect() {
			return Collision::CollisionRect{ pos, size, vel };
		}
	};

	bool PointVsRect(const Point2f p, const CollisionRect& r);

	bool RectVsRect(const CollisionRect& r1, const CollisionRect r2);

	bool RayVsRect(const Point2f& rayOrigin, const Point2f& rayDirection, const Collision::CollisionRect target, Point2f& contactPoint, Point2f& contactNormal, float& t_HitNear);

	bool DynamicRectVsRect(const CollisionRect& dynamicRectangle, float ElapsedTime, const CollisionRect& staticRectangle, Point2f& contactPoint, Point2f& contactNormal, float& contactTime);

	bool ResolveDynamicRectVsRect(CollisionRect& dynamicRectangle, float ElapsedTime, CollisionRect* staticRectangle);

	bool ResolvePlayerVsRect(Player& player, float ElapsedTime, Collision::CollisionRect* staticRectangle);
}
