/**
 *  one room arena
 *  Copyright (C) 2016 POSITIVE MENTAL ATTITUDE
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, version 3 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <cmath>
#include <sstream>
#include <Starlight.hpp>
Starlight::Starlight(RenderWindow* window, bool* keepRunning):
	_map(),
	_player(&_map),
	_powerups(&_map),
	_returnCode(0),
	_running(true),
	_keepRunning(keepRunning)
{
	_window = window;

	_player.setPosition(768.f, 768.f);
	_player.setColor(Color(255, 50, 50, 200));
	
	_enemy.push_back(new AiPlayer(&_map));
	_enemy[0]->setPosition(2536.f, 536.f);
	_enemy[0]->setColor(Color(50, 255, 255, 200));
	
	_powerups.registerPlayer(&_player);

	_view.setCenter(_player.getPosition());
	_view.setSize(768.f * 2.f, 768.f * 2.f);
	
	_frame.setSize(Vector2f(768.f, 768.f));
	_frame.setFillColor(Color(0, 0, 0, 200));
	_frame.setPosition(0, 0);
	
	Player::actualPlayer = &_player;
	Player::aiPlayer = &_enemy;
}

Starlight::~Starlight()
{
	
}
 
void Starlight::run()
{
	sf::Clock clock;
	float delta;
	while(_running)
	{
		delta = clock.restart().asSeconds();
		events();
		input(delta);
		logic(delta);
		render();
	} 
}

void Starlight::events()
{
	Event event;
	while(_window->pollEvent(event))
	{
		if(event.type == Event::Closed)
			_running = false;
		if(event.type == Event::KeyPressed && (event.key.code == Keyboard::Escape || event.key.code == Keyboard::P))
			_menu.revive();
		if(event.type == Event::MouseButtonPressed && event.mouseButton.button == Mouse::Right)
			_player.spawnBullet(true);
		if(event.type == Event::MouseWheelMoved)
		{
			if((event.mouseWheel.delta < 0.f && _view.getSize().x < 3072.f)
			|| (event.mouseWheel.delta > 0.f && _view.getSize().x > 768.f))
			_view.setSize(_view.getSize() * (1.f - event.mouseWheel.delta / 10.f));
		}
	}
}
void Starlight::input(float delta)
{
	if(_menu.isDead())
	{
		if(!_player.isDead())
			_player.input(delta, &_map, (Vector2f)Mouse::getPosition(*_window) - (Vector2f)_window->getSize() / 2.f);
		for(unsigned i = 0; i < _enemy.size(); ++i)
			_enemy[i]->input(delta, &_map, &_player);
	}
}

void Starlight::logic(float delta)
{
	if(_menu.isDead())
		toggleFrame(false, delta);
	else
		toggleFrame(true, delta);
	
	if(!_player.isDead())
		_view.setCenter(_player.getPosition());
	else
		_menu.revive(true);

	if(!_menu.isDead())
		_menu.logic(delta, Mouse::getPosition(*_window), _running, _keepRunning);
	else
	{
		_powerups.logic();
		if(!_player.isDead())
			_player.logic(delta);
		for(unsigned i = 0; i < _enemy.size(); ++i)
		{
			_enemy[i]->logic(delta);
			if(_enemy[i]->isDead())
			{
				_powerups.deregisterPlayer(_enemy[i]);
				_enemy.erase(_enemy.begin() + i);
				--i; 
			}
		}
			
		static Clock clock, clock2;
		if(clock.getElapsedTime().asSeconds() > 4.f && _enemy.size() < 50)
		{
			static Color colors[] = {
				Color(50, 255, 50, 200),
				Color(50, 50, 255, 200),
				Color(255, 50, 255, 200),
				Color(255, 255, 0, 200),
				Color(0, 255, 255, 200)
			};
			_enemy.push_back(new AiPlayer(&_map));
			int x, y;
			do {
				x = rand() % (_map.getSize().x - 200) + 100;
				y = rand() % (_map.getSize().x - 200) + 100;
				_enemy.back()->setPosition(x, y);
			} while(
			   _map.collision(Vector2f(x - 50.f, y)) 
			|| _map.collision(Vector2f(x + 50.f, y)) 
			|| _map.collision(Vector2f(x, y + 50.f)) 
			|| _map.collision(Vector2f(x, y - 50.f))
			|| _map.collision(Vector2f(x - 150.f, y)) 
			|| _map.collision(Vector2f(x + 150.f, y)) 
			|| _map.collision(Vector2f(x, y + 150.f)) 
			|| _map.collision(Vector2f(x, y - 150.f))
			|| _map.collision(Vector2f(x, y))
			|| std::sqrt(std::pow(x - _player.getPosition().x, 2) + std::pow(y - _player.getPosition().y, 2)) < 600);
			_powerups.registerPlayer(_enemy.back());
			_enemy.back()->setColor(colors[rand() % 5]);
			_enemy.back()->registerPowerups(&_powerups);
			clock.restart();
		}
		if(clock2.getElapsedTime().asSeconds() >= 1.f)
		{
			Player::totalScore += 10;
			clock2.restart();
		}
	}
}

void Starlight::render()
{
	std::ostringstream oss;
	oss << "one room arena - Score: " << Player::totalScore << ", Nukes: " << _player.nukes();
	_window->setTitle(oss.str());
	_window->clear(Color::Black);
	_window->setView(_view);
	_window->draw(_map);
	if(!_player.isDead())
		_window->draw(_player);
	for(unsigned i = 0; i < _enemy.size(); ++i)
		_window->draw(*_enemy[i]);
	_window->draw(_powerups);
	_player.drawBullets(*_window);
	for(unsigned i = 0; i < _enemy.size(); ++i)
		_enemy[i]->drawBullets(*_window);
	_window->setView(_window->getDefaultView());
	_window->draw(_frame);
	if(!_menu.isDead())
	{
		_menu.render(*_window);
	}
	_window->display();
}

void Starlight::toggleFrame(bool on, float delta)
{
	static float transparency = 0.f;
	if(on)
	{
		transparency += delta * 75.f;
		if(transparency > 200.f)
			transparency = 200.f;
		_frame.setFillColor(Color(0, 0, 0, (int)transparency));
	}
	else
	{
		transparency -= delta * 75.f;
		if(transparency < 0.f)
			transparency = 0.f;
		_frame.setFillColor(Color(0, 0, 0, (int)transparency));
	}
}
