/**
 *  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/>.
 */

#pragma once

#include <list>
#include <functional>
#include <SFML/Window.hpp>
#include "InputMap.hpp"
#include <iostream>
template<typename T = int>
class InputTarget
{
	public:
		InputTarget(const InputTarget<T>&) = delete;
		InputTarget<T>& operator=(const InputTarget<T>&) = delete;
		
		InputTarget(const InputMap<T>& map): _inputMap(map) {}
		
		bool think(const sf::Event& event) const
		{
			for(auto& pair: _eventsPoll)
			{
				if(_inputMap.get(pair.first) == event)
				{
					pair.second(event, 1.f);
					return true;
				}
			}
			return false;
		}
		void think() const
		{
			for(auto& pair: _eventsRealTime)
			{
				const Input& input = _inputMap.get(pair.first);
				float power = input.test();
				if(power != 0.f)
					pair.second(input._event, power);
			}
		}
		
		void bind(const T& key, const std::function<void(const sf::Event&, float)>& callback)
		{
			const Input& input = _inputMap.get(key);
			if(input._type & Input::Type::RealTime)
				_eventsRealTime.emplace_back(key, callback);
			else
				_eventsPoll.emplace_back(key, callback);
		}

		void unbind(const T& key)
		{
			auto remove_func = [&key](const std::pair<T, std::function<void(const sf::Event&, float)>>& pair) -> bool
			{
				return pair.first == key;
			};

			if(_inputMap.get(key)._type & Input::Type::RealTime)
				_eventsRealTime.remove_if(remove_func);
			else
				_eventsPoll.remove_if(remove_func);
		}
	
	private:
		std::list<std::pair<T, std::function<void(const sf::Event&, float power)>>> _eventsRealTime;
		std::list<std::pair<T, std::function<void(const sf::Event&, float power)>>> _eventsPoll;
		
		const InputMap<T>& _inputMap;
};