#pragma once
#include "Collision.h"
#include "Texture.h"
#include "WorldGridManager.h"
#include "../TextureManager.h"

class Camera;

enum class GroundTileTypes
{
	Air,
	Dirt,
	Grass,
	Stone,
	Lava,

	//Special
	Hard,

	//Ores
	Bronze,
	Gold,
	Iron,
};

static std::map<GroundTileTypes, std::string> GroundTileTypeStrings {
	{ GroundTileTypes::Air, "Air" },
	{ GroundTileTypes::Dirt, "Dirt" },
	{ GroundTileTypes::Grass, "Grass" },
	{ GroundTileTypes::Stone, "Stone" },
	{ GroundTileTypes::Lava, "Lava" },
	{ GroundTileTypes::Hard, "Hard" },
	{ GroundTileTypes::Bronze, "Bronze" },
	{ GroundTileTypes::Gold, "Gold" },
	{ GroundTileTypes::Iron, "Iron" },
};


GroundTileType * getRandomGroundTile();

class GroundTileType
{
public:
	GroundTileType(const std::string&& filePath, GroundTileTypes type): m_filePath(filePath), m_type(type) {
	}
	virtual ~GroundTileType() = default;
	bool operator==(const GroundTileType& rhs) const {
		return m_type == rhs.m_type;
	}
	bool operator!=(const GroundTileType& rhs) const {
		return m_type != rhs.m_type;
	}

	virtual bool operator==(const GroundTileType* rhs) const {
		return rhs->m_type == m_type;
	}
	virtual bool operator!=(const GroundTileType* rhs) const {
		return rhs->m_type != m_type;
	}

	virtual std::string getPath() const {
		return m_filePath;
	}

	virtual GroundTileTypes getType() const {
		return m_type;
	}

protected:
	std::string m_filePath;

private:
	GroundTileTypes m_type;
};

class RandomGroundTile : public GroundTileType
{
public:
	RandomGroundTile(const std::string& filePath, GroundTileTypes type, int maxRandom): GroundTileType(std::move(filePath), type), m_maxRandom(maxRandom) {
	}

	~RandomGroundTile() override = default;

	bool operator==(const GroundTileType* rhs) const override {
		return rhs->getType() == this->getType();
	}

	bool operator!=(const GroundTileType* rhs) const override {
		return rhs->getType() != this->getType();
	}

	std::string getPath() const override {
		int variant = utils::randRange(1, m_maxRandom);
		std::string toReplace { "[0]" };
		std::string replacement = std::to_string(utils::randRange(1, m_maxRandom));

		size_t found = m_filePath.find(toReplace);
		std::string newFilePath { m_filePath };

		if (found != std::string::npos) {
			newFilePath.replace(found, 3, replacement);
		}

		return newFilePath;
	}

private:
	int m_maxRandom;
};

class Tiles
{
public:
	
};

// static std::map<GroundTileType *, float> GroundTileWeights {
// 	{ Tiles::AIR, 0.2f },
// 	{ Tiles::DIRT, 0.5f },
// 	{ Tiles::Special::GRASS, 0.0f },
// 	{ Tiles::Hazards::STONE, 0.025f },
// 	{ Tiles::Hazards::LAVA, 0.01f },
// 	{ Tiles::Special::HARD_LEFT, 0.0f },
// 	{ Tiles::Special::HARD_MIDDLE, 0.0f },
// 	{ Tiles::Special::HARD_RIGHT, 0.0f },
// 	{ Tiles::Ores::BRONZE, 0.05f },
// 	{ Tiles::Ores::GOLD, 0.02f },
// 	{ Tiles::Ores::IRON, 0.1f },
// };

static std::map<GroundTileType*, float> GroundTileWeights;

void InitializeGroundTiles();

class WorldTile
{
public:
	WorldTile() = default;
	WorldTile(const Vector2f& position, GroundTileType* groundTileType, TextureManager* pTextureManager, WorldGridManager* pGridManager);
	~WorldTile();

	void Draw();
	void Update(const Camera* camera); //TODO: no use

	Vector2f GetPosition() const {
		return m_Position;
	}
	void SetPosition(const Vector2f& position) {
		m_Position = position;
	}

	Vector2f GetSize() const {
		return Vector2f { 50, 50 };
	}

	GroundTileType * GetTileType() const {
		return m_GroundTileType;
	}
	void SetTileType(GroundTileType* type) {
		m_GroundTileType = type;
		m_pTexture = TextureManager::GetInstance()->GetTexture(type->getPath()); //Chage the texture when setting a new type
	}

	Collision::TileCollisionRect GetCollisionRect();

	bool m_Hightlight { false };

private:
	void DrawSide(const TileDirection& direction);

	Vector2f m_Position;
	GroundTileType* m_GroundTileType;

	Texture* m_pTexture;

	Collision::CollisionRect m_CollisionRect;

	WorldGridManager* m_pGridManager;

	surroundingTiles m_SurroundingTiles;

	std::vector<Texture*> m_SideTextures { 8, nullptr };

	Texture* m_pAllTexture;
};
