#include "pch.h"
#include "WorldTile.h"

#include <iostream>

#include "Camera.h"
#include "colors.h"
#include "GroundTileTypeManager.h"
#include "../TextureManager.h"
#include "utils.h"
#include "WorldGridManager.h"




GroundTileType * getRandomGroundTile() {
	// Generate a random weight between 0 and the sum of weights
	float sumWeights = 0.0f;
	for (const auto& pair : GroundTileWeights) {
		sumWeights += pair.second;
	}

	float randomWeight = static_cast<float>(rand()) / RAND_MAX * sumWeights;

	// Find the corresponding ground tile type
	float cumulativeWeight = 0.0f;
	for (const auto& pair : GroundTileWeights) {
		cumulativeWeight += pair.second;
		if (randomWeight <= cumulativeWeight) {
			return pair.first;
		}
	}

	// This should never be reached if weights sum to 1.0
	return GroundTileTypeManager::GetInstance()->AIR; // Default value
}
void InitializeGroundTiles() {
	GroundTileTypeManager::GetInstance()->AIR = new GroundTileType("", GroundTileTypes::Air, 0);
	GroundTileTypeManager::GetInstance()->DIRT = new RandomGroundTile("tiles/dirt/dirt[0].png", GroundTileTypes::Dirt, 5, 250);

	GroundTileTypeManager::GetInstance()->STONE = new RandomGroundTile("tiles/ores/Ore_Stone_[0].png", GroundTileTypes::Stone, 3, 0);
	GroundTileTypeManager::GetInstance()->LAVA = new RandomGroundTile("tiles/ores/Ore_Lava_[0].png", GroundTileTypes::Lava, 3, 0);

	GroundTileTypeManager::GetInstance()->IRON = new GroundTileType("tiles/ores/Ore_Ironium.png", GroundTileTypes::Iron, 1500);
	GroundTileTypeManager::GetInstance()->BRONZE = new GroundTileType("tiles/ores/Ore_Bronzium.png", GroundTileTypes::Bronze, 3000);
	GroundTileTypeManager::GetInstance()->GOLD = new GroundTileType("tiles/ores/Ore_Goldium.png", GroundTileTypes::Gold, 12500);

	GroundTileTypeManager::GetInstance()->GRASS = new RandomGroundTile("tiles/dirt/special/grass[0].png", GroundTileTypes::Grass, 2, 250);
	GroundTileTypeManager::GetInstance()->HARD_LEFT = new GroundTileType("tiles/dirt/special/hardLeft.png", GroundTileTypes::Hard, 0);
	GroundTileTypeManager::GetInstance()->HARD_RIGHT = new GroundTileType("tiles/dirt/special/hardRight.png", GroundTileTypes::Hard, 0);
	GroundTileTypeManager::GetInstance()->HARD_MIDDLE = new GroundTileType("tiles/dirt/special/hardMiddle.png", GroundTileTypes::Hard, 0);

	GroundTileWeights = {
		{ GroundTileTypeManager::GetInstance()->AIR, 0.2f },
		{ GroundTileTypeManager::GetInstance()->DIRT, 0.5f },
		{ GroundTileTypeManager::GetInstance()->GRASS, 0.0f },
		{ GroundTileTypeManager::GetInstance()->STONE, 0.025f },
		{ GroundTileTypeManager::GetInstance()->LAVA, 0.01f },
		{ GroundTileTypeManager::GetInstance()->HARD_LEFT, 0.0f },
		{ GroundTileTypeManager::GetInstance()->HARD_MIDDLE, 0.0f },
		{ GroundTileTypeManager::GetInstance()->HARD_RIGHT, 0.0f },
		{ GroundTileTypeManager::GetInstance()->BRONZE, 0.05f },
		{ GroundTileTypeManager::GetInstance()->GOLD, 0.02f },
		{ GroundTileTypeManager::GetInstance()->IRON, 0.1f },
	};
}

WorldTile::WorldTile(const Vector2f& position, GroundTileType* groundTileType, TextureManager* pTextureManager, WorldGridManager* pGridManager) : m_Position { position },
	m_GroundTileType { groundTileType }, m_pGridManager { pGridManager } {
	// const std::string dirtPath =  + "tiles/dirt/dirt" + std::to_string(utils::randRange(1, 5))  + ".png";
	// m_pTexture = new Texture(dirtPath);
	m_pTexture = pTextureManager->GetTexture(groundTileType->GetPath());

	m_SideTextures[TileDirection::TopLeft] = pTextureManager->GetTexture("tiles/dirt/sidepieces/topLeft.png");
	m_SideTextures[TileDirection::TopRight] = pTextureManager->GetTexture("tiles/dirt/sidepieces/topRight.png");
	m_SideTextures[TileDirection::BottomLeft] = pTextureManager->GetTexture("tiles/dirt/sidepieces/bottomLeft.png");
	m_SideTextures[TileDirection::BottomRight] = pTextureManager->GetTexture("tiles/dirt/sidepieces/bottomRight.png");

	m_SideTextures[TileDirection::TopMiddle] = pTextureManager->GetTexture("tiles/dirt/sidepieces/middleTop.png");
	m_SideTextures[TileDirection::BottomMiddle] = pTextureManager->GetTexture("tiles/dirt/sidepieces/middleBottom.png");
	m_SideTextures[TileDirection::MiddleLeft] = pTextureManager->GetTexture("tiles/dirt/sidepieces/middleLeft.png");
	m_SideTextures[TileDirection::MiddleRight] = pTextureManager->GetTexture("tiles/dirt/sidepieces/middleRight.png");


	m_pAllTexture = pTextureManager->GetTexture("tiles/dirt/sidepieces/all.png");
}
WorldTile::~WorldTile() {
}
void WorldTile::Draw() {

	utils::SetColor(Colors::WHITE);

	switch (m_GroundTileType->GetType()) {
	case GroundTileTypes::Air: {
		//check if it's all around dirt
		// bool allDirt = true;
		// TileDirection allDirtDirections[] { TileDirection::BottomMiddle, TileDirection::MiddleLeft, TileDirection::MiddleRight, TileDirection::TopMiddle };
		// for (int i = 0; i < 3; i++) {
		// 	const WorldTile* tile = m_SurroundingTiles.GetTile(allDirtDirections[i]);
		// 	if (tile != nullptr) { //Tile exists
		// 		const GroundTileTypes type = tile->GetTileType()->getType();
		// 		if (type != GroundTileTypeManager::GetInstance()->DIRT->getType()) {
		// 			allDirt = false;
		// 			break;
		// 		}
		// 	}
		// }
		// if (allDirt) {
		// 	m_pAllTexture->Draw(m_Position);
		// 	return;
		// }
		// else {
		this->DrawSide(TileDirection::TopLeft);
		this->DrawSide(TileDirection::TopRight);
		this->DrawSide(TileDirection::BottomLeft);
		this->DrawSide(TileDirection::BottomRight);

		this->DrawSide(TileDirection::TopMiddle);
		this->DrawSide(TileDirection::BottomMiddle);
		this->DrawSide(TileDirection::MiddleLeft);
		this->DrawSide(TileDirection::MiddleRight);
		// }
		break;
	}
	case GroundTileTypes::Dirt:
	case GroundTileTypes::Hard:
	case GroundTileTypes::Stone:
	case GroundTileTypes::Iron:
		m_pTexture->Draw(m_Position);
		break;
	default:
		break;
	}


	if (*m_GroundTileType != GroundTileTypeManager::GetInstance()->AIR) {
		m_pTexture->Draw(m_Position);
		if (m_Hightlight) {
			utils::SetColor(Colors::GREEN);
			utils::FillRect(m_Position, 50, 50);
		}
	}


}

void WorldTile::Update(const Camera* camera) {
	m_pGridManager->GetIndexFromPosition(m_Position);
	m_SurroundingTiles = m_pGridManager->GetSurroundingTiles(this);
	const Vector2f mouse_pos = camera->TransformMouse(Vector2f { utils::GetMousePos().x, 500 - utils::GetMousePos().y });
	m_Hightlight = utils::IsPointInRect(mouse_pos, Rectf { GetCollisionRect().pos, GetCollisionRect().size });
}
Collision::TileCollisionRect WorldTile::GetCollisionRect() {
	return Collision::TileCollisionRect { m_Position, GetSize(), ( this ) };
}

void WorldTile::DrawSide(const TileDirection& direction) {
	const WorldTile* tile = m_SurroundingTiles.GetTile(direction);
	if (tile != nullptr) {
		const GroundTileTypes type = tile->GetTileType()->GetType();
		if (direction == TileDirection::BottomMiddle || direction == TileDirection::BottomLeft || direction == TileDirection::BottomRight) {
			if (type == GroundTileTypeManager::GetInstance()->GRASS->GetType() || type == GroundTileTypeManager::GetInstance()->HARD_LEFT->GetType() || type ==
				GroundTileTypeManager::GetInstance()->HARD_MIDDLE->GetType() || type == GroundTileTypeManager::GetInstance()->HARD_RIGHT->GetType()) {
				//Fix for edges being renderd on grass / hard tiles
				//TODO: Possible fix if i have time
				return;
			}
		}

		if (type != GroundTileTypeManager::GetInstance()->AIR->GetType()) {
			m_SideTextures[direction]->Draw(m_Position);
		}
	}
}
