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

#include "MapCameraController.hpp"
#include "Input/InputManager.hpp"
#include "Scene/Camera.hpp"
#include "Base/FrameMetadata.hpp"

namespace OpenVulkano
{
	MapCameraController::MapCameraController(Scene::Camera* camera) : CameraController(camera)
	{
		auto input = Input::InputManager::GetInstance();
		m_actionUp = input->GetAction("map_up");
		m_actionSide = input->GetAction("map_side");
		m_actionZoom = input->GetAction("map_zoom");
	}

	void MapCameraController::Tick()
	{
		if (!GetCamera()) return;
		auto input = Input::InputManager::GetInstance();
		float up = input->GetAxis(m_actionUp);
		float side = input->GetAxis(m_actionSide);
		Math::Vector3f_SIMD vec = m_dirUp * up + m_dirSide * side;
		vec /= GetCamera()->GetZoom();
		vec /= GetCamera()->GetContentScaleFactor();

		float zoom = Input::InputManager::GetInstance()->GetAxis(m_actionZoom);
		if (zoom != 0)
		{
			float tmp = sqrt(GetCamera()->GetZoom()) + zoom / std::max(10.0f, (100 - GetCamera()->GetZoom()));
			tmp = std::max(3.0f, tmp);
			GetCamera()->SetZoom(tmp * tmp);
			GetCamera()->UpdateProjectionMatrix();
		}

		if (zoom != 0 || up != 0 || side != 0)
		{
			GetCamera()->SetMatrix(Math::Utils::translate(vec) * GetCamera()->GetMatrix());
			CURRENT_FRAME.needsRedraw = true;
		}
	}
	
	void MapCameraController::SetSliceHeight(float height)
	{
		float diff = height - GetCamera()->GetPosition().y;
		GetCamera()->SetMatrix(Math::Utils::translate(Math::Vector3f_SIMD{0,diff,0}) * GetCamera()->GetMatrix());
		CURRENT_FRAME.needsRedraw = true;
	}

	void MapCameraController::SetDefaultKeybindings()
	{
		m_actionUp->BindKey(Input::InputKey::Controller::AXIS_LEFT_Y);
		m_actionUp->BindKey(Input::InputKey::Touch::AXIS_PAN_Y);
		m_actionUp->BindKey(Input::InputKey::Touch::AXIS_PAN_TWO_FINGERS_Y);
		m_actionUp->BindKey(Input::InputKey::Mouse::AXIS_Y);
		m_actionSide->BindKey(Input::InputKey::Controller::AXIS_LEFT_X);
		m_actionSide->BindKey(Input::InputKey::Touch::AXIS_PAN_X);
		m_actionSide->BindKey(Input::InputKey::Touch::AXIS_PAN_TWO_FINGERS_X);
		m_actionSide->BindKey(Input::InputKey::Mouse::AXIS_X);
		m_actionZoom->BindKey(Input::InputKey::Mouse::AXIS_WHEEL_Y, 2);
		m_actionZoom->BindKey(Input::InputKey::Touch::AXIS_PINCH, 0.2);
	}
}
