#pragma once
#include <iostream>
#include <SFML/Graphics.hpp>
#include <deque>
#include <random>
#include <string>
#include "Textbox.h"

enum class Smjer { Nema, Gore, Dolje, Lijevo, Desno };
// kasnije u kodu pisemo npr. Smjer::Dolje, Smjer::Nema, ...

class Zmija {
public:
	Smjer DohvatiSmjer() {
		return smjer;
	}
	int DohvatiZivote() {
		return brZivota;
	}
	int DohvatiBodove() {
		return bodovi;
	}
	bool JelIzgubio() {
		return izgubio;
	}
	float DohvatiBrzinu() {
		return brzina;
	}
	sf::Vector2i KoordinateGlave() {
		return koordinate.front();
	}
	void Izgubio() {
		textbox->Dodaj("Igra gotova. Ukupni bodovi: "
			+ std::to_string(DohvatiBodove()));
		izgubio = true;
	}
	void PovecajBodove() {
		bodovi += 10;
	}
	void PostaviSmjer(Smjer s) {
		smjer = s;
	}
	Zmija(int, Textbox*);
	~Zmija();
	void Reset();
	void Korak();
	void Pomakni();
	void ProvjeraSudara();
	void Odrezi(size_t);
	void Produlji() {
		koordinate.push_back(koordUklonjenog);
	}
	void Renderiraj(sf::RenderWindow&);
	Smjer dohvatiFizickiSmjer();
private:
	Textbox* textbox;
	int brZivota;
	int bodovi;
	bool izgubio;
	float brzina;
	int velBloka;
	sf::RectangleShape blok;
	Smjer smjer;
	std::deque<sf::Vector2i> koordinate;
	sf::Vector2i koordUklonjenog;
};

void Zmija::Renderiraj(sf::RenderWindow& p) {
	auto velicina = koordinate.size();
	for (size_t i = 0; i < velicina; ++i) {
		blok.setFillColor((i == 0) ?
			sf::Color::Yellow : sf::Color::Green);
		blok.setPosition(koordinate[i].x * velBloka,
			koordinate[i].y * velBloka);
		p.draw(blok);
	}
}

void Zmija::Odrezi(size_t i) {
	auto velicina = koordinate.size();
	for (auto j = i; j < velicina; ++j)
		koordinate.pop_back();
	--brZivota;
	textbox->Dodaj("Izgubio zivot! Preostalo zivota: "
	 + std::to_string(DohvatiZivote()));
	if (brZivota == 0)
		Izgubio();
}

void Zmija::ProvjeraSudara() {
	auto velicina = koordinate.size();
	sf::Vector2i glava = koordinate[0];
	if (velicina > 4) {
		for (size_t i = 1; i < velicina; ++i) {
			if (glava == koordinate[i]) {
				Odrezi(i);
				return;
			}
		}
	}
}

void Zmija::Pomakni() {
	sf::Vector2i novi = KoordinateGlave();
	koordUklonjenog = koordinate.back();
	koordinate.pop_back();
	switch (smjer) {
		case Smjer::Gore:
			--novi.y;
			break;
		case Smjer::Dolje:
			++novi.y;
			break;
		case Smjer::Lijevo:
			--novi.x;
			break;
		case Smjer::Desno:
			++novi.x;
	}
	koordinate.push_front(novi);
}

void Zmija::Korak() {
	if (brzina <= 20)
		brzina += 0.01f;
	if (smjer != Smjer::Nema) {
		Pomakni();
		ProvjeraSudara();
	}
}

void Zmija::Reset() {
	koordinate.clear();
	koordinate.push_back(sf::Vector2i(10, 10));
	brZivota = 3;
	bodovi = 0;
	izgubio = false;
	brzina = 10;
	PostaviSmjer(Smjer::Nema);
}

Zmija::Zmija(int v, Textbox* t) : velBloka(v),
	textbox(t) {
	blok.setSize(sf::Vector2f(v - 1, v - 1));
	Reset();
}

Zmija::~Zmija() {

}


class Svijet {
public:
	int dohvatiVBloka() {
		return velicinaBloka;
	}
	Svijet(int,sf::Vector2u, Textbox*);
	~Svijet() {}
	void PostaviJabuku();
	void Update(Zmija&);
	void Renderiraj(sf::RenderWindow&);
private:
	Textbox* ptextbox;
	sf::Vector2u velicinaProzora;
	int velicinaBloka;
	sf::RectangleShape rub;
	sf::CircleShape jabuka;
	sf::Vector2i jabukaKoord;
};

Smjer Zmija::dohvatiFizickiSmjer() {
	if (koordinate.size() == 1)
		return Smjer::Nema;
	auto razlika = koordinate[0] - koordinate[1];
	if (razlika == sf::Vector2i(0, 1))
		return Smjer::Dolje;
	if (razlika == sf::Vector2i(1, 0))
		return Smjer::Desno;
	if (razlika == sf::Vector2i(0, -1))
		return Smjer::Gore;
	return Smjer::Lijevo;
}

void Svijet::Renderiraj(sf::RenderWindow& p) {
	p.draw(rub);
	p.draw(jabuka);
}

void Svijet::Update(Zmija& igrac) {
	if (jabukaKoord == igrac.KoordinateGlave()) {
		igrac.Produlji();
		igrac.PovecajBodove();
		ptextbox->Dodaj("Jabuka! Trenutni bodovi: "
		 + std::to_string(igrac.DohvatiBodove()));
		PostaviJabuku();
	}
	sf::Vector2i brPolja(velicinaProzora.x / velicinaBloka,
		velicinaProzora.y / velicinaBloka);
	if (igrac.KoordinateGlave().x <= 0
		|| igrac.KoordinateGlave().x >= brPolja.x - 1
		|| igrac.KoordinateGlave().y <= 0
		|| igrac.KoordinateGlave().y >= brPolja.y - 1) {
		igrac.Izgubio();
	}
}

void Svijet::PostaviJabuku() {
	static std::uniform_int_distribution<unsigned> 
		u(0,10000);
	static std::default_random_engine e(time(0));
	int maxX = (velicinaProzora.x / velicinaBloka) - 2;
	int maxY = (velicinaProzora.y / velicinaBloka) - 2;
	jabukaKoord = sf::Vector2i(u(e) % maxX + 1,
		u(e) % maxY + 1);
	jabuka.setPosition(jabukaKoord.x * velicinaBloka,
		jabukaKoord.y * velicinaBloka);
}

Svijet::Svijet(int vBloka, sf::Vector2u vProzora,
	Textbox* t) 
	: velicinaBloka(vBloka), 
	  velicinaProzora(vProzora),
		ptextbox(t)	{
	PostaviJabuku();
	jabuka.setFillColor(sf::Color::Red);
	jabuka.setRadius(vBloka / 2.f);
	rub.setFillColor(sf::Color::Transparent);
	rub.setSize(sf::Vector2f(vProzora.x, vProzora.y));
	rub.setOutlineThickness(-vBloka);
	rub.setOutlineColor(sf::Color::Blue);
}