#include "stdafx.h"
#include "shortcut_handler.h"
#include "gui_settings.h"

LOG_CHANNEL(shortcut_log, "Shortcuts");

shortcut_handler::shortcut_handler(gui::shortcuts::shortcut_handler_id handler_id, QObject* parent, const std::shared_ptr<gui_settings>& gui_settings)
	: QObject(parent), m_handler_id(handler_id), m_gui_settings(gui_settings)
{
	// Initialize shortcuts
	shortcut_settings sc_settings{};

	for (const auto& [shortcut_key, info] : sc_settings.shortcut_map)
	{
		// Skip shortcuts that weren't meant for this handler
		if (handler_id != info.handler_id)
		{
			continue;
		}

		QKeySequence key_sequence = sc_settings.get_key_sequence(info, gui_settings);

		shortcut_key_info key_info{};
		key_info.shortcut = make_shortcut(shortcut_key, info, key_sequence);
		key_info.info = info;
		key_info.key_sequence = std::move(key_sequence);

		m_shortcuts[shortcut_key] = std::move(key_info);
	}
}

QShortcut* shortcut_handler::make_shortcut(gui::shortcuts::shortcut key, const shortcut_info& info, const QKeySequence& key_sequence)
{
	if (key_sequence.isEmpty())
	{
		return nullptr;
	}

	QShortcut* shortcut = new QShortcut(key_sequence, parent());
	shortcut->setAutoRepeat(info.allow_auto_repeat);

	connect(shortcut, &QShortcut::activated, this, [this, key]()
	{
		handle_shortcut(key, m_shortcuts[key].key_sequence);
	});
	connect(shortcut, &QShortcut::activatedAmbiguously, this, [this, key]()
	{
		// TODO: do not allow same shortcuts and remove this connect
		// activatedAmbiguously will trigger if you have the same key sequence for several shortcuts
		const QKeySequence& key_sequence = m_shortcuts[key].key_sequence;
		shortcut_log.error("%s: Shortcut activated ambiguously: %s (%s)", m_handler_id, key, key_sequence.toString());
		handle_shortcut(key, key_sequence);
	});

	return shortcut;
}

void shortcut_handler::update()
{
	shortcut_log.notice("%s: Updating shortcuts", m_handler_id);

	shortcut_settings sc_settings{};

	for (const auto& [shortcut_key, info] : sc_settings.shortcut_map)
	{
		// Skip shortcuts that weren't meant for this handler
		if (m_handler_id != info.handler_id || !m_shortcuts.contains(shortcut_key))
		{
			continue;
		}

		const QKeySequence key_sequence = sc_settings.get_key_sequence(info, m_gui_settings);

		shortcut_key_info& key_info = m_shortcuts[shortcut_key];
		key_info.key_sequence = key_sequence;

		if (key_info.shortcut)
		{
			if (key_sequence.isEmpty())
			{
				key_info.shortcut->deleteLater();
				key_info.shortcut = nullptr;
			}
			else
			{
				key_info.shortcut->setKey(key_sequence);
			}
		}
		else
		{
			key_info.shortcut = make_shortcut(shortcut_key, info, key_sequence);
		}
	}
}

void shortcut_handler::handle_shortcut(gui::shortcuts::shortcut shortcut_key, const QKeySequence& key_sequence)
{
	shortcut_log.notice("%s: Shortcut pressed: %s (%s)", m_handler_id, shortcut_key, key_sequence.toString());

	Q_EMIT shortcut_activated(shortcut_key, key_sequence);
}
