/**
 *  Triangles
 *  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 "TrianglesWindow.hpp"
#include "InputTarget.hpp"
#include "Utility.hpp"

TrianglesWindow::TrianglesWindow(const std::string& title, sf::Vector2u size):
	InputTarget(_inputMap),
	_size(size),
	_title(title),
	_mouseLocked(false)
{
	_context = nullptr;
	_inputMap.map(0, Input(sf::Keyboard::F9, Input::Type::Pressed));
	_inputMap.map(1, Input(sf::Keyboard::F11, Input::Type::Pressed));
	_inputMap.map(2, Input(sf::Keyboard::F10, Input::Type::Pressed));
	bind(0, [this](const sf::Event&, float)
	{
		unsigned s = sf::VideoMode::getFullscreenModes().size();
		for(unsigned i = 0; i < s; ++i)
		{
			sf::VideoMode vm = sf::VideoMode::getFullscreenModes()[i];
			if(vm.width < 640 || vm.height < 480)
				continue;
			else if(vm.width == _size.x && vm.height == _size.y)
			{
				if(i + 1 < s && sf::VideoMode::getFullscreenModes()[i + 1].width >= 640 && sf::VideoMode::getFullscreenModes()[i + 1].height >= 480)
					_size = sf::Vector2u(sf::VideoMode::getFullscreenModes()[i + 1].width, sf::VideoMode::getFullscreenModes()[i + 1].height);
				else
					_size = sf::Vector2u(sf::VideoMode::getFullscreenModes()[0].width, sf::VideoMode::getFullscreenModes()[0].height);
				break;
			}
		}
		recreate();
	});
	bind(1, [this](const sf::Event&, float) 
	{
		_context->fullscreen = !_context->fullscreen;
		recreate();
	});
	bind(2, [this](const sf::Event&, float)
	{
		_context->vsync = !_context->vsync;
		recreate();
	});
	
	_textures.reserve(2000);
}

TrianglesWindow::~TrianglesWindow()
{
	close();
}

void TrianglesWindow::setContext(Context* context)
{
	_context = context;
}

void TrianglesWindow::clear()
{
	_window.clear(sf::Color::Black);
}

void TrianglesWindow::clear(sf::Color color)
{
	_window.clear(color);
}

void TrianglesWindow::render()
{
	_window.display();
	_window.setMouseCursorVisible(true);
}

void TrianglesWindow::recreate()
{
	close();
	open();
}

void TrianglesWindow::lockFramerate(bool locked)
{
	if(_context->vsync)
		return;
	if(locked)
		_window.setFramerateLimit(30);
	else
		_window.setFramerateLimit(240);
}

bool TrianglesWindow::setActive(bool active)
{
	return _window.setActive(active);
}

void TrianglesWindow::setSize(sf::Vector2u& size)
{
	_size = size;
}

void TrianglesWindow::setSize(unsigned width, unsigned height)
{
	_size = sf::Vector2u(width, height);
}

sf::Vector2u TrianglesWindow::getSize()
{
	return _window.getSize();
}

void TrianglesWindow::setView(const sf::View* view)
{
	_window.setView(*view);
}

void TrianglesWindow::setView()
{
	_window.setView(_window.getDefaultView());
}

void TrianglesWindow::draw(sf::Drawable& drawable)
{
	_window.draw(drawable);
}
void TrianglesWindow::draw(sf::Drawable& drawable, sf::RenderStates states)
{
	_window.draw(drawable, states);
}
void TrianglesWindow::draw(sf::Drawable& drawable, sf::Shader* shader)
{
	_window.draw(drawable, shader);
}

bool TrianglesWindow::pollEvent(sf::Event& event)
{
	return _window.pollEvent(event);
}

sf::Vector2i TrianglesWindow::getMousePosition()
{
	return sf::Mouse::getPosition(_window);
}

void TrianglesWindow::lockMouse()
{
	lockMouse(sf::Vector2i(_size.x / 2.f, _size.y / 2.f));
}

void TrianglesWindow::lockMouse(sf::Vector2i position)
{
	_window.setMouseCursorVisible(false);
	sf::Mouse::setPosition(position, _window);
}

const sf::View& TrianglesWindow::getDefaultView()
{
	return _window.getDefaultView();
}

void TrianglesWindow::open()
{
	sf::ContextSettings settings;
	settings.majorVersion = 1;
	settings.minorVersion = 1;
	//settings.antialiasingLevel = 8;
	_window.create(sf::VideoMode(_size.x, _size.y), _title, (_context->fullscreen ? sf::Style::Fullscreen : (_context->borderless ? sf::Style::None : (sf::Style::Titlebar | sf::Style::Close))), settings);
	_window.setKeyRepeatEnabled(false);
	if(_context->borderless)
		_window.setPosition(sf::Vector2i(0, 0));
	if(_context->vsync)
		_window.setVerticalSyncEnabled(true);
	if(_context)
		_context->needsUpdate = true;
}

void TrianglesWindow::close()
{
	if(_window.isOpen())
		_window.close();
}