#include <iostream>
#include <SFML/Graphics.hpp>
#include "BubbleGrid.h"
#include "Player.h"
#include "NPC.h"

using namespace std;

sf::Vector2f RESOLUTION(576 + 192, 768);
sf::RenderWindow GAMEWINDOW(sf::VideoMode(RESOLUTION.x, RESOLUTION.y), "Bubble Pop");

int main() {
	// Seed randomise function with current time.
	srand(time(NULL));

	bool gameOver = false;

	BubbleGrid* bubbleGrid = new BubbleGrid();
	Player* player = new Player(0.0f, 11 * 64.0f);
	NPC* npc = new NPC(576 + 32, 128 + 32);

	sf::Clock deltaClock;
	sf::Clock bubbleClock;

	sf::Font font;
	font.loadFromFile("C:/Windows/Fonts/comic.ttf");

	sf::Text scoreText;
	scoreText.setFont(font);
	scoreText.setPosition(576 + 8, 8);
	scoreText.setCharacterSize(24);
	scoreText.setFillColor(sf::Color::Yellow);
	scoreText.setOutlineColor(sf::Color::Black);
	scoreText.setOutlineThickness(3);
	scoreText.setString("Score: 0");

	sf::Text bubbleCount;
	bubbleCount.setFont(font);
	bubbleCount.setPosition(576 + 8 + 32, 64 + 32);
	bubbleCount.setCharacterSize(24);
	bubbleCount.setFillColor(sf::Color::Yellow);
	bubbleCount.setOutlineColor(sf::Color::Black);
	bubbleCount.setOutlineThickness(3);
	bubbleCount.setString("0");

	Bubble* UIHoldingBubble = new Bubble(576 + 8, 64);

	sf::Texture BGTEXTURE;
	sf::Sprite BGSPRITE;

	if (!BGTEXTURE.loadFromFile("Assets/Background.png")) {
		cout << "Error while loading background image" << endl;
	}

	BGSPRITE.setTexture(BGTEXTURE);

	sf::Texture GAMEOVERTEXTURE;
	sf::Sprite GAMEOVERSPRITE;

	GAMEOVERSPRITE.setPosition(0, -768);

	if (!GAMEOVERTEXTURE.loadFromFile("Assets/GameOver.png")) {
		cout << "Error while loading background image" << endl;
	}

	GAMEOVERSPRITE.setTexture(GAMEOVERTEXTURE);
	
	while (GAMEWINDOW.isOpen()) {
		sf::Time deltaTime = deltaClock.restart(); // deltaTime.asSeconds() - deltaClock.getElapsedTime().asSeconds();

		float elapsedSeconds = bubbleClock.getElapsedTime().asSeconds();

		float difficultyOffset = player->score / 350;

		if (elapsedSeconds > (5.0f - difficultyOffset)) {
			bubbleClock.restart();
			bubbleGrid->addRow();
			npc->setMood(NPC::NEUTRAL);
		}
		else if (elapsedSeconds > .5 && bubbleGrid->remainingBubbles() < GRIDCOLS * 3) {
			bubbleClock.restart();
			bubbleGrid->addRow();
		}

		if (npc->currentMood >= 2 && bubbleGrid->rowContainsBubbles(ceil(GRIDROWS * 0.7))) {
			npc->setMood(NPC::WORRIED);
		}
		else if (npc->currentMood >= 2 && bubbleGrid->rowContainsBubbles(ceil(GRIDROWS * 0.5))) {
			npc->setMood(NPC::UNSURE);
		}

		sf::Event event;
		while (GAMEWINDOW.pollEvent(event)) {
			if (event.type == sf::Event::Closed) {
				GAMEWINDOW.close();
			}

			if (event.type == sf::Event::KeyPressed) {
				PlayerEvent* playerEvent = player->handleMovement(event, deltaTime.asSeconds() - deltaClock.getElapsedTime().asSeconds());

				sf::Vector2i playerGridPos = player->getRelativePosition();

				if (playerEvent->type == PlayerEventType::THROW) {
					// Fire currently held bubbles
					cout << "player wants to fire" << endl;

					BubbleDelivery* delivery = new BubbleDelivery(player->holdCount, player->holdingBubble);
					BubbleGrid::AddToColResult* addToColResult = bubbleGrid->addToCol(playerGridPos.x, delivery);

					if (addToColResult->success) {
						player->holdCount = 0;
						player->holdingBubble = (BubbleType) - 1;
						player->score += addToColResult->scoreGain;

						if (addToColResult->scoreGain >= 10) npc->setMood(NPC::ECSTATIC);
						else if (addToColResult->scoreGain > 0) npc->setMood(NPC::HAPPY);

						scoreText.setString("Score: " + to_string(player->score));
					}
				}
				else if (playerEvent->type == PlayerEventType::GRAB) {
					// Check if can hold incoming bubbles, and if so pick em up
					cout << "player wants to grab" << endl;

					int limiter = -1;
					if (player->holdCount > 0) limiter = player->holdingBubble;

					BubbleDelivery* incoming = bubbleGrid->grabFromCol(playerGridPos.x, (BubbleType)limiter);

					if (incoming->count > 0) {
						player->holdingBubble = incoming->type;
						player->holdCount += incoming->count;
					}

					
				}
			}
		}

		GAMEWINDOW.clear();

		GAMEWINDOW.draw(BGSPRITE);
		GAMEWINDOW.draw(npc->getSprite());

		if (bubbleGrid->gameOver) {
			sf::Vector2f curPos = GAMEOVERSPRITE.getPosition();
			float y = curPos.y;
			if (y < 0) y = curPos.y + 0.25;
			GAMEOVERSPRITE.setPosition(0, y);

			GAMEWINDOW.draw(GAMEOVERSPRITE);
		}
		else {
			for (auto& row : bubbleGrid->getGrid()) {
				for (auto& col : row) {
					if (!col) continue;
					GAMEWINDOW.draw(col->getSprite());
				}
			}

			GAMEWINDOW.draw(player->getSprite());

			if (player->holdCount > 0) {
				UIHoldingBubble->setBubbleType(player->holdingBubble);

				bubbleCount.setString(to_string(player->holdCount));

				GAMEWINDOW.draw(UIHoldingBubble->getSprite());
				GAMEWINDOW.draw(bubbleCount);
			}
		}

		
		GAMEWINDOW.draw(scoreText);
		GAMEWINDOW.display();
	}

	return 0;
}