#include "Core.hpp"
#include "Echo.hpp"
#include "Animation.hpp"

Core::Core(Global* lg):
	_player(&_settings),
	_lives(lg->lives),
	g(lg)
{
	_settings.view = &_view;
	_settings.window = &g->window;
	_settings.evm = &_evm;
	_settings.bg = &_background;
	_settings.fog = &_fog;
	_settings.size = Vector2u(256, 224);
	_settings.running = true;
	_settings.paused = false;
	_settings.p = &_player;
	_settings._s = g->score;
	if(_settings._s == 0 && _lives == 2)
	_settings.state = 0;
	else
	_settings.state = 2;

	_view = g->window.getDefaultView();

	loadTexture(_hud_tx, "data/hud.png");
	_hud_score.setTexture(_hud_tx);
	_hud_score.setTextureRect(IntRect(0, 0, 72, 7));
	_hud_score.setPosition(8, 0);

	_hud_highscore.setTexture(_hud_tx);
	_hud_highscore.setTextureRect(IntRect(0, 7, 72, 7));
	_hud_highscore.setPosition(88, 0);

	_hud_time.setTexture(_hud_tx);
	_hud_time.setTextureRect(IntRect(0, 14, 72, 7));
	_hud_time.setPosition(15, 17);

	_hud_energy.setTexture(_hud_tx);
	_hud_energy.setTextureRect(IntRect(0, 21, 72, 7));
	_hud_energy.setPosition(80, 17);

	loadTexture(_font, "data/numbers.png");
	_score_text.setTexture(&_font);
	_score_text.setPosition(55, 8);
	_highscore_text.setTexture(&_font);
	_highscore_text.setPosition(138, 8);

	_time_text.setTexture(&_font);
	_time_text.semicolon();
	_time_text.setPosition(18, 27);
	_energy_text.setTexture(&_font);
	_energy_text.percent();
	_energy_text.setPosition(100, 27);

	loadTexture(_head_tx, "data/glim-head.png");
	_head_tx.setRepeated(true);
	_head.setTexture(_head_tx);
	_head.setPosition(0, 224);
	_head.setOrigin(0, _head_tx.getSize().y);
	_head.setTextureRect(IntRect(0, 0, _head_tx.getSize().x * _lives, _head_tx.getSize().y));

	loadTexture(_frame_tx, "data/frame.png");
	_frame.setTexture(_frame_tx);
	_frame.setPosition(128, 224);
	_frame.setOrigin(_frame_tx.getSize().x / 2.f, _frame_tx.getSize().y + 4.f);

	if(g->reachedEast)
		_player.setPosition(16 * 86, 224);
	else
		_player.setPosition(16 * 9, 224);
	_player.addAnimation("data/snowfall-walk.png", "data/glim-walk.png", 500, "walk", true);
	_player.addAnimation("data/snowfall-idle.png", "data/glim-idle.png", 10000, "idle", true);
	_player.addAnimation("data/snowfall-longidle.png", "data/glim-longidle.png", 1000, "longidle", false);
	_player.addAnimation("data/snowfall-forward.png", "data/glim-forward.png", 1000, "forward", false);
	_player.addAnimation("data/snowfall-jump.png", "data/glim-jump.png", 200, "jump", false);
	_player.setAnimation("longidle", true);

	_view.setSize(256, 224);
	_view.setCenter(_player.getPosition().x, _player.getPosition().y - 80.f);

	loadTexture(_background_tx, "data/basic_background.png");
	_background.setTexture(_background_tx);
	_background.setOrigin((Vector2f)_background_tx.getSize() / 2.f);
	_background.setPosition(_player.getPosition().x, _player.getPosition().y - 80.f);

	loadTexture(_evm_tx, "data/evilmountain.png");
	_evm.setTexture(_evm_tx);
	_evm.setOrigin((Vector2f)_evm_tx.getSize() / 2.f);
	_evm.setPosition(_player.getPosition().x + 32.f, _player.getPosition().y - 128.f);

	loadTexture(_fog_tx, "data/basic_fog.png");
	_fog.setTexture(_fog_tx);
	_fog.setOrigin((Vector2f)_fog_tx.getSize() / 2.f);
	_fog.setColor(Color(255, 255, 255, 10));
	_fog.setPosition(_player.getPosition().x, _player.getPosition().y - 80.f);

	map.load("data/map1.tmx");

	for(unsigned i = 0; i < LAYERCOUNT; ++i) {
    	_layer[i].create(map, i);
	}

	/// Left invisible wall
	_settings.cb.emplace_back(-16, 0, 16, 16 * 32);
	_settings.cb.emplace_back(192 * 16, 0, 16, 16 * 32);

	/// Graves
	_settings.cb.emplace_back(6 * 16, 13 * 16, 16, 16);
	_settings.cb.emplace_back(19 * 16, 13 * 16, 16, 16);
	_settings.cb.emplace_back(38 * 16, 13 * 16, 16, 16);
	_settings.cb.emplace_back(53 * 16, 13 * 16, 16, 16);
	_settings.cb.emplace_back(28 * 16, 9 * 16, 16, 16);

	/// Ground
	_settings.cp.emplace_back(0, 224, 64 * 16 + 16, 8);
	_settings.cp.emplace_back(22 * 16, 10 * 16, 13 * 16 + 16, 8);
	_settings.cp.emplace_back(73 * 16, 224, 130 * 16 + 16, 8);

	jedi.emplace_back(2 * 16, 13 * 16, 48, 16);
	jedi.emplace_back(11 * 16, 13 * 16, 48, 16);
	jedi.emplace_back(48 * 16, 13 * 16, 48, 16);
	jedi.emplace_back(86 * 16, 13 * 16, 48, 16);
	jedi.emplace_back(101 * 16, 13 * 16, 48, 16);
	jedi.emplace_back(112 * 16, 13 * 16, 48, 16);
	jedi.emplace_back(124 * 16, 13 * 16, 48, 16);
	jedi.emplace_back(139 * 16, 13 * 16, 48, 16);
	jedi.emplace_back(171 * 16, 13 * 16, 48 * 3, 16);

	jedi.emplace_back(31 * 16, 9 * 16, 48, 16);

	_p1.create(&_settings, {23, 13}, {23, 9});
	_p2.create(&_settings, {64, 13}, {74, 13});
	_p3.create(&_settings, {75, 13}, {63, 13});

	debug.setFillColor(Color(255, 0, 0, 100));
	debug.setSize(Vector2f(4.f, 4.f));
	debug.setOrigin(2.f, 2.f);
	debug2.setFillColor(Color::Red);
	debug2.setSize(Vector2f(4.f, 4.f));
	debug2.setOrigin(2.f, 2.f);

	splashtx.loadFromFile("data/splash.png");
	splash.setTexture(splashtx);

	_settings._t = sf::seconds(120);
	_settings._s = g->score;
	_settings._h = g->high;
	_settings._e = 50;
	timegranted = false;

	boom.loadFromFile("data/shoot.wav");
	sht.setBuffer(boom);
	sht.setVolume(40.f);

	ggtex.loadFromFile("data/shot.png");

	_corrupted.emplace_back(&_settings);
	_corrupted.back().setPosition(170 * 16, 224);
	_corrupted.back().out = 0.f;
	_corrupted.back().in = 0.f;
	_corrupted.back().speed = 144.f;
	_corrupted.back().lifespan = 2000000000;
	_corrupted.back().hp = 6;
	_corrupted.back().ready = true;

	_trix.loadFromFile("data/trixie.png");
	_trixie.setPosition(_player.getPosition().x + 32.f, _player.getPosition().y);
	_trixie.setOrigin(0.f, 14.f);
	_trixie.setTexture(_trix);
}

Core::~Core()
{

}

void Core::run()
{
	Clock clock;
	float delta;
	float minimum = 1.f / 30.f;
	Echo(INFO, "Starting.");
	while(_settings.running) {
		think(delta);
		delta = clock.restart().asSeconds();
		while(delta > minimum) {
			delta -= minimum;
			if(!_settings.paused)
				loop(minimum);
		}
		if(!_settings.paused)
			loop(delta);
		render();
	}
}

void Core::think(float delta)
{
    Event event;
	_settings.jump = false;
    while(g->window.pollEvent(event)) {
        if(event.type == Event::Closed || (event.type == Event::KeyReleased && event.key.code == Keyboard::Escape)) {
            g->window.close();
			g->restart = false;
			_settings.running = false;
		}
		else if(event.type == Event::GainedFocus) {
			_settings.paused = false;
		}
		else if(event.type == Event::LostFocus) {
			_settings.paused = true;
		}
		else if(event.type == Event::KeyReleased && event.key.code == Keyboard::P) {
			_settings.paused = !_settings.paused;
		}
		else if(_settings.state == 2 && event.type == Event::KeyPressed && (event.key.code == Keyboard::Space || event.key.code == Keyboard::X)) {
			if(_settings._e >= 10.f && !_player.dead)
			{
				_settings.jump = true;
				_settings._e -= 10.f;
			}
		}
		else if(_settings.state == 2 && event.type == Event::KeyPressed && (event.key.code == Keyboard::LControl || event.key.code == Keyboard::Z)) {
			if(gg.size() < 3 && _settings._e >= 20.f) {
				_settings._e -= 20.f;
				sht.setPitch(int(80 + rand() % 40) / 100.f);
				sht.play();
				gg.emplace_back();
				gg.back().setTexture(ggtex);
				gg.back().setOrigin(4, 4 + 24);
				gg.back().setScale(_player.getScale());
				gg.back().setPosition(_player.getPosition().x, _player.getPosition().y);
			}
		}
		else if(_settings.state < 2 && event.type == Event::KeyReleased && (
			event.key.code == Keyboard::Return || event.key.code == Keyboard::Num1)) {
			_settings.state = 2;
			_s1c.restart();
		}
    }
}
#include <sstream>
void Core::loop(float delta)
{
	if(_settings.state == 2)
		_player.loop(delta);
	else
		_player.animate();
	if(_settings.state != 1) {
		_s1c.restart();
	}
	_settings.hz.clear();
	_settings.gz.clear();
	_p1.animate();
	_p2.animate();
	_p3.animate();

	_score_text.setNumber(_settings._s);
	_highscore_text.setNumber(_settings._h);
	std::stringstream ss;
	int asfioahsfuio;
	if(int(_settings._t.asSeconds() / 60) < 10)
		ss << 0;
	ss << int(_settings._t.asSeconds() / 60.f);
	if(int(_settings._t.asSeconds()) % 60 < 10)
		ss << 0;
	ss << int(_settings._t.asSeconds()) % 60;
	ss >> asfioahsfuio;
	_time_text.setNumber(asfioahsfuio);
	_energy_text.setNumber((int)_settings._e);

	if(_settings.state == 1) {

	}

	if(_settings.state == 2) {
		if(_settings._e < 100.f) {
			_settings._e += delta * 3.f;
			bool jedifound = false;
			for(unsigned i = 0; i < jedi.size(); ++i) {
				if(jedi[i].intersects(IntRect(_player.getGlobalBounds()))) {
					jedifound = true;
					break;
				}
			}
			if(jedifound) {
				if(jediClock.getElapsedTime().asSeconds() > 1.f) {
					_settings._e += delta * 17.f;
				}
			}
			else {
				jediClock.restart();
			}

		}
		_settings._t -= seconds(delta);
		if(!timegranted && _player.getPosition().x > 70.f * 16.f) {
			timegranted = true;
			_settings._t = sf::seconds(120);
			g->reachedEast = true;
		}

		for(unsigned i = 0; i < gg.size(); ++i) {
			gg[i].move(delta * 256.f * gg[i].getScale().x, 0.f);
			_settings.gz.push_back(IntRect(gg[i].getPosition().x - gg[i].getOrigin().x,
						 gg[i].getPosition().y - gg[i].getOrigin().x,
							 gg[i].getTextureRect().width,
							 gg[i].getTextureRect().height));
		}

		for(unsigned i = 0; i < _corrupted.size(); ++i) {
			_corrupted[i].loop(delta);
		}

		if(_corrupted[0].dead) {
			_settings._s += 900;
			_settings._s += _settings._t.asSeconds() * 10;
			_settings.state = 5;
			splashtx.loadFromFile("data/gaemover.png");
			splash.setTexture(splashtx);
		}

		for(unsigned i = 1; i < _corrupted.size(); ++i) {
			if(_corrupted[i].dead) {
				_corrupted.erase(_corrupted.begin() + i);
				i--;
			}
		}

		for(unsigned i = 0; i < _corrupted.size(); ++i) {
			if(!_corrupted[i].ready) {
				continue;
			}
				_settings.hz.push_back(IntRect(_corrupted[i].getPosition().x - _corrupted[i].getOrigin().x,
								 _corrupted[i].getPosition().y - _corrupted[i].getOrigin().x,
								 _corrupted[i].getTextureRect().width,
								 _corrupted[i].getTextureRect().height));
		}

		for(unsigned i = 0; i < keb.size(); ++i) {
			keb[i].loop(delta);
		}

		for(unsigned i = 0; i < keb.size(); ++i) {
			if(keb[i].dead) {
				keb.erase(keb.begin() + i);
			}
		}

		for(unsigned i = 0; i < keb.size(); ++i) {
				_settings.hz.push_back(IntRect(keb[i].getPosition().x + keb[i].keb.getGlobalBounds().left,
								 keb[i].getPosition().y + keb[i].spr.getGlobalBounds().top + 8.f,
								 keb[i].keb.getTextureRect().width,
								 keb[i].keb.getTextureRect().height + 16.f));
				_settings.hz.push_back(IntRect(keb[i].getPosition().x + keb[i].spr.getGlobalBounds().left,
				 				keb[i].getPosition().y + keb[i].spr.getGlobalBounds().top + 8.f,
				 				 keb[i].spr.getTextureRect().width,
				 				 keb[i].spr.getTextureRect().height));

		}
		//debug2.setPosition(_player.getPosition().x - 8.f * _player.getScale().x, _player.getPosition().y);

		if(_player.getPosition().x < 64 * 16) {
			if(_corr_clock.getElapsedTime().asSeconds() > 2.f && !_player.isJumping() && _corrupted.size() < 6) {
				_corr_clock.restart();
				_corrupted.emplace_back(&_settings);
				bool bad = true;
				while(bad) {
					bad = true;
					_corrupted.back().setPosition(_player.getPosition().x - 32.f + rand() % 64, _player.getPosition().y + 24.f + 16.f * (rand() % 2));
					for(unsigned i = 0; i < _settings.cp.size(); ++i) {
						if(((_corrupted.back().getPosition().x >= _settings.cp[i].left + 4.f
							&& _corrupted.back().getPosition().x <= _settings.cp[i].left - 4.f + _settings.cp[i].width)
						||
							(_corrupted.back().getPosition().x - 8.f >= _settings.cp[i].left + 4.f
							&& _corrupted.back().getPosition().x - 8.f <= _settings.cp[i].left - 4.f + _settings.cp[i].width))

						&& _corrupted.back().getPosition().y - 24.f >= _settings.cp[i].top
						&& _corrupted.back().getPosition().y - 24.f <= _settings.cp[i].top + _settings.cp[i].height) {
							bad = false;
							break;
						}
					}
					if(_corrupted.back().getPosition().x >= _player.getPosition().x - 16.f && _corrupted.back().getPosition().x <= _player.getPosition().x + 16.f)
						bad = true;
					for(unsigned i = 0; i < _settings.cb.size() && !bad; ++i) {
						if(_corrupted.back().getPosition().x + 12.f > _settings.cb[i].left
						&& _corrupted.back().getPosition().x + 12.f < _settings.cb[i].left + _settings.cb[i].width
						&& _corrupted.back().getPosition().y - 24.f - 8.f > _settings.cb[i].top
						&& _corrupted.back().getPosition().y - 24.f - 8.f < _settings.cb[i].top + _settings.cb[i].height) {
							bad = true;
							break;
						}
					}
				}
			}
		}
		if(_player.getPosition().x > 90 * 16 && !_player.isJumping()) {
			if(_corr_clock.getElapsedTime().asSeconds() > 2.f && keb.size() < 6) {
				_corr_clock.restart();
				keb.emplace_back(&_settings);
				keb.back().setPosition(_player.getPosition().x - 128.f + rand() % 256, _player.getPosition().y - 32.f - ((rand() % 2) * 16.f));
				keb.back().keb.setColor(Color(255, 255, 255, 0));
			}
		}
	}

	for(unsigned i = 0; i < gg.size(); ++i) {
		if(_settings.gz[i].width == 0 || _settings.gz[i].left > _view.getCenter().x + _view.getSize().x / 2.f || _settings.gz[i].left + _settings.gz[i].width < _view.getCenter().x - _view.getSize().x / 2.f) {
			gg.erase(gg.begin() + i);
			break;
		}
	}
	static float waiting = 0.f;
	if(_player.dead || _settings._t.asSeconds() < 0.5f) {
		if(waiting < 1.f) {
			if(_lives == 0) {
				_settings.state = 4;
				splashtx.loadFromFile("data/gaemover2.png");
				splash.setTexture(splashtx);
				waiting += 1.f;
			}
			else waiting += 3.f;
		}
		waiting += delta;
		if(waiting > 4.f) {
			waiting = 0.f;
			--_lives;
			g->lives--;
			g->score = _settings._s;
			_settings.running = false;
			/*_player.setPosition(16 * 9, 224);
			_head.setTextureRect(IntRect(0, 0, _head_tx.getSize().x * _lives, _head_tx.getSize().y));
			if(_lives <= -1) {
				_settings.state = 4;
				splashtx.loadFromFile("data/gaemover2.png");
				splash.setTexture(splashtx);
			}
			_view.setCenter(_player.getPosition().x, _player.getPosition().y - 80.f);
			_background.setPosition(_player.getPosition().x, _player.getPosition().y - 80.f);
			_evm.setPosition(_player.getPosition().x + 32.f, _player.getPosition().y - 128.f);
			_fog.setPosition(_player.getPosition().x, _player.getPosition().y - 80.f);

			_player.dead = false;
			_player.armored = true;
			_player.iframed = true;
			_player.iframeclock.restart();*/
		}
	}
}

void Core::render()
{
	g->window.setView(_view);
	g->window.draw(_background);
	g->window.draw(_evm);
	for(unsigned i = 1; i < LAYERCOUNT; ++i) {
    	g->window.draw(_layer[i]);
	}
	g->window.draw(_p1);
	g->window.draw(_p2);
	g->window.draw(_p3);
	for(unsigned i = 0; i < _corrupted.size(); ++i) {
		g->window.draw(_corrupted[i]);
	}
	for(unsigned i = 0; i < keb.size(); ++i) {
		g->window.draw(keb[i]);
	}
	g->window.draw(_layer[0]);
	if(_settings.state == 2)
		g->window.draw(_player);
	if(_settings.state == 0 && _s1c.getElapsedTime().asSeconds() < 4.f)
		g->window.draw(_trixie);
	for(unsigned i = 0; i < gg.size(); ++i) {
		g->window.draw(gg[i]);
	}
	g->window.draw(_fog);
	g->window.draw(debug);
	g->window.draw(debug2);
	g->window.setView(g->window.getDefaultView());

	g->window.draw(_hud_time);
	g->window.draw(_hud_highscore);
	g->window.draw(_hud_energy);
	g->window.draw(_highscore_text);
	g->window.draw(_time_text);
	g->window.draw(_energy_text);
	if(_settings.state == 2) {
		g->window.draw(_head);
		g->window.draw(_frame);
	}
	if(_settings.state == 0 || _settings.state > 2) {
		g->window.draw(splash);
	}
	g->window.draw(_hud_score);
	g->window.draw(_score_text);
	g->window.display();
}
