/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

#pragma once

#include "InputDevice.hpp"
#include <bitset>

namespace OpenVulkano
{
	class IWindow;

	namespace Input
	{
		class InputDeviceKeyboard : public InputDevice
		{
			std::bitset<InputKey::Keyboard::KEY_LAST + 1> keyState;
			std::bitset<InputKey::Keyboard::KEY_LAST + 1> lastKeyState;
			IWindow* lastWindow = nullptr;

		protected:
			InputDeviceKeyboard() = default;

			void Init(int index, const std::string& name)
			{
				InputDevice::Init(InputDeviceType::KEYBOARD, index, name);
			}

			void PreTick()
			{
				lastKeyState = keyState;
			}

			void UpdateKey(InputKey::Keyboard::Key key, bool state)
			{
				keyState[key] = state;
			}

			void UpdateActiveWindow(IWindow* window)
			{
				lastWindow = window;
			}

			[[nodiscard]] float ReadAxis(int16_t key) const final
			{
				return 0;
			}

			[[nodiscard]] bool ReadButton(int16_t key) const final
			{
				return GetButton(static_cast<InputKey::Keyboard::Key>(key));
			}

			[[nodiscard]] bool ReadButtonUp(int16_t key) const final
			{
				return GetButtonUp(static_cast<InputKey::Keyboard::Key>(key));
			}

			[[nodiscard]] bool ReadButtonDown(int16_t key) const final
			{
				return GetButtonDown(static_cast<InputKey::Keyboard::Key>(key));
			}

		public:
			[[nodiscard]] bool GetButton(const InputKey::Keyboard::Key button) const
			{
				return keyState[button] > 0;
			}

			[[nodiscard]] bool GetButtonUp(const InputKey::Keyboard::Key button) const
			{
				return !keyState[button] && lastKeyState[button];
			}

			[[nodiscard]] bool GetButtonDown(const InputKey::Keyboard::Key button) const
			{
				return keyState[button] && !lastKeyState[button];
			}

			[[nodiscard]] IWindow* GetActiveWindow() const
			{
				return lastWindow;
			}

			bool IsInWindow(const IWindow* window) const
			{
				return window == lastWindow;
			}
		};
	}
}