/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          https://www.mrpt.org/                         |
   |                                                                        |
   | Copyright (c) 2005-2023, Individual contributors, see AUTHORS file     |
   | See: https://www.mrpt.org/Authors - All rights reserved.               |
   | Released under BSD License. See: https://www.mrpt.org/License          |
   +------------------------------------------------------------------------+ */

#include "graphslam-precomp.h"	// Precompiled headers
//
// Implementation file for CWindowObserver class
#include <mrpt/graphslam/misc/CWindowObserver.h>
#include <mrpt/gui/CBaseGUIWindow.h>
#include <mrpt/opengl/Viewport.h>

using namespace mrpt::graphslam;

CWindowObserver::CWindowObserver()
{
	m_help_msg =
		"User options:\n"
		" - h/H: Toggle help message\n"
		" - Alt+Enter: Toggle fullscreen\n"
		" - Mouse click: Set camera manually\n"
		" - Ctrl+c: Halt program execution";

	// register the default keystrokes
	m_key_codes_to_pressed["h"] = false;
	m_key_codes_to_pressed["Alt+Enter"] = false;
	m_key_codes_to_pressed["Ctrl+c"] = false;
	m_key_codes_to_pressed["mouse_clicked"] = false;
}

void CWindowObserver::returnEventsStruct(
	std::map<std::string, bool>* codes_to_pressed,
	bool reset_keypresses /*= true */)
{
	*codes_to_pressed = m_key_codes_to_pressed;

	// reset the code flags
	if (reset_keypresses)
	{
		for (auto& map_it : m_key_codes_to_pressed)
		{
			map_it.second = false;
		}
	}
}

void CWindowObserver::registerKeystroke(
	const std::string key_str, const std::string key_desc)
{
	m_help_msg += std::string("\n") + " - " + key_str + "/" +
		mrpt::system::upperCase(key_str) + ": " + key_desc;

	m_key_codes_to_pressed[key_str] = false;
}

void CWindowObserver::OnEvent(const mrpt::system::mrptEvent& e)
{
	if (e.isOfType<mrpt::system::mrptEventOnDestroy>())
	{
		const auto& ev =
			dynamic_cast<const mrpt::system::mrptEventOnDestroy&>(e);
		(void)ev;
		std::cout << "Event received: mrptEventOnDestroy" << std::endl;
	}
	else if (e.isOfType<mrpt::gui::mrptEventWindowResize>())
	{
		const auto& ev =
			static_cast<const mrpt::gui::mrptEventWindowResize&>(e);
		std::cout << "Resize event received from: " << ev.source_object
				  << ", new size: " << ev.new_width << " x " << ev.new_height
				  << std::endl;
	}
	else if (e.isOfType<mrpt::gui::mrptEventWindowChar>())
	{
		const auto& ev = dynamic_cast<const mrpt::gui::mrptEventWindowChar&>(e);
		std::cout << "Char event received from: " << ev.source_object
				  << ". Char code: " << ev.char_code
				  << " modif: " << ev.key_modifiers << std::endl;
		;

		switch (ev.char_code)
		{
			case 'h':
			case 'H': m_key_codes_to_pressed["h"] = true; break;
			case 'c':
			case 'C':
				// case 3: // <C-c>
				if (ev.key_modifiers == 8192)
				{
					std::cout << "Pressed C-c inside CDisplayWindow3D"
							  << std::endl;
					m_key_codes_to_pressed["Ctrl+c"] = true;
				}
				break;

			default:
				// just raise the corresponding flag. Let the class which
				// actually
				// cares translate the character to its corresponding meaning.
				// Pressed letter is stored in lower case form only to make it
				// easier
				// to check afterwards
				m_key_codes_to_pressed[mrpt::system::lowerCase(
					std::string(1, ev.char_code))] = true;
				break;
		}

	}  // end of e.isOftype<mrptEventWindowChar>
	else if (e.isOfType<mrpt::gui::mrptEventWindowClosed>())
	{
		const auto& ev =
			dynamic_cast<const mrpt::gui::mrptEventWindowClosed&>(e);
		std::cout << "Window closed event received from: " << ev.source_object
				  << "\n";
	}
	else if (e.isOfType<mrpt::gui::mrptEventMouseDown>())
	{
		const auto& ev = dynamic_cast<const mrpt::gui::mrptEventMouseDown&>(e);
		m_key_codes_to_pressed["mouse_clicked"] = true;

		std::cout << "Mouse down event received from: " << ev.source_object
				  << "pt: " << ev.coords.x << "," << ev.coords.y << "\n";
	}
	else if (e.isOfType<mrpt::opengl::mrptEventGLPostRender>())
	{
		/*
		 * An event sent by an mrpt::opengl::Viewport AFTER calling
		 * the
		 * SCENE OPENGL DRAWING PRIMITIVES and before doing a glSwapBuffers.
		 */

		// was: show m_help_msg.c_str()
	}
}
