#pragma once

#include <QString>

#include "BuildingType.h"
#include "ControlAction.h"
#include "WorldCamera.h"

class QKeyEvent;

// Turns raw key events into the game's semantic actions and publishes them
// (REQ-UI-HOTKEYS). Widgets react to the action, never to the key, so the two can
// be rebound independently later.
//
// Which key means what is not decided here: the caller hands in a ControlContext and
// ControlAction.h resolves the press against it, so this file only knows what each
// action means once resolved. That is what keeps the controls panel and the key
// handling from drifting apart -- both read the one table (REQ-UI-CONTROLS-ACCURACY).
//
// Two output shapes, chosen by the nature of the action rather than by taste:
//
//  * Discrete actions — one press, one thing happens — fire an event as they
//    always have.
//  * Continuous actions, currently just panning, are held state. They also travel
//    as events, but level-triggered ones carrying the complete current value (see
//    PanDirectionChangedEvent), so a receiver never has to reconstruct state from
//    edges.
//
// Holding the state here rather than in the widgets is what makes releaseAll()
// possible: one call clears every held action at once, which is how a lost key-up
// (focus moving to a modal mid-pan) stops being a stuck input.
class InputMapper
{
public:
    // The build hotkey that selects the given building type, spelled for display on
    // its build button's badge (REQ-UI-BUILD-COST): "1" for a plain digit, "⇧1" for
    // a Shift+digit, and an empty string for a building type with no build hotkey.
    // Lives here so the badge and the key handling read the same binding table.
    static QString getBuildHotkeyLabel(BuildingType type);

    // Both return true when the key was consumed; the caller passes anything else
    // on to its base class so unrelated shortcuts keep working. `context` is the
    // player's current situation, which decides what a key does (REQ-UI-CONTROLS-CONTENT).
    bool handleKeyPress(QKeyEvent* event, const ControlContext& context);
    bool handleKeyRelease(QKeyEvent* event, const ControlContext& context);

    // Drops all held-key state, publishing the resulting change. Call when the
    // receiving widget can no longer expect key-up events.
    void releaseAll();

private:
    // Recomputes the pan direction from the held keys and publishes it if it
    // changed. Holding both keys cancels out.
    void updatePanDirection();

    bool         m_panLeftHeld   = false;
    bool         m_panRightHeld  = false;
    PanDirection m_panDirection  = PanDirection::None;
};
