#include "../config/ConfigValue.hpp"
#include "../config/legacy/ConfigManager.hpp"
#include "../config/shared/monitor/MonitorRuleManager.hpp"
#include "../devices/IKeyboard.hpp"
#include "../desktop/state/FocusState.hpp"
#include "../desktop/history/WindowHistoryTracker.hpp"
#include "../desktop/history/WorkspaceHistoryTracker.hpp"
#include "../managers/SeatManager.hpp"
#include "../protocols/LayerShell.hpp"
#include "../protocols/ShortcutsInhibit.hpp"
#include "../protocols/GlobalShortcuts.hpp"
#include "../protocols/IdleNotify.hpp"
#include "../protocols/core/DataDevice.hpp"
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
#include "KeybindManager.hpp"
#include "PointerManager.hpp"
#include "Compositor.hpp"
#include "TokenManager.hpp"
#include "eventLoop/EventLoopManager.hpp"
#include "debug/log/Logger.hpp"
#include "../managers/input/InputManager.hpp"
#include "../managers/animation/DesktopAnimationManager.hpp"
#include "../managers/EventManager.hpp"
#include "../render/Renderer.hpp"
#include "../errorOverlay/Overlay.hpp"
#include "../config/ConfigManager.hpp"
#include "../desktop/rule/windowRule/WindowRule.hpp"
#include "../desktop/rule/Engine.hpp"
#include "../desktop/view/Group.hpp"
#include "../layout/LayoutManager.hpp"
#include "../layout/target/WindowTarget.hpp"
#include "../layout/space/Space.hpp"
#include "../layout/algorithm/Algorithm.hpp"
#include "../layout/algorithm/tiled/master/MasterAlgorithm.hpp"
#include "../layout/algorithm/tiled/monocle/MonocleAlgorithm.hpp"
#include "../event/EventBus.hpp"
#include "../config/supplementary/executor/Executor.hpp"

#include <optional>
#include <iterator>
#include <string>
#include <string_view>
#include <cstring>

#include <hyprutils/string/String.hpp>
#include <hyprutils/string/ConstVarList.hpp>
#include <hyprutils/string/VarList.hpp>
#include <hyprutils/string/VarList2.hpp>
#include <hyprutils/os/FileDescriptor.hpp>
using namespace Hyprutils::String;
using namespace Hyprutils::OS;

#include <sys/ioctl.h>
#include <fcntl.h>
#include <vector>
#if defined(__linux__)
#include <linux/vt.h>
#elif defined(__NetBSD__) || defined(__OpenBSD__)
#include <dev/wscons/wsdisplay_usl_io.h>
#elif defined(__DragonFly__) || defined(__FreeBSD__)
#include <sys/consio.h>
#endif

CKeybindManager::CKeybindManager() {
    // initialize all dispatchers

    m_dispatchers["exec"]                           = spawn;
    m_dispatchers["execr"]                          = spawnRaw;
    m_dispatchers["killactive"]                     = closeActive;
    m_dispatchers["forcekillactive"]                = killActive;
    m_dispatchers["closewindow"]                    = closeWindow;
    m_dispatchers["killwindow"]                     = killWindow;
    m_dispatchers["signal"]                         = signalActive;
    m_dispatchers["signalwindow"]                   = signalWindow;
    m_dispatchers["togglefloating"]                 = toggleActiveFloating;
    m_dispatchers["setfloating"]                    = setActiveFloating;
    m_dispatchers["settiled"]                       = setActiveTiled;
    m_dispatchers["workspace"]                      = changeworkspace;
    m_dispatchers["renameworkspace"]                = renameWorkspace;
    m_dispatchers["fullscreen"]                     = fullscreenActive;
    m_dispatchers["fullscreenstate"]                = fullscreenStateActive;
    m_dispatchers["movetoworkspace"]                = moveActiveToWorkspace;
    m_dispatchers["movetoworkspacesilent"]          = moveActiveToWorkspaceSilent;
    m_dispatchers["pseudo"]                         = toggleActivePseudo;
    m_dispatchers["movefocus"]                      = moveFocusTo;
    m_dispatchers["movewindow"]                     = moveActiveTo;
    m_dispatchers["swapwindow"]                     = swapActive;
    m_dispatchers["centerwindow"]                   = centerWindow;
    m_dispatchers["togglegroup"]                    = toggleGroup;
    m_dispatchers["changegroupactive"]              = changeGroupActive;
    m_dispatchers["movegroupwindow"]                = moveGroupWindow;
    m_dispatchers["focusmonitor"]                   = focusMonitor;
    m_dispatchers["movecursortocorner"]             = moveCursorToCorner;
    m_dispatchers["movecursor"]                     = moveCursor;
    m_dispatchers["workspaceopt"]                   = workspaceOpt;
    m_dispatchers["exit"]                           = exitHyprland;
    m_dispatchers["movecurrentworkspacetomonitor"]  = moveCurrentWorkspaceToMonitor;
    m_dispatchers["focusworkspaceoncurrentmonitor"] = focusWorkspaceOnCurrentMonitor;
    m_dispatchers["moveworkspacetomonitor"]         = moveWorkspaceToMonitor;
    m_dispatchers["togglespecialworkspace"]         = toggleSpecialWorkspace;
    m_dispatchers["forcerendererreload"]            = forceRendererReload;
    m_dispatchers["resizeactive"]                   = resizeActive;
    m_dispatchers["moveactive"]                     = moveActive;
    m_dispatchers["cyclenext"]                      = circleNext;
    m_dispatchers["focuswindowbyclass"]             = focusWindow;
    m_dispatchers["focuswindow"]                    = focusWindow;
    m_dispatchers["tagwindow"]                      = tagWindow;
    m_dispatchers["toggleswallow"]                  = toggleSwallow;
    m_dispatchers["submap"]                         = setSubmap;
    m_dispatchers["pass"]                           = pass;
    m_dispatchers["sendshortcut"]                   = sendshortcut;
    m_dispatchers["sendkeystate"]                   = sendkeystate;
    m_dispatchers["layoutmsg"]                      = layoutmsg;
    m_dispatchers["dpms"]                           = dpms;
    m_dispatchers["movewindowpixel"]                = moveWindow;
    m_dispatchers["resizewindowpixel"]              = resizeWindow;
    m_dispatchers["swapnext"]                       = swapnext;
    m_dispatchers["swapactiveworkspaces"]           = swapActiveWorkspaces;
    m_dispatchers["pin"]                            = pinActive;
    m_dispatchers["mouse"]                          = mouse;
    m_dispatchers["bringactivetotop"]               = bringActiveToTop;
    m_dispatchers["alterzorder"]                    = alterZOrder;
    m_dispatchers["focusurgentorlast"]              = focusUrgentOrLast;
    m_dispatchers["focuscurrentorlast"]             = focusCurrentOrLast;
    m_dispatchers["lockgroups"]                     = lockGroups;
    m_dispatchers["lockactivegroup"]                = lockActiveGroup;
    m_dispatchers["moveintogroup"]                  = moveIntoGroup;
    m_dispatchers["moveintoorcreategroup"]          = moveIntoOrCreateGroup;
    m_dispatchers["moveoutofgroup"]                 = moveOutOfGroup;
    m_dispatchers["movewindoworgroup"]              = moveWindowOrGroup;
    m_dispatchers["setignoregrouplock"]             = setIgnoreGroupLock;
    m_dispatchers["denywindowfromgroup"]            = denyWindowFromGroup;
    m_dispatchers["event"]                          = event;
    m_dispatchers["global"]                         = global;
    m_dispatchers["setprop"]                        = setProp;
    m_dispatchers["forceidle"]                      = forceIdle;

    m_scrollTimer.reset();

    m_longPressTimer = makeShared<CEventLoopTimer>(
        std::nullopt,
        [this](SP<CEventLoopTimer> self, void* data) {
            if (!m_lastLongPressKeybind || g_pSeatManager->m_keyboard.expired())
                return;

            const auto PACTIVEKEEB = g_pSeatManager->m_keyboard.lock();
            if (!PACTIVEKEEB->m_allowBinds)
                return;

            const auto DISPATCHER = g_pKeybindManager->m_dispatchers.find(m_lastLongPressKeybind->handler);

            Log::logger->log(Log::DEBUG, "Long press timeout passed, calling dispatcher.");
            DISPATCHER->second(m_lastLongPressKeybind->arg);
        },
        nullptr);

    m_repeatKeyTimer = makeShared<CEventLoopTimer>(
        std::nullopt,
        [this](SP<CEventLoopTimer> self, void* data) {
            if (m_activeKeybinds.empty() || g_pSeatManager->m_keyboard.expired())
                return;

            const auto PACTIVEKEEB = g_pSeatManager->m_keyboard.lock();
            if (!PACTIVEKEEB->m_allowBinds)
                return;

            for (const auto& k : m_activeKeybinds) {
                const auto DISPATCHER = g_pKeybindManager->m_dispatchers.find(k->handler);

                Log::logger->log(Log::DEBUG, "Keybind repeat triggered, calling dispatcher.");
                DISPATCHER->second(k->arg);
            }

            self->updateTimeout(std::chrono::milliseconds(1000 / m_repeatKeyRate));
        },
        nullptr);

    // null in --verify-config mode
    if (g_pEventLoopManager) {
        g_pEventLoopManager->addTimer(m_longPressTimer);
        g_pEventLoopManager->addTimer(m_repeatKeyTimer);
    }

    static auto P = Event::bus()->m_events.config.reloaded.listen([this] {
        m_activeKeybinds.clear();
        m_lastLongPressKeybind.reset();
        m_pressedSpecialBinds.clear();
    });
}

CKeybindManager::~CKeybindManager() {
    if (m_xkbTranslationState)
        xkb_state_unref(m_xkbTranslationState);
    if (m_longPressTimer && g_pEventLoopManager) {
        g_pEventLoopManager->removeTimer(m_longPressTimer);
        m_longPressTimer.reset();
    }
    if (m_repeatKeyTimer && g_pEventLoopManager) {
        g_pEventLoopManager->removeTimer(m_repeatKeyTimer);
        m_repeatKeyTimer.reset();
    }
}

void CKeybindManager::addKeybind(SKeybind kb) {
    m_keybinds.emplace_back(makeShared<SKeybind>(kb));

    m_activeKeybinds.clear();
    m_lastLongPressKeybind.reset();
}

void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) {
    std::erase_if(m_keybinds, [&mod, &key](const auto& el) { return el->modmask == mod && el->key == key.key && el->keycode == key.keycode && el->catchAll == key.catchAll; });

    m_activeKeybinds.clear();
    m_lastLongPressKeybind.reset();
}

uint32_t CKeybindManager::stringToModMask(std::string mods) {
    uint32_t modMask = 0;
    std::ranges::transform(mods, mods.begin(), ::toupper);
    if (mods.contains("SHIFT"))
        modMask |= HL_MODIFIER_SHIFT;
    if (mods.contains("CAPS"))
        modMask |= HL_MODIFIER_CAPS;
    if (mods.contains("CTRL") || mods.contains("CONTROL"))
        modMask |= HL_MODIFIER_CTRL;
    if (mods.contains("ALT") || mods.contains("MOD1"))
        modMask |= HL_MODIFIER_ALT;
    if (mods.contains("MOD2"))
        modMask |= HL_MODIFIER_MOD2;
    if (mods.contains("MOD3"))
        modMask |= HL_MODIFIER_MOD3;
    if (mods.contains("SUPER") || mods.contains("WIN") || mods.contains("LOGO") || mods.contains("MOD4") || mods.contains("META"))
        modMask |= HL_MODIFIER_META;
    if (mods.contains("MOD5"))
        modMask |= HL_MODIFIER_MOD5;

    return modMask;
}

uint32_t CKeybindManager::keycodeToModifier(xkb_keycode_t keycode) {
    if (keycode == 0)
        return 0;

    switch (keycode - 8) {
        case KEY_LEFTMETA: return HL_MODIFIER_META;
        case KEY_RIGHTMETA: return HL_MODIFIER_META;
        case KEY_LEFTSHIFT: return HL_MODIFIER_SHIFT;
        case KEY_RIGHTSHIFT: return HL_MODIFIER_SHIFT;
        case KEY_LEFTCTRL: return HL_MODIFIER_CTRL;
        case KEY_RIGHTCTRL: return HL_MODIFIER_CTRL;
        case KEY_LEFTALT: return HL_MODIFIER_ALT;
        case KEY_RIGHTALT: return HL_MODIFIER_ALT;
        case KEY_CAPSLOCK: return HL_MODIFIER_CAPS;
        case KEY_NUMLOCK: return HL_MODIFIER_MOD2;
        default: return 0;
    }
}

void CKeybindManager::updateXKBTranslationState() {
    if (m_xkbTranslationState) {
        xkb_state_unref(m_xkbTranslationState);

        m_xkbTranslationState = nullptr;
    }

    static auto       PFILEPATH = CConfigValue<std::string>("input:kb_file");
    static auto       PRULES    = CConfigValue<std::string>("input:kb_rules");
    static auto       PMODEL    = CConfigValue<std::string>("input:kb_model");
    static auto       PLAYOUT   = CConfigValue<std::string>("input:kb_layout");
    static auto       PVARIANT  = CConfigValue<std::string>("input:kb_variant");
    static auto       POPTIONS  = CConfigValue<std::string>("input:kb_options");

    const std::string FILEPATH = std::string{*PFILEPATH} == STRVAL_EMPTY ? "" : *PFILEPATH;
    const std::string RULES    = std::string{*PRULES} == STRVAL_EMPTY ? "" : *PRULES;
    const std::string MODEL    = std::string{*PMODEL} == STRVAL_EMPTY ? "" : *PMODEL;
    const std::string LAYOUT   = std::string{*PLAYOUT} == STRVAL_EMPTY ? "" : *PLAYOUT;
    const std::string VARIANT  = std::string{*PVARIANT} == STRVAL_EMPTY ? "" : *PVARIANT;
    const std::string OPTIONS  = std::string{*POPTIONS} == STRVAL_EMPTY ? "" : *POPTIONS;

    xkb_rule_names    rules      = {.rules = RULES.c_str(), .model = MODEL.c_str(), .layout = LAYOUT.c_str(), .variant = VARIANT.c_str(), .options = OPTIONS.c_str()};
    const auto        PCONTEXT   = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
    FILE* const       KEYMAPFILE = FILEPATH.empty() ? nullptr : fopen(absolutePath(FILEPATH, Config::mgr()->currentConfigPath()).c_str(), "r");

    auto              PKEYMAP = KEYMAPFILE ? xkb_keymap_new_from_file(PCONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_COMPILE_NO_FLAGS) :
                                             xkb_keymap_new_from_names2(PCONTEXT, &rules, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_COMPILE_NO_FLAGS);
    if (KEYMAPFILE)
        fclose(KEYMAPFILE);

    if (!PKEYMAP) {
        ErrorOverlay::overlay()->queueCreate("[Runtime Error] Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT +
                                                 ", options: " + OPTIONS + ", layout: " + LAYOUT + " )",
                                             ErrorOverlay::Colors::ERROR);

        Log::logger->log(Log::ERR, "[XKBTranslationState] Keyboard layout {} with variant {} (rules: {}, model: {}, options: {}) couldn't have been loaded.", rules.layout,
                         rules.variant, rules.rules, rules.model, rules.options);
        memset(&rules, 0, sizeof(rules));

        PKEYMAP = xkb_keymap_new_from_names2(PCONTEXT, &rules, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_COMPILE_NO_FLAGS);
    }

    xkb_context_unref(PCONTEXT);
    m_xkbTranslationState = xkb_state_new(PKEYMAP);
    xkb_keymap_unref(PKEYMAP);
}

bool CKeybindManager::ensureMouseBindState() {
    if (!g_layoutManager->dragController()->target())
        return false;

    if (g_layoutManager->dragController()->target()) {
        changeMouseBindMode(MBIND_INVALID);
        return true;
    }

    return false;
}

static void updateRelativeCursorCoords() {
    static auto PNOWARPS = CConfigValue<Hyprlang::INT>("cursor:no_warps");

    if (*PNOWARPS)
        return;

    if (Desktop::focusState()->window())
        Desktop::focusState()->window()->m_relativeCursorCoordsOnLastWarp = g_pInputManager->getMouseCoordsInternal() - Desktop::focusState()->window()->m_position;
}

bool CKeybindManager::tryMoveFocusToMonitor(PHLMONITOR monitor) {
    if (!monitor)
        return false;

    const auto LASTMONITOR = Desktop::focusState()->monitor();
    if (!LASTMONITOR)
        return false;
    if (LASTMONITOR == monitor) {
        Log::logger->log(Log::DEBUG, "Tried to move to active monitor");
        return false;
    }

    static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
    static auto PNOWARPS     = CConfigValue<Hyprlang::INT>("cursor:no_warps");

    const auto  PWORKSPACE        = Desktop::focusState()->monitor()->m_activeWorkspace;
    const auto  PNEWMAINWORKSPACE = monitor->m_activeWorkspace;

    g_pInputManager->unconstrainMouse();

    const auto PNEWWORKSPACE = monitor->m_activeSpecialWorkspace ? monitor->m_activeSpecialWorkspace : PNEWMAINWORKSPACE;

    const auto PNEWWINDOW = PNEWWORKSPACE->getLastFocusedWindow();
    if (PNEWWINDOW) {
        updateRelativeCursorCoords();
        Desktop::focusState()->fullWindowFocus(PNEWWINDOW, Desktop::FOCUS_REASON_KEYBIND);
        PNEWWINDOW->warpCursor();

        if (*PNOWARPS == 0 || *PFOLLOWMOUSE < 2) {
            g_pInputManager->m_forcedFocus = PNEWWINDOW;
            g_pInputManager->simulateMouseMovement();
            g_pInputManager->m_forcedFocus.reset();
        }
    } else {
        Desktop::focusState()->rawWindowFocus(nullptr, Desktop::FOCUS_REASON_KEYBIND);
        g_pCompositor->warpCursorTo(monitor->middle());
    }
    Desktop::focusState()->rawMonitorFocus(monitor);

    return true;
}

void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool forceFSCycle) {
    static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
    static auto PNOWARPS     = CConfigValue<Hyprlang::INT>("cursor:no_warps");

    const auto  PLASTWINDOW = Desktop::focusState()->window();

    if (PWINDOWTOCHANGETO == PLASTWINDOW || !PWINDOWTOCHANGETO)
        return;

    // remove constraints
    g_pInputManager->unconstrainMouse();

    if (PLASTWINDOW && PLASTWINDOW->m_workspace == PWINDOWTOCHANGETO->m_workspace && PLASTWINDOW->isFullscreen())
        Desktop::focusState()->fullWindowFocus(PWINDOWTOCHANGETO, Desktop::FOCUS_REASON_KEYBIND, nullptr, forceFSCycle);
    else {
        updateRelativeCursorCoords();
        Desktop::focusState()->fullWindowFocus(PWINDOWTOCHANGETO, Desktop::FOCUS_REASON_KEYBIND, nullptr, forceFSCycle);
        PWINDOWTOCHANGETO->warpCursor();

        // Move mouse focus to the new window if required by current follow_mouse and warp modes
        if (*PNOWARPS == 0 || *PFOLLOWMOUSE < 2) {
            g_pInputManager->m_forcedFocus = PWINDOWTOCHANGETO;
            g_pInputManager->simulateMouseMovement();
            g_pInputManager->m_forcedFocus.reset();
        }

        if (PLASTWINDOW && PLASTWINDOW->m_monitor != PWINDOWTOCHANGETO->m_monitor) {
            // event
            const auto PNEWMON = PWINDOWTOCHANGETO->m_monitor.lock();

            Desktop::focusState()->rawMonitorFocus(PNEWMON);
        }
    }
};

bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) {
    if (!g_pCompositor->m_sessionActive || g_pCompositor->m_unsafeState) {
        m_pressedKeys.clear();
        return true;
    }

    if (!pKeyboard->m_allowBinds)
        return true;

    if (!m_xkbTranslationState) {
        Log::logger->log(Log::ERR, "BUG THIS: m_pXKBTranslationState nullptr!");
        updateXKBTranslationState();

        if (!m_xkbTranslationState)
            return true;
    }

    auto               e = std::any_cast<IKeyboard::SKeyEvent>(event);

    const auto         KEYCODE = e.keycode + 8; // Because to xkbcommon it's +8 from libinput

    const xkb_keysym_t keysym         = xkb_state_key_get_one_sym(pKeyboard->m_resolveBindsBySym ? pKeyboard->m_xkbSymState : m_xkbTranslationState, KEYCODE);
    const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->m_xkbState, KEYCODE);

    if (keysym == XKB_KEY_Escape || internalKeysym == XKB_KEY_Escape)
        PROTO::data->abortDndIfPresent();

    // handleInternalKeybinds returns true when the key should be suppressed,
    // while this function returns true when the key event should be sent
    if (handleInternalKeybinds(internalKeysym))
        return false;

    const auto MODS = g_pInputManager->getModsFromAllKBs();

    m_timeLastMs    = e.timeMs;
    m_lastCode      = KEYCODE;
    m_lastMouseCode = 0;

    bool       mouseBindWasActive = ensureMouseBindState();

    const auto KEY = SPressedKeyWithMods{
        .keysym             = keysym,
        .keycode            = KEYCODE,
        .modmaskAtPressTime = MODS,
        .sent               = true,
        .submapAtPress      = m_currentSelectedSubmap,
        .mousePosAtPress    = g_pInputManager->getMouseCoordsInternal(),
    };

    m_activeKeybinds.clear();

    m_lastLongPressKeybind.reset();

    bool suppressEvent = false;
    if (e.state == WL_KEYBOARD_KEY_STATE_PRESSED) {

        m_pressedKeys.push_back(KEY);

        suppressEvent = !handleKeybinds(MODS, KEY, true, pKeyboard, pKeyboard).passEvent;

        if (suppressEvent)
            shadowKeybinds(keysym, KEYCODE);

        m_pressedKeys.back().sent = !suppressEvent;
    } else { // key release

        bool foundInPressedKeys = false;
        for (auto it = m_pressedKeys.begin(); it != m_pressedKeys.end();) {
            if (it->keycode == KEYCODE) {
                handleKeybinds(MODS, *it, false, pKeyboard, pKeyboard);
                foundInPressedKeys = true;
                suppressEvent      = !it->sent;
                it                 = m_pressedKeys.erase(it);
            } else {
                ++it;
            }
        }
        if (!foundInPressedKeys) {
            Log::logger->log(Log::ERR, "BUG THIS: key not found in m_dPressedKeys");
            // fallback with wrong `KEY.modmaskAtPressTime`, this can be buggy
            suppressEvent = !handleKeybinds(MODS, KEY, false, pKeyboard, pKeyboard).passEvent;
        }

        shadowKeybinds();
    }

    return !suppressEvent && !mouseBindWasActive;
}

bool CKeybindManager::onAxisEvent(const IPointer::SAxisEvent& e, SP<IPointer> pointer) {
    const auto  MODS = g_pInputManager->getModsFromAllKBs();

    static auto PDELAY = CConfigValue<Hyprlang::INT>("binds:scroll_event_delay");

    if (m_scrollTimer.getMillis() < *PDELAY)
        return true; // timer hasn't passed yet!

    m_scrollTimer.reset();

    m_activeKeybinds.clear();

    bool found = false;
    if (e.source == WL_POINTER_AXIS_SOURCE_WHEEL && e.axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
        if (e.delta < 0)
            found = !handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_down"}, true, nullptr, pointer).passEvent;
        else
            found = !handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_up"}, true, nullptr, pointer).passEvent;
    } else if (e.source == WL_POINTER_AXIS_SOURCE_WHEEL && e.axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
        if (e.delta < 0)
            found = !handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_left"}, true, nullptr, pointer).passEvent;
        else
            found = !handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_right"}, true, nullptr, pointer).passEvent;
    }

    if (found)
        shadowKeybinds();

    return !found;
}

bool CKeybindManager::onMouseEvent(const IPointer::SButtonEvent& e, SP<IPointer> mouse) {
    const auto MODS = g_pInputManager->getModsFromAllKBs();

    bool       suppressEvent = false;

    m_lastMouseCode = e.button;
    m_lastCode      = 0;
    m_timeLastMs    = e.timeMs;

    bool       mouseBindWasActive = ensureMouseBindState();

    const auto KEY_NAME = "mouse:" + std::to_string(e.button);

    const auto KEY = SPressedKeyWithMods{
        .keyName            = KEY_NAME,
        .modmaskAtPressTime = MODS,
        .mousePosAtPress    = g_pInputManager->getMouseCoordsInternal(),
    };

    m_activeKeybinds.clear();

    if (e.state == WL_POINTER_BUTTON_STATE_PRESSED) {
        m_pressedKeys.push_back(KEY);

        suppressEvent = !handleKeybinds(MODS, KEY, true, nullptr, mouse).passEvent;

        if (suppressEvent)
            shadowKeybinds();

        m_pressedKeys.back().sent = !suppressEvent;
    } else {
        bool foundInPressedKeys = false;
        for (auto it = m_pressedKeys.begin(); it != m_pressedKeys.end();) {
            if (it->keyName == KEY_NAME) {
                suppressEvent      = !handleKeybinds(MODS, *it, false, nullptr, mouse).passEvent;
                foundInPressedKeys = true;
                suppressEvent      = !it->sent;
                it                 = m_pressedKeys.erase(it);
            } else {
                ++it;
            }
        }
        if (!foundInPressedKeys) {
            Log::logger->log(Log::ERR, "BUG THIS: key not found in m_dPressedKeys (2)");
            // fallback with wrong `KEY.modmaskAtPressTime`, this can be buggy
            suppressEvent = !handleKeybinds(MODS, KEY, false, nullptr, mouse).passEvent;
        }

        shadowKeybinds();
    }

    return !suppressEvent && !mouseBindWasActive;
}

void CKeybindManager::resizeWithBorder(const IPointer::SButtonEvent& e) {
    changeMouseBindMode(e.state == WL_POINTER_BUTTON_STATE_PRESSED ? MBIND_RESIZE : MBIND_INVALID);
}

void CKeybindManager::onSwitchEvent(const std::string& switchName) {
    handleKeybinds(0, SPressedKeyWithMods{.keyName = "switch:" + switchName}, true, nullptr, nullptr);
}

void CKeybindManager::onSwitchOnEvent(const std::string& switchName) {
    handleKeybinds(0, SPressedKeyWithMods{.keyName = "switch:on:" + switchName}, true, nullptr, nullptr);
}

void CKeybindManager::onSwitchOffEvent(const std::string& switchName) {
    handleKeybinds(0, SPressedKeyWithMods{.keyName = "switch:off:" + switchName}, true, nullptr, nullptr);
}

eMultiKeyCase CKeybindManager::mkKeysymSetMatches(const std::set<xkb_keysym_t> keybindKeysyms, const std::set<xkb_keysym_t> pressedKeysyms) {
    // Returns whether two sets of keysyms are equal, partially equal, or not
    // matching. (Partially matching means that pressed is a subset of bound)

    std::set<xkb_keysym_t> boundKeysNotPressed;
    std::set<xkb_keysym_t> pressedKeysNotBound;

    std::ranges::set_difference(keybindKeysyms, pressedKeysyms, std::inserter(boundKeysNotPressed, boundKeysNotPressed.begin()));
    std::ranges::set_difference(pressedKeysyms, keybindKeysyms, std::inserter(pressedKeysNotBound, pressedKeysNotBound.begin()));

    if (boundKeysNotPressed.empty() && pressedKeysNotBound.empty())
        return MK_FULL_MATCH;

    if (!boundKeysNotPressed.empty() && pressedKeysNotBound.empty())
        return MK_PARTIAL_MATCH;

    return MK_NO_MATCH;
}

eMultiKeyCase CKeybindManager::mkBindMatches(const SP<SKeybind> keybind) {
    if (mkKeysymSetMatches(keybind->sMkMods, m_mkMods) != MK_FULL_MATCH)
        return MK_NO_MATCH;

    return mkKeysymSetMatches(keybind->sMkKeys, m_mkKeys);
}

SSubmap CKeybindManager::getCurrentSubmap() {
    return m_currentSelectedSubmap;
}

SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWithMods& key, bool pressed, SP<IKeyboard> keyboard, SP<IHID> device) {
    static auto     PDISABLEINHIBIT = CConfigValue<Hyprlang::INT>("binds:disable_keybind_grabbing");
    static auto     PDRAGTHRESHOLD  = CConfigValue<Hyprlang::INT>("binds:drag_threshold");

    bool            found = false;
    SDispatchResult res;

    // Skip keysym tracking for events with no keysym (e.g., scroll wheel events).
    // Scroll events have keysym=0 and are always "pressed" (never released),
    // so without this check, 0 gets inserted into m_mkKeys and never removed,
    // breaking multi-key binds (binds flag 's'). See issue #8699.
    if (key.keysym != 0) {
        if (pressed) {
            if (keycodeToModifier(key.keycode))
                m_mkMods.insert(key.keysym);
            else
                m_mkKeys.insert(key.keysym);
        } else {
            if (keycodeToModifier(key.keycode))
                m_mkMods.erase(key.keysym);
            else
                m_mkKeys.erase(key.keysym);
        }
    }

    for (auto& k : m_keybinds) {
        const bool SPECIALDISPATCHER = k->handler == "global" || k->handler == "pass" || k->handler == "sendshortcut" || k->handler == "mouse";
        const bool SPECIALTRIGGERED  = std::ranges::find_if(m_pressedSpecialBinds, [&](const auto& other) { return other == k; }) != m_pressedSpecialBinds.end();
        const bool IGNORECONDITIONS =
            SPECIALDISPATCHER && !pressed && SPECIALTRIGGERED; // ignore mods. Pass, global dispatchers should be released immediately once the key is released.

        if (!k->dontInhibit && !*PDISABLEINHIBIT && PROTO::shortcutsInhibit->isInhibited())
            continue;

        if (!k->locked && g_pSessionLockManager->isSessionLocked())
            continue;

        if (!IGNORECONDITIONS && ((modmask != k->modmask && !k->ignoreMods) || (k->submap != m_currentSelectedSubmap && !k->submapUniversal) || k->shadowed))
            continue;

        if (device) {
            if (k->deviceInclusive ^ k->devices.contains(device->m_hlName))
                continue;
        }

        if (k->multiKey) {
            switch (mkBindMatches(k)) {
                case MK_NO_MATCH: continue;
                case MK_PARTIAL_MATCH: found = true; continue;
                case MK_FULL_MATCH: found = true;
            }
        } else if (!key.keyName.empty()) {
            if (key.keyName != k->key)
                continue;
        } else if (k->keycode != 0) {
            if (key.keycode != k->keycode)
                continue;
        } else if (k->catchAll) {
            if (found || key.submapAtPress != m_currentSelectedSubmap)
                continue;
        } else {
            // in this case, we only have the keysym to go off of for this keybind, and it's invalid
            // since there might be something like keycode to match with other keybinds, try the next
            if (key.keysym == XKB_KEY_NoSymbol)
                continue;

            // oMg such performance hit!!11!
            // this little maneouver is gonna cost us 4µs
            const auto KBKEY      = xkb_keysym_from_name(k->key.c_str(), XKB_KEYSYM_NO_FLAGS);
            const auto KBKEYLOWER = xkb_keysym_from_name(k->key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);

            if (KBKEY == XKB_KEY_NoSymbol && KBKEYLOWER == XKB_KEY_NoSymbol) {
                // Keysym failed to resolve from the key name of the currently iterated bind.
                // This happens for names such as `switch:off:Lid Switch` as well as some keys
                // (such as yen and ro).
                //
                // We can't let compare a 0-value with currently pressed key below,
                // because if this key also have no keysym (i.e. key.keysym == 0) it will incorrectly trigger the
                // currently iterated bind. That's confirmed to be happening with yen and ro keys.
                continue;
            }

            if (key.keysym != KBKEY && key.keysym != KBKEYLOWER)
                continue;
        }

        if (pressed && k->release && !SPECIALDISPATCHER) {
            if (k->nonConsuming)
                continue;

            found = true; // suppress the event
            continue;
        }

        if (!pressed) {
            // Require mods to be matching when the key was first pressed.
            if (key.modmaskAtPressTime != modmask && !k->ignoreMods) {
                // Handle properly `bindr` where a key is itself a bind mod for example:
                // "bindr = SUPER, SUPER_L, exec, $launcher".
                // This needs to be handled separately for the above case, because `key.modmaskAtPressTime` is set
                // from currently pressed keys as programs see them, but it doesn't yet include the currently
                // pressed mod key, which is still being handled internally.
                if (keycodeToModifier(key.keycode) == key.modmaskAtPressTime)
                    continue;

            } else if (!k->release && !SPECIALDISPATCHER) {
                if (k->nonConsuming)
                    continue;

                found = true; // suppress the event
                continue;
            }

            // Require mouse to stay inside drag_threshold for clicks, outside for drags
            // Check if either a mouse bind has triggered or currently over the threshold (maybe there is no mouse bind on the same key)
            const auto THRESHOLDREACHED = key.mousePosAtPress.distanceSq(g_pInputManager->getMouseCoordsInternal()) > std::pow(*PDRAGTHRESHOLD, 2);
            if (k->click && (g_layoutManager->dragController()->dragThresholdReached() || THRESHOLDREACHED))
                continue;
            else if (k->drag && !g_layoutManager->dragController()->dragThresholdReached() && !THRESHOLDREACHED)
                continue;
        }

        if (pressed && k->longPress) {
            const auto PACTIVEKEEB = g_pSeatManager->m_keyboard.lock();

            m_longPressTimer->updateTimeout(std::chrono::milliseconds(PACTIVEKEEB->m_repeatDelay));
            m_lastLongPressKeybind = k;

            continue;
        }

        const auto DISPATCHER = m_dispatchers.find(k->mouse ? "mouse" : k->handler);

        if (SPECIALTRIGGERED && !pressed)
            std::erase_if(m_pressedSpecialBinds, [&](const auto& other) { return other == k; });
        else if (SPECIALDISPATCHER && pressed)
            m_pressedSpecialBinds.emplace_back(k);

        // Should never happen, as we check in the ConfigManager, but oh well
        if (DISPATCHER == m_dispatchers.end()) {
            Log::logger->log(Log::ERR, "Invalid handler in a keybind! (handler {} does not exist)", k->handler);
        } else {
            // call the dispatcher
            Log::logger->log(Log::DEBUG, "Keybind triggered, calling dispatcher ({}, {}, {}, {})", modmask, key.keyName, key.keysym, DISPATCHER->first);

            m_passPressed = sc<int>(pressed);

            // if the dispatchers says to pass event then we will
            if (k->handler == "mouse")
                res = DISPATCHER->second((pressed ? "1" : "0") + k->arg);
            else
                res = DISPATCHER->second(k->arg);

            m_passPressed = -1;

            if (k->handler == "submap") {
                found = true; // don't process keybinds on submap change.
                break;
            }
            if (k->handler != "submap" && !k->submap.reset.empty())
                setSubmap(k->submap.reset);
        }

        if (pressed && k->repeat) {
            const auto KEEB = keyboard ? keyboard : g_pSeatManager->m_keyboard.lock();
            m_repeatKeyRate = KEEB->m_repeatRate;

            m_activeKeybinds.emplace_back(k);
            m_repeatKeyTimer->updateTimeout(std::chrono::milliseconds(KEEB->m_repeatDelay));
        }

        if (!k->nonConsuming)
            found = true;
    }

    g_layoutManager->dragController()->resetDragThresholdReached();

    // if keybind wasn't found (or dispatcher said to) then pass event
    res.passEvent |= !found;

    if (!found && !*PDISABLEINHIBIT && PROTO::shortcutsInhibit->isInhibited()) {
        Log::logger->log(Log::DEBUG, "Keybind handling is disabled due to an inhibitor");

        res.success = false;
        if (res.error.empty())
            res.error = "Keybind handling is disabled due to an inhibitor";
    }

    return res;
}

void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const uint32_t doesntHaveCode) {
    // shadow disables keybinds after one has been triggered

    for (auto& k : m_keybinds) {

        bool shadow = false;

        if (k->handler == "global" || k->transparent)
            continue; // can't be shadowed

        if (k->multiKey && (mkBindMatches(k) == MK_FULL_MATCH))
            shadow = true;
        else {
            const auto KBKEY      = xkb_keysym_from_name(k->key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
            const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY);

            for (auto const& pk : m_pressedKeys) {
                if ((pk.keysym != 0 && (pk.keysym == KBKEY || pk.keysym == KBKEYUPPER))) {
                    shadow = true;

                    if (pk.keysym == doesntHave && doesntHave != 0) {
                        shadow = false;
                        break;
                    }
                }

                if (pk.keycode != 0 && pk.keycode == k->keycode) {
                    shadow = true;

                    if (pk.keycode == doesntHaveCode && doesntHaveCode != 0) {
                        shadow = false;
                        break;
                    }
                }
            }
        }

        k->shadowed = shadow;
    }
}

bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
    // Handles the CTRL+ALT+FX TTY keybinds
    if (keysym < XKB_KEY_XF86Switch_VT_1 || keysym > XKB_KEY_XF86Switch_VT_12)
        return false;

    // beyond this point, return true to not handle anything else.
    // we'll avoid printing shit to active windows.

    if (g_pCompositor->m_aqBackend->hasSession()) {
        const unsigned int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1;

        const auto         CURRENT_TTY = g_pCompositor->getVTNr();

        if (!CURRENT_TTY.has_value() || *CURRENT_TTY == TTY)
            return true;

        Log::logger->log(Log::DEBUG, "Switching from VT {} to VT {}", *CURRENT_TTY, TTY);

        g_pCompositor->m_aqBackend->session->switchVT(TTY);
    }

    return true;
}

bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) {
    if (handleVT(keysym))
        return true;

    // handle ESC while in kill mode
    if (g_pInputManager->getClickMode() == CLICKMODE_KILL) {
        const auto KBKEY = xkb_keysym_from_name("ESCAPE", XKB_KEYSYM_CASE_INSENSITIVE);

        if (keysym == KBKEY) {
            g_pInputManager->setClickMode(CLICKMODE_DEFAULT);
            return true;
        }
    }

    return false;
}

// Dispatchers
SDispatchResult CKeybindManager::spawn(std::string args) {
    const auto PROC = Config::Supplementary::executor()->spawn(args);
    if (!PROC.has_value())
        return {.success = false, .error = std::format("Failed to start process. No closing bracket in exec rule. {}", args)};
    return {.success = PROC.value() > 0, .error = std::format("Failed to start process {}", args)};
}

SDispatchResult CKeybindManager::spawnRaw(std::string args) {
    const auto PROC = Config::Supplementary::executor()->spawnRaw(args);
    return {.success = PROC && *PROC > 0, .error = std::format("Failed to start process {}", args)};
}

SDispatchResult CKeybindManager::killActive(std::string args) {
    const auto PWINDOW = Desktop::focusState()->window();

    if (!PWINDOW) {
        Log::logger->log(Log::ERR, "killActive: no window found");
        return {.success = false, .error = "killActive: no window found"};
    }

    kill(PWINDOW->getPID(), SIGKILL);

    return {};
}

SDispatchResult CKeybindManager::closeActive(std::string args) {
    if (Desktop::focusState()->window() && Desktop::focusState()->window()->m_closeableSince > Time::steadyNow())
        return {.success = false, .error = "can't close window, it's not closeable yet (noclosefor)"};

    g_pCompositor->closeWindow(Desktop::focusState()->window());

    return {};
}

SDispatchResult CKeybindManager::closeWindow(std::string args) {
    const auto PWINDOW = g_pCompositor->getWindowByRegex(args);

    if (!PWINDOW) {
        Log::logger->log(Log::ERR, "closeWindow: no window found");
        return {.success = false, .error = "closeWindow: no window found"};
    }

    if (PWINDOW->m_closeableSince > Time::steadyNow())
        return {.success = false, .error = "can't close window, it's not closeable yet (noclosefor)"};

    g_pCompositor->closeWindow(PWINDOW);

    return {};
}

SDispatchResult CKeybindManager::killWindow(std::string args) {
    const auto PWINDOW = g_pCompositor->getWindowByRegex(args);

    if (!PWINDOW) {
        Log::logger->log(Log::ERR, "killWindow: no window found");
        return {.success = false, .error = "killWindow: no window found"};
    }

    kill(PWINDOW->getPID(), SIGKILL);

    return {};
}

SDispatchResult CKeybindManager::signalActive(std::string args) {
    if (!isNumber(args))
        return {.success = false, .error = "signalActive: signal has to be int"};

    try {
        const auto SIGNALNUM = std::stoi(args);
        if (SIGNALNUM < 1 || SIGNALNUM > 31) {
            Log::logger->log(Log::ERR, "signalActive: invalid signal number {}", SIGNALNUM);
            return {.success = false, .error = std::format("signalActive: invalid signal number {}", SIGNALNUM)};
        }
        kill(Desktop::focusState()->window()->getPID(), SIGNALNUM);
    } catch (const std::exception& e) {
        Log::logger->log(Log::ERR, "signalActive: invalid signal format \"{}\"", args);
        return {.success = false, .error = std::format("signalActive: invalid signal format \"{}\"", args)};
    }

    kill(Desktop::focusState()->window()->getPID(), std::stoi(args));

    return {};
}

SDispatchResult CKeybindManager::signalWindow(std::string args) {
    const auto WINDOWREGEX = args.substr(0, args.find_first_of(','));
    const auto SIGNAL      = args.substr(args.find_first_of(',') + 1);

    const auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX);

    if (!PWINDOW) {
        Log::logger->log(Log::ERR, "signalWindow: no window");
        return {.success = false, .error = "signalWindow: no window"};
    }

    if (!std::ranges::all_of(SIGNAL, ::isdigit))
        return {.success = false, .error = "signalWindow: signal has to be int"};

    try {
        const auto SIGNALNUM = std::stoi(SIGNAL);
        if (SIGNALNUM < 1 || SIGNALNUM > 31) {
            Log::logger->log(Log::ERR, "signalWindow: invalid signal number {}", SIGNALNUM);
            return {.success = false, .error = std::format("signalWindow: invalid signal number {}", SIGNALNUM)};
        }
        kill(PWINDOW->getPID(), SIGNALNUM);
    } catch (const std::exception& e) {
        Log::logger->log(Log::ERR, "signalWindow: invalid signal format \"{}\"", SIGNAL);
        return {.success = false, .error = std::format("signalWindow: invalid signal format \"{}\"", SIGNAL)};
    }

    return {};
}

void CKeybindManager::clearKeybinds() {
    m_keybinds.clear();
}

static SDispatchResult toggleActiveFloatingCore(std::string args, std::optional<bool> floatState) {
    PHLWINDOW PWINDOW = nullptr;

    if (args != "active" && args.length() > 1)
        PWINDOW = g_pCompositor->getWindowByRegex(args);
    else
        PWINDOW = Desktop::focusState()->window();

    if (!PWINDOW)
        return {.success = false, .error = "Window not found"};

    if (floatState.has_value() && floatState == PWINDOW->m_isFloating)
        return {};

    // remove drag status
    if (g_layoutManager->dragController()->target())
        CKeybindManager::changeMouseBindMode(MBIND_INVALID);

    g_layoutManager->changeFloatingMode(PWINDOW->layoutTarget());

    if (PWINDOW->m_isFloating)
        g_pCompositor->changeWindowZOrder(PWINDOW, true);

    if (PWINDOW->m_workspace) {
        PWINDOW->m_workspace->updateWindows();
        PWINDOW->m_workspace->updateWindowData();
    }

    g_pCompositor->updateAllWindowsAnimatedDecorationValues();

    return {};
}

SDispatchResult CKeybindManager::toggleActiveFloating(std::string args) {
    return toggleActiveFloatingCore(args, std::nullopt);
}

SDispatchResult CKeybindManager::setActiveFloating(std::string args) {
    return toggleActiveFloatingCore(args, true);
}

SDispatchResult CKeybindManager::setActiveTiled(std::string args) {
    return toggleActiveFloatingCore(args, false);
}

SDispatchResult CKeybindManager::centerWindow(std::string args) {
    const auto PWINDOW = Desktop::focusState()->window();

    if (!PWINDOW || !PWINDOW->m_isFloating || PWINDOW->isFullscreen())
        return {.success = false, .error = "No floating window found"};

    const auto PMONITOR = PWINDOW->m_monitor.lock();

    PWINDOW->layoutTarget()->setPositionGlobal(CBox{PMONITOR->logicalBoxMinusReserved().middle() - PWINDOW->m_realSize->goal() / 2.F, PWINDOW->layoutTarget()->position().size()});

    return {};
}

SDispatchResult CKeybindManager::toggleActivePseudo(std::string args) {
    PHLWINDOW PWINDOW = nullptr;

    if (args != "active" && args.length() > 1)
        PWINDOW = g_pCompositor->getWindowByRegex(args);
    else
        PWINDOW = Desktop::focusState()->window();

    if (!PWINDOW)
        return {.success = false, .error = "Window not found"};

    PWINDOW->layoutTarget()->setPseudo(!PWINDOW->layoutTarget()->isPseudo());

    return {};
}

static SWorkspaceIDName getWorkspaceToChangeFromArgs(std::string args, PHLWORKSPACE PCURRENTWORKSPACE, PHLMONITORREF PMONITOR) {
    if (!args.starts_with("previous")) {
        return getWorkspaceIDNameFromString(args);
    }

    const bool             PER_MON = args.contains("_per_monitor");
    const SWorkspaceIDName PPREVWS = PER_MON ? Desktop::History::workspaceTracker()->previousWorkspaceIDName(PCURRENTWORKSPACE, PMONITOR.lock()) :
                                               Desktop::History::workspaceTracker()->previousWorkspaceIDName(PCURRENTWORKSPACE);
    // Do nothing if there's no previous workspace, otherwise switch to it.
    if (PPREVWS.id == -1 || PPREVWS.id == PCURRENTWORKSPACE->m_id) {
        Log::logger->log(Log::DEBUG, "No previous workspace to change to");
        return {.id = WORKSPACE_NOT_CHANGED};
    }

    if (const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(PPREVWS.id); PWORKSPACETOCHANGETO) {
        return {.id = PWORKSPACETOCHANGETO->m_id, .name = PWORKSPACETOCHANGETO->m_name};
    }

    return {.id = PPREVWS.id, .name = PPREVWS.name.empty() ? std::to_string(PPREVWS.id) : PPREVWS.name};
}

SDispatchResult CKeybindManager::changeworkspace(std::string args) {
    // Workspace_back_and_forth being enabled means that an attempt to switch to
    // the current workspace will instead switch to the previous.
    static auto PBACKANDFORTH                 = CConfigValue<Hyprlang::INT>("binds:workspace_back_and_forth");
    static auto PWORKSPACECENTERON            = CConfigValue<Hyprlang::INT>("binds:workspace_center_on");
    static auto PHIDESPECIALONWORKSPACECHANGE = CConfigValue<Hyprlang::INT>("binds:hide_special_on_workspace_change");

    const auto  PMONITOR = Desktop::focusState()->monitor();

    if (!PMONITOR)
        return {.success = false, .error = "Last monitor not found"};

    const auto PCURRENTWORKSPACE = PMONITOR->m_activeWorkspace;
    const bool EXPLICITPREVIOUS  = args.contains("previous");

    const auto& [workspaceToChangeTo, workspaceName, isAutoID] = getWorkspaceToChangeFromArgs(args, PCURRENTWORKSPACE, PMONITOR);
    if (workspaceToChangeTo == WORKSPACE_INVALID) {
        Log::logger->log(Log::ERR, "Error in changeworkspace, invalid value");
        return {.success = false, .error = "Error in changeworkspace, invalid value"};
    }

    if (workspaceToChangeTo == WORKSPACE_NOT_CHANGED)
        return {};

    const SWorkspaceIDName PPREVWS = args.contains("_per_monitor") ? Desktop::History::workspaceTracker()->previousWorkspaceIDName(PCURRENTWORKSPACE, PMONITOR) :
                                                                     Desktop::History::workspaceTracker()->previousWorkspaceIDName(PCURRENTWORKSPACE);

    const bool             BISWORKSPACECURRENT = workspaceToChangeTo == PCURRENTWORKSPACE->m_id;
    if (BISWORKSPACECURRENT && (!(*PBACKANDFORTH || EXPLICITPREVIOUS) || PPREVWS.id == -1)) {
        if (*PHIDESPECIALONWORKSPACECHANGE)
            PMONITOR->setSpecialWorkspace(nullptr);

        return {.success = false, .error = "Previous workspace doesn't exist"};
    }

    g_pInputManager->unconstrainMouse();
    g_pInputManager->m_emptyFocusCursorSet = false;

    auto pWorkspaceToChangeTo = g_pCompositor->getWorkspaceByID(BISWORKSPACECURRENT ? PPREVWS.id : workspaceToChangeTo);
    if (!pWorkspaceToChangeTo)
        pWorkspaceToChangeTo =
            g_pCompositor->createNewWorkspace(BISWORKSPACECURRENT ? PPREVWS.id : workspaceToChangeTo, PMONITOR->m_id, BISWORKSPACECURRENT ? PPREVWS.name : workspaceName);

    if (!BISWORKSPACECURRENT && pWorkspaceToChangeTo->m_isSpecialWorkspace) {
        PMONITOR->setSpecialWorkspace(pWorkspaceToChangeTo);
        g_pInputManager->simulateMouseMovement();
        return {};
    }

    g_pInputManager->releaseAllMouseButtons();

    const auto PMONITORWORKSPACEOWNER = PMONITOR == pWorkspaceToChangeTo->m_monitor ? PMONITOR : pWorkspaceToChangeTo->m_monitor.lock();

    if (!PMONITORWORKSPACEOWNER)
        return {.success = false, .error = "Workspace to switch to has no monitor"};

    updateRelativeCursorCoords();

    Desktop::focusState()->rawMonitorFocus(PMONITORWORKSPACEOWNER);

    if (*PHIDESPECIALONWORKSPACECHANGE)
        PMONITORWORKSPACEOWNER->setSpecialWorkspace(nullptr);
    PMONITORWORKSPACEOWNER->changeWorkspace(pWorkspaceToChangeTo, false, true);

    if (PMONITOR != PMONITORWORKSPACEOWNER) {
        Vector2D middle = PMONITORWORKSPACEOWNER->middle();
        if (const auto PLAST = pWorkspaceToChangeTo->getLastFocusedWindow(); PLAST) {
            Desktop::focusState()->fullWindowFocus(PLAST, Desktop::FOCUS_REASON_KEYBIND);
            if (*PWORKSPACECENTERON == 1)
                middle = PLAST->middle();
        }
        g_pCompositor->warpCursorTo(middle);
    }

    if (!g_pInputManager->m_lastFocusOnLS) {
        if (Desktop::focusState()->surface())
            g_pInputManager->sendMotionEventsToFocused();
        else
            g_pInputManager->simulateMouseMovement();
    }

    const static auto PWARPONWORKSPACECHANGE = CConfigValue<Hyprlang::INT>("cursor:warp_on_change_workspace");

    if (*PWARPONWORKSPACECHANGE > 0) {
        auto PLAST     = pWorkspaceToChangeTo->getLastFocusedWindow();
        auto HLSurface = Desktop::View::CWLSurface::fromResource(g_pSeatManager->m_state.pointerFocus.lock());

        if (PLAST && (!HLSurface || HLSurface->view()->type() == Desktop::View::VIEW_TYPE_WINDOW))
            PLAST->warpCursor(*PWARPONWORKSPACECHANGE == 2);
    }

    return {};
}

SDispatchResult CKeybindManager::fullscreenActive(std::string args) {
    const auto PWINDOW = Desktop::focusState()->window();
    const auto ARGS    = CConstVarList(args, 2, ' ');

    if (!PWINDOW)
        return {.success = false, .error = "Window not found"};

    const eFullscreenMode MODE = ARGS.size() > 0 && ARGS[0] == "1" ? FSMODE_MAXIMIZED : FSMODE_FULLSCREEN;

    if (ARGS.size() <= 1 || ARGS[1] == "toggle") {
        if (PWINDOW->isEffectiveInternalFSMode(MODE))
            g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);
        else
            g_pCompositor->setWindowFullscreenInternal(PWINDOW, MODE);
    } else {
        if (ARGS[1] == "set")
            g_pCompositor->setWindowFullscreenInternal(PWINDOW, MODE);
        else if (ARGS[1] == "unset")
            g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);
    }

    return {};
}

SDispatchResult CKeybindManager::fullscreenStateActive(std::string args) {
    const auto PWINDOW = Desktop::focusState()->window();
    const auto ARGS    = CVarList(args, 3, ' ');

    if (!PWINDOW)
        return {.success = false, .error = "Window not found"};

    PWINDOW->m_ruleApplicator->syncFullscreenOverride(Desktop::Types::COverridableVar(false, Desktop::Types::PRIORITY_SET_PROP));

    int internalMode, clientMode;
    try {
        internalMode = std::stoi(ARGS[0]);
    } catch (std::exception& e) { internalMode = -1; }
    try {
        clientMode = std::stoi(ARGS[1]);
    } catch (std::exception& e) { clientMode = -1; }

    const Desktop::View::SFullscreenState STATE =
        Desktop::View::SFullscreenState{.internal = (internalMode != -1 ? sc<eFullscreenMode>(internalMode) : PWINDOW->m_fullscreenState.internal),
                                        .client   = (clientMode != -1 ? sc<eFullscreenMode>(clientMode) : PWINDOW->m_fullscreenState.client)};

    if (ARGS.size() <= 2 || ARGS[2] == "toggle") {
        if (internalMode != -1 && clientMode != -1 && PWINDOW->m_fullscreenState.internal == STATE.internal && PWINDOW->m_fullscreenState.client == STATE.client)
            g_pCompositor->setWindowFullscreenState(PWINDOW, Desktop::View::SFullscreenState{.internal = FSMODE_NONE, .client = FSMODE_NONE});
        else if (internalMode != -1 && clientMode == -1 && PWINDOW->m_fullscreenState.internal == STATE.internal)
            g_pCompositor->setWindowFullscreenState(PWINDOW, Desktop::View::SFullscreenState{.internal = FSMODE_NONE, .client = PWINDOW->m_fullscreenState.client});
        else if (internalMode == -1 && clientMode != -1 && PWINDOW->m_fullscreenState.client == STATE.client)
            g_pCompositor->setWindowFullscreenState(PWINDOW, Desktop::View::SFullscreenState{.internal = PWINDOW->m_fullscreenState.internal, .client = FSMODE_NONE});
        else
            g_pCompositor->setWindowFullscreenState(PWINDOW, STATE);
    } else if (ARGS[2] == "set") {
        g_pCompositor->setWindowFullscreenState(PWINDOW, STATE);
    }

    PWINDOW->m_ruleApplicator->syncFullscreenOverride(
        Desktop::Types::COverridableVar(PWINDOW->m_fullscreenState.internal == PWINDOW->m_fullscreenState.client, Desktop::Types::PRIORITY_SET_PROP));

    return {};
}

SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) {

    PHLWINDOW PWINDOW = nullptr;

    if (args.contains(',')) {
        PWINDOW = g_pCompositor->getWindowByRegex(args.substr(args.find_last_of(',') + 1));
        args    = args.substr(0, args.find_last_of(','));
    } else {
        PWINDOW = Desktop::focusState()->window();
    }

    if (!PWINDOW)
        return {.success = false, .error = "Window not found"};

    const auto& [WORKSPACEID, workspaceName, isAutoID] = getWorkspaceIDNameFromString(args);
    if (WORKSPACEID == WORKSPACE_INVALID) {
        Log::logger->log(Log::DEBUG, "Invalid workspace in moveActiveToWorkspace");
        return {.success = false, .error = "Invalid workspace in moveActiveToWorkspace"};
    }

    if (WORKSPACEID == PWINDOW->workspaceID()) {
        Log::logger->log(Log::DEBUG, "Not moving to workspace because it didn't change.");
        return {.success = false, .error = "Not moving to workspace because it didn't change."};
    }

    auto       pWorkspace = g_pCompositor->getWorkspaceByID(WORKSPACEID);
    PHLMONITOR pMonitor   = nullptr;
    const auto POLDWS     = PWINDOW->m_workspace;

    updateRelativeCursorCoords();

    g_pHyprRenderer->damageWindow(PWINDOW);

    if (pWorkspace) {
        const auto FULLSCREENMODE = PWINDOW->m_fullscreenState.internal;
        g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace);
        pMonitor = pWorkspace->m_monitor.lock();
        Desktop::focusState()->rawMonitorFocus(pMonitor);
        g_pCompositor->setWindowFullscreenInternal(PWINDOW, FULLSCREENMODE);
    } else {
        pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->monitorID(), workspaceName, false);
        pMonitor   = pWorkspace->m_monitor.lock();
        g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace);
    }

    POLDWS->m_lastFocusedWindow = POLDWS->getFirstWindow();

    if (pWorkspace->m_isSpecialWorkspace)
        pMonitor->setSpecialWorkspace(pWorkspace);
    else if (POLDWS->m_isSpecialWorkspace)
        POLDWS->m_monitor.lock()->setSpecialWorkspace(nullptr);

    pMonitor->changeWorkspace(pWorkspace);

    Desktop::focusState()->fullWindowFocus(PWINDOW, Desktop::FOCUS_REASON_KEYBIND);
    PWINDOW->warpCursor();

    return {};
}

SDispatchResult CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
    PHLWINDOW PWINDOW = nullptr;

    if (args.contains(',')) {
        PWINDOW = g_pCompositor->getWindowByRegex(args.substr(args.find_last_of(',') + 1));
        args    = args.substr(0, args.find_last_of(','));
    } else {
        PWINDOW = Desktop::focusState()->window();
    }

    if (!PWINDOW)
        return {.success = false, .error = "Window not found"};

    const auto& [WORKSPACEID, workspaceName, isAutoID] = getWorkspaceIDNameFromString(args);
    if (WORKSPACEID == WORKSPACE_INVALID) {
        Log::logger->log(Log::ERR, "Error in moveActiveToWorkspaceSilent, invalid value");
        return {.success = false, .error = "Error in moveActiveToWorkspaceSilent, invalid value"};
    }

    if (WORKSPACEID == PWINDOW->workspaceID())
        return {};

    g_pHyprRenderer->damageWindow(PWINDOW);

    auto       pWorkspace = g_pCompositor->getWorkspaceByID(WORKSPACEID);
    const auto OLDMIDDLE  = PWINDOW->middle();

    if (pWorkspace) {
        g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace);
    } else {
        pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->monitorID(), workspaceName, false);
        g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace);
    }

    if (PWINDOW == Desktop::focusState()->window()) {
        if (const auto PATCOORDS =
                g_pCompositor->vectorToWindowUnified(OLDMIDDLE, Desktop::View::RESERVED_EXTENTS | Desktop::View::INPUT_EXTENTS | Desktop::View::ALLOW_FLOATING, PWINDOW);
            PATCOORDS)
            Desktop::focusState()->fullWindowFocus(PATCOORDS, Desktop::FOCUS_REASON_KEYBIND);
        else
            g_pInputManager->refocus();
    }

    return {};
}

SDispatchResult CKeybindManager::moveFocusTo(std::string args) {
    static auto      PFULLCYCLE       = CConfigValue<Hyprlang::INT>("binds:movefocus_cycles_fullscreen");
    static auto      PGROUPCYCLE      = CConfigValue<Hyprlang::INT>("binds:movefocus_cycles_groupfirst");
    static auto      PMONITORFALLBACK = CConfigValue<Hyprlang::INT>("binds:window_direction_monitor_fallback");
    Math::eDirection dir              = Math::fromChar(args[0]);

    if (dir == Math::DIRECTION_DEFAULT) {
        Log::logger->log(Log::ERR, "Cannot move focus in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0]);
        return {.success = false, .error = std::format("Cannot move focus in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0])};
    }

    const auto PLASTWINDOW = Desktop::focusState()->window();
    if (!PLASTWINDOW || !PLASTWINDOW->aliveAndVisible()) {
        if (*PMONITORFALLBACK)
            tryMoveFocusToMonitor(g_pCompositor->getMonitorInDirection(dir));
        return {};
    }

    const auto PWINDOWTOCHANGETO = *PFULLCYCLE && PLASTWINDOW->isFullscreen() ?
        g_pCompositor->getWindowCycle(PLASTWINDOW, true, {}, false, dir != Math::DIRECTION_DOWN && dir != Math::DIRECTION_RIGHT) :
        g_pCompositor->getWindowInDirection(PLASTWINDOW, dir);

    // Prioritize focus change within groups if the window is a part of it.
    if (*PGROUPCYCLE && PLASTWINDOW->m_group) {
        auto isTheOnlyGroupOnWs = !PWINDOWTOCHANGETO && g_pCompositor->m_monitors.size() == 1;
        if (dir == Math::DIRECTION_LEFT && (PLASTWINDOW != PLASTWINDOW->m_group->head() || isTheOnlyGroupOnWs)) {
            PLASTWINDOW->m_group->moveCurrent(false);
            return {};
        }

        else if (dir == Math::DIRECTION_RIGHT && (PLASTWINDOW != PLASTWINDOW->m_group->tail() || isTheOnlyGroupOnWs)) {
            PLASTWINDOW->m_group->moveCurrent(true);
            return {};
        }
    }

    // Found window in direction, switch to it
    if (PWINDOWTOCHANGETO) {
        switchToWindow(PWINDOWTOCHANGETO, *PFULLCYCLE && PLASTWINDOW->isFullscreen());
        return {};
    }

    Log::logger->log(Log::DEBUG, "No window found in direction {}, looking for a monitor", Math::toString(dir));

    if (*PMONITORFALLBACK && tryMoveFocusToMonitor(g_pCompositor->getMonitorInDirection(dir)))
        return {};

    static auto PNOFALLBACK = CConfigValue<Hyprlang::INT>("general:no_focus_fallback");
    if (*PNOFALLBACK)
        return {.success = false, .error = std::format("Nothing to focus to in direction {}", Math::toString(dir))};

    Log::logger->log(Log::DEBUG, "No monitor found in direction {}, getting the inverse edge", Math::toString(dir));

    const auto PMONITOR = PLASTWINDOW->m_monitor.lock();

    if (!PMONITOR)
        return {.success = false, .error = "last window has no monitor?"};

    if (dir == Math::DIRECTION_LEFT || dir == Math::DIRECTION_RIGHT) {
        if (STICKS(PLASTWINDOW->m_position.x, PMONITOR->m_position.x) && STICKS(PLASTWINDOW->m_size.x, PMONITOR->m_size.x))
            return {.success = false, .error = "move does not make sense, would return back"};
    } else if (STICKS(PLASTWINDOW->m_position.y, PMONITOR->m_position.y) && STICKS(PLASTWINDOW->m_size.y, PMONITOR->m_size.y))
        return {.success = false, .error = "move does not make sense, would return back"};

    CBox box = PMONITOR->logicalBox();
    switch (dir) {
        case Math::DIRECTION_LEFT:
            box.x += box.w;
            box.w = 1;
            break;
        case Math::DIRECTION_RIGHT:
            box.x -= 1;
            box.w = 1;
            break;
        case Math::DIRECTION_UP:
            box.y += box.h;
            box.h = 1;
            break;
        case Math::DIRECTION_DOWN:
            box.y -= 1;
            box.h = 1;
            break;
        default: break;
    }

    const auto PWINDOWCANDIDATE = g_pCompositor->getWindowInDirection(box, PMONITOR->m_activeSpecialWorkspace ? PMONITOR->m_activeSpecialWorkspace : PMONITOR->m_activeWorkspace,
                                                                      dir, PLASTWINDOW, PLASTWINDOW->m_isFloating);
    if (PWINDOWCANDIDATE)
        switchToWindow(PWINDOWCANDIDATE);

    return {};
}

SDispatchResult CKeybindManager::focusUrgentOrLast(std::string args) {
    const auto& HISTORY       = Desktop::History::windowTracker()->fullHistory();
    const auto  PWINDOWURGENT = g_pCompositor->getUrgentWindow();
    const auto  PWINDOWPREV   = Desktop::focusState()->window() ? (HISTORY.size() < 2 ? nullptr : HISTORY[1].lock()) : (HISTORY.empty() ? nullptr : HISTORY[0].lock());

    if (!PWINDOWURGENT && !PWINDOWPREV)
        return {.success = false, .error = "Window not found"};

    switchToWindow(PWINDOWURGENT ? PWINDOWURGENT : PWINDOWPREV);

    return {};
}

SDispatchResult CKeybindManager::focusCurrentOrLast(std::string args) {
    const auto& HISTORY = Desktop::History::windowTracker()->fullHistory();

    if (HISTORY.size() <= 1)
        return {.success = false, .error = "History too short"};

    const auto PWINDOWPREV = HISTORY[HISTORY.size() - 2].lock();

    if (!PWINDOWPREV)
        return {.success = false, .error = "Window not found"};

    switchToWindow(PWINDOWPREV);

    return {};
}

SDispatchResult CKeybindManager::swapActive(std::string args) {
    const auto PLASTWINDOW       = Desktop::focusState()->window();
    PHLWINDOW  PWINDOWTOCHANGETO = nullptr;

    if (!PLASTWINDOW)
        return {.success = false, .error = "Window to swap with not found"};

    if (PLASTWINDOW->isFullscreen())
        return {.success = false, .error = "Can't swap fullscreen window"};

    if (isDirection(args)) {
        Math::eDirection dir = Math::fromChar(args[0]);
        PWINDOWTOCHANGETO    = g_pCompositor->getWindowInDirection(PLASTWINDOW, dir);
    } else
        PWINDOWTOCHANGETO = g_pCompositor->getWindowByRegex(args);

    if (!PWINDOWTOCHANGETO || PWINDOWTOCHANGETO == PLASTWINDOW) {
        Log::logger->log(Log::ERR, "Can't swap with {}, invalid window", args);
        return {.success = false, .error = std::format("Can't swap with {}, invalid window", args)};
    }

    Log::logger->log(Log::DEBUG, "Swapping active window with {}", args);

    updateRelativeCursorCoords();
    g_layoutManager->switchTargets(PLASTWINDOW->layoutTarget(), PWINDOWTOCHANGETO->layoutTarget(), true);
    PLASTWINDOW->warpCursor();
    return {};
}

SDispatchResult CKeybindManager::moveActiveTo(std::string args) {
    bool silent = args.ends_with(" silent");
    if (silent)
        args = args.substr(0, args.length() - 7);

    if (args.starts_with("mon:")) {
        const auto PNEWMONITOR = g_pCompositor->getMonitorFromString(args.substr(4));
        if (!PNEWMONITOR)
            return {.success = false, .error = std::format("Monitor {} not found", args.substr(4))};

        if (silent)
            moveActiveToWorkspaceSilent(PNEWMONITOR->m_activeWorkspace->getConfigName());
        else
            moveActiveToWorkspace(PNEWMONITOR->m_activeWorkspace->getConfigName());

        return {};
    }

    Math::eDirection dir = Math::fromChar(args[0]);
    if (dir == Math::DIRECTION_DEFAULT) {
        Log::logger->log(Log::ERR, "Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0]);
        return {.success = false, .error = std::format("Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0])};
    }

    const auto PLASTWINDOW = Desktop::focusState()->window();

    if (!PLASTWINDOW)
        return {.success = false, .error = "Window to move not found"};

    if (PLASTWINDOW->isFullscreen())
        return {.success = false, .error = "Can't move fullscreen window"};

    updateRelativeCursorCoords();

    g_layoutManager->moveInDirection(PLASTWINDOW->layoutTarget(), args, silent);
    if (!silent)
        PLASTWINDOW->warpCursor();

    return {};
}

SDispatchResult CKeybindManager::toggleGroup(std::string args) {
    const auto PWINDOW = Desktop::focusState()->window();

    if (!PWINDOW)
        return {.success = false, .error = "Window not found"};

    if (PWINDOW->isFullscreen())
        g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);

    if (!PWINDOW->m_group)
        PWINDOW->m_group = Desktop::View::CGroup::create({PWINDOW});
    else
        PWINDOW->m_group->destroy();

    return {};
}

SDispatchResult CKeybindManager::changeGroupActive(std::string args) {
    const auto PWINDOW = Desktop::focusState()->window();

    if (!PWINDOW)
        return {.success = false, .error = "Window not found"};

    if (!PWINDOW->m_group)
        return {.success = false, .error = "No group"};

    if (PWINDOW->m_group->size() == 1)
        return {.success = false, .error = "Only one window in group"};

    if (isNumber(args, false)) {
        // index starts from '1'; '0' means last window
        try {
            const int INDEX = std::stoi(args);
            if (INDEX <= 0)
                PWINDOW->m_group->setCurrent(PWINDOW->m_group->size() - 1);
            else
                PWINDOW->m_group->setCurrent(INDEX - 1);
        } catch (...) { return {.success = false, .error = "invalid idx"}; }

        return {};
    }

    if (args != "b" && args != "prev")
        PWINDOW->m_group->moveCurrent(true);
    else
        PWINDOW->m_group->moveCurrent(false);

    return {};
}

SDispatchResult CKeybindManager::focusMonitor(std::string arg) {
    const auto PMONITOR = g_pCompositor->getMonitorFromString(arg);
    tryMoveFocusToMonitor(PMONITOR);

    return {};
}

SDispatchResult CKeybindManager::moveCursorToCorner(std::string arg) {
    if (!isNumber(arg)) {
        Log::logger->log(Log::ERR, "moveCursorToCorner, arg has to be a number.");
        return {.success = false, .error = "moveCursorToCorner, arg has to be a number."};
    }

    const auto CORNER = std::stoi(arg);

    if (CORNER < 0 || CORNER > 3) {
        Log::logger->log(Log::ERR, "moveCursorToCorner, corner not 0 - 3.");
        return {.success = false, .error = "moveCursorToCorner, corner not 0 - 3."};
    }

    const auto PWINDOW = Desktop::focusState()->window();

    if (!PWINDOW)
        return {.success = false, .error = "Window not found"};

    switch (CORNER) {
        case 0:
            // bottom left
            g_pCompositor->warpCursorTo({PWINDOW->m_realPosition->value().x, PWINDOW->m_realPosition->value().y + PWINDOW->m_realSize->value().y}, true);
            break;
        case 1:
            // bottom right
            g_pCompositor->warpCursorTo({PWINDOW->m_realPosition->value().x + PWINDOW->m_realSize->value().x, PWINDOW->m_realPosition->value().y + PWINDOW->m_realSize->value().y},
                                        true);
            break;
        case 2:
            // top right
            g_pCompositor->warpCursorTo({PWINDOW->m_realPosition->value().x + PWINDOW->m_realSize->value().x, PWINDOW->m_realPosition->value().y}, true);
            break;
        case 3:
            // top left
            g_pCompositor->warpCursorTo({PWINDOW->m_realPosition->value().x, PWINDOW->m_realPosition->value().y}, true);
            break;
    }

    return {};
}

SDispatchResult CKeybindManager::moveCursor(std::string args) {
    std::string x_str, y_str;
    int         x, y;

    size_t      i = args.find_first_of(' ');
    if (i == std::string::npos) {
        Log::logger->log(Log::ERR, "moveCursor, takes 2 arguments.");
        return {.success = false, .error = "moveCursor, takes 2 arguments"};
    }

    x_str = args.substr(0, i);
    y_str = args.substr(i + 1);

    if (!isNumber(x_str)) {
        Log::logger->log(Log::ERR, "moveCursor, x argument has to be a number.");
        return {.success = false, .error = "moveCursor, x argument has to be a number."};
    }
    if (!isNumber(y_str)) {
        Log::logger->log(Log::ERR, "moveCursor, y argument has to be a number.");
        return {.success = false, .error = "moveCursor, y argument has to be a number."};
    }

    x = std::stoi(x_str);
    y = std::stoi(y_str);

    g_pCompositor->warpCursorTo({x, y}, true);
    g_pInputManager->simulateMouseMovement();

    return {};
}

SDispatchResult CKeybindManager::workspaceOpt(std::string args) {
    return {.success = false, .error = "workspaceopt is deprecated"};
}

SDispatchResult CKeybindManager::renameWorkspace(std::string args) {
    try {
        const auto FIRSTSPACEPOS = args.find_first_of(' ');
        if (FIRSTSPACEPOS != std::string::npos) {
            int         workspace = std::stoi(args.substr(0, FIRSTSPACEPOS));
            std::string name      = args.substr(FIRSTSPACEPOS + 1);
            if (const auto& PWS = g_pCompositor->getWorkspaceByID(workspace); PWS)
                PWS->rename(name);
            else
                return {.success = false, .error = "No such workspace"};
        } else if (const auto& PWS = g_pCompositor->getWorkspaceByID(std::stoi(args)); PWS)
            PWS->rename("");
        else
            return {.success = false, .error = "No such workspace"};
    } catch (std::exception& e) {
        Log::logger->log(Log::ERR, R"(Invalid arg in renameWorkspace, expected numeric id only or a numeric id and string name. "{}": "{}")", args, e.what());
        return {.success = false, .error = std::format(R"(Invalid arg in renameWorkspace, expected numeric id only or a numeric id and string name. "{}": "{}")", args, e.what())};
    }

    return {};
}

SDispatchResult CKeybindManager::exitHyprland(std::string argz) {
    Event::bus()->m_events.exit.emit();

    if (g_pCompositor->m_finalRequests)
        return {}; // Exiting deferred until requests complete

    g_pCompositor->stopCompositor();
    return {};
}

SDispatchResult CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
    PHLMONITOR PMONITOR = g_pCompositor->getMonitorFromString(args);

    if (!PMONITOR) {
        Log::logger->log(Log::ERR, "Ignoring moveCurrentWorkspaceToMonitor: monitor doesn't exist");
        return {.success = false, .error = "Ignoring moveCurrentWorkspaceToMonitor: monitor doesn't exist"};
    }

    // get the current workspace
    const auto PCURRENTWORKSPACE = Desktop::focusState()->monitor()->m_activeWorkspace;
    if (!PCURRENTWORKSPACE) {
        Log::logger->log(Log::ERR, "moveCurrentWorkspaceToMonitor invalid workspace!");
        return {.success = false, .error = "moveCurrentWorkspaceToMonitor invalid workspace!"};
    }

    g_pCompositor->moveWorkspaceToMonitor(PCURRENTWORKSPACE, PMONITOR);

    return {};
}

SDispatchResult CKeybindManager::moveWorkspaceToMonitor(std::string args) {
    if (!args.contains(' '))
        return {.success = false, .error = "Invalid arguments, expected: workspace monitor"};

    std::string workspace = args.substr(0, args.find_first_of(' '));
    std::string monitor   = args.substr(args.find_first_of(' ') + 1);

    const auto  PMONITOR = g_pCompositor->getMonitorFromString(monitor);

    if (!PMONITOR) {
        Log::logger->log(Log::ERR, "Ignoring moveWorkspaceToMonitor: monitor doesn't exist");
        return {.success = false, .error = "Ignoring moveWorkspaceToMonitor: monitor doesn't exist"};
    }

    const auto WORKSPACEID = getWorkspaceIDNameFromString(workspace).id;

    if (WORKSPACEID == WORKSPACE_INVALID) {
        Log::logger->log(Log::ERR, "moveWorkspaceToMonitor invalid workspace!");
        return {.success = false, .error = "moveWorkspaceToMonitor invalid workspace!"};
    }

    const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);

    if (!PWORKSPACE) {
        Log::logger->log(Log::ERR, "moveWorkspaceToMonitor workspace doesn't exist!");
        return {.success = false, .error = "moveWorkspaceToMonitor workspace doesn't exist!"};
    }

    g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PMONITOR);

    return {};
}

SDispatchResult CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) {
    auto [workspaceID, workspaceName, isAutoID] = getWorkspaceIDNameFromString(args);
    if (workspaceID == WORKSPACE_INVALID) {
        Log::logger->log(Log::ERR, "focusWorkspaceOnCurrentMonitor invalid workspace!");
        return {.success = false, .error = "focusWorkspaceOnCurrentMonitor invalid workspace!"};
    }

    const auto PCURRMONITOR = Desktop::focusState()->monitor();

    if (!PCURRMONITOR) {
        Log::logger->log(Log::ERR, "focusWorkspaceOnCurrentMonitor monitor doesn't exist!");
        return {.success = false, .error = "focusWorkspaceOnCurrentMonitor monitor doesn't exist!"};
    }

    auto pWorkspace = g_pCompositor->getWorkspaceByID(workspaceID);

    if (!pWorkspace) {
        pWorkspace = g_pCompositor->createNewWorkspace(workspaceID, PCURRMONITOR->m_id, workspaceName);
        // we can skip the moving, since it's already on the current monitor
        changeworkspace(pWorkspace->getConfigName());
        return {};
    }

    static auto PBACKANDFORTH = CConfigValue<Hyprlang::INT>("binds:workspace_back_and_forth");
    const auto  PREVWS        = Desktop::History::workspaceTracker()->previousWorkspaceIDName(pWorkspace);

    if (*PBACKANDFORTH && PCURRMONITOR->activeWorkspaceID() == workspaceID && PREVWS.id != -1) {
        // Workspace to focus is previous workspace
        pWorkspace = g_pCompositor->getWorkspaceByID(PREVWS.id);
        if (!pWorkspace)
            pWorkspace = g_pCompositor->createNewWorkspace(PREVWS.id, PCURRMONITOR->m_id, PREVWS.name);

        workspaceID = pWorkspace->m_id;
    }

    if (pWorkspace->m_monitor != PCURRMONITOR) {
        const auto POLDMONITOR = pWorkspace->m_monitor.lock();
        if (!POLDMONITOR) { // wat
            Log::logger->log(Log::ERR, "focusWorkspaceOnCurrentMonitor old monitor doesn't exist!");
            return {.success = false, .error = "focusWorkspaceOnCurrentMonitor old monitor doesn't exist!"};
        }
        if (POLDMONITOR->activeWorkspaceID() == workspaceID) {
            g_pCompositor->swapActiveWorkspaces(POLDMONITOR, PCURRMONITOR);
            return {};
        } else {
            g_pCompositor->moveWorkspaceToMonitor(pWorkspace, PCURRMONITOR, true);
        }
    }

    changeworkspace(pWorkspace->getConfigName());

    return {};
}

SDispatchResult CKeybindManager::toggleSpecialWorkspace(std::string args) {
    const auto& [workspaceID, workspaceName, isAutoID] = getWorkspaceIDNameFromString("special:" + args);
    if (workspaceID == WORKSPACE_INVALID || !g_pCompositor->isWorkspaceSpecial(workspaceID)) {
        Log::logger->log(Log::ERR, "Invalid workspace passed to special");
        return {.success = false, .error = "Invalid workspace passed to special"};
    }

    bool       requestedWorkspaceIsAlreadyOpen = false;
    const auto PMONITOR                        = Desktop::focusState()->monitor();
    auto       specialOpenOnMonitor            = PMONITOR->activeSpecialWorkspaceID();

    for (auto const& m : g_pCompositor->m_monitors) {
        if (m->activeSpecialWorkspaceID() == workspaceID) {
            requestedWorkspaceIsAlreadyOpen = true;
            break;
        }
    }

    updateRelativeCursorCoords();

    PHLWORKSPACEREF focusedWorkspace;

    if (requestedWorkspaceIsAlreadyOpen && specialOpenOnMonitor == workspaceID) {
        // already open on this monitor
        Log::logger->log(Log::DEBUG, "Toggling special workspace {} to closed", workspaceID);
        PMONITOR->setSpecialWorkspace(nullptr);

        focusedWorkspace = PMONITOR->m_activeWorkspace;
    } else {
        Log::logger->log(Log::DEBUG, "Toggling special workspace {} to open", workspaceID);
        auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceID);

        if (!PSPECIALWORKSPACE)
            PSPECIALWORKSPACE = g_pCompositor->createNewWorkspace(workspaceID, PMONITOR->m_id, workspaceName);

        PMONITOR->setSpecialWorkspace(PSPECIALWORKSPACE);

        focusedWorkspace = PSPECIALWORKSPACE;
    }

    const static auto PWARPONTOGGLESPECIAL = CConfigValue<Hyprlang::INT>("cursor:warp_on_toggle_special");

    if (*PWARPONTOGGLESPECIAL > 0) {
        auto PLAST     = focusedWorkspace->getLastFocusedWindow();
        auto HLSurface = Desktop::View::CWLSurface::fromResource(g_pSeatManager->m_state.pointerFocus.lock());

        if (PLAST && (!HLSurface || HLSurface->view()->type() == Desktop::View::VIEW_TYPE_WINDOW))
            PLAST->warpCursor(*PWARPONTOGGLESPECIAL == 2);
    }

    return {};
}

SDispatchResult CKeybindManager::forceRendererReload(std::string args) {
    bool overAgain = false;

    for (auto const& m : g_pCompositor->m_monitors) {
        if (!m->m_output)
            continue;

        auto rule = Config::monitorRuleMgr()->get(m);
        if (!m->applyMonitorRule(std::move(rule), true)) {
            overAgain = true;
            break;
        }
    }

    if (overAgain)
        forceRendererReload(args);

    return {};
}

SDispatchResult CKeybindManager::resizeActive(std::string args) {
    const auto PLASTWINDOW = Desktop::focusState()->window();

    if (!PLASTWINDOW)
        return {.success = false, .error = "No window found"};

    if (PLASTWINDOW->isFullscreen())
        return {.success = false, .error = "Window is fullscreen"};

    const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_realSize->goal());

    if (SIZ.x < 1 || SIZ.y < 1)
        return {.success = false, .error = "Invalid size provided"};

    g_layoutManager->resizeTarget(SIZ - PLASTWINDOW->m_realSize->goal(), PLASTWINDOW->layoutTarget());

    if (PLASTWINDOW->m_realSize->goal().x > 1 && PLASTWINDOW->m_realSize->goal().y > 1)
        PLASTWINDOW->setHidden(false);

    return {};
}

SDispatchResult CKeybindManager::moveActive(std::string args) {
    const auto PLASTWINDOW = Desktop::focusState()->window();

    if (!PLASTWINDOW)
        return {.success = false, .error = "No window found"};

    if (PLASTWINDOW->isFullscreen())
        return {.success = false, .error = "Window is fullscreen"};

    const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_realPosition->goal());

    g_layoutManager->moveTarget(POS - PLASTWINDOW->m_realPosition->goal(), PLASTWINDOW->layoutTarget());

    return {};
}

SDispatchResult CKeybindManager::moveWindow(std::string args) {

    const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1);
    const auto MOVECMD     = args.substr(0, args.find_first_of(','));

    const auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX);

    if (!PWINDOW) {
        Log::logger->log(Log::ERR, "moveWindow: no window");
        return {.success = false, .error = "moveWindow: no window"};
    }

    if (PWINDOW->isFullscreen())
        return {.success = false, .error = "Window is fullscreen"};

    const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_realPosition->goal());

    g_layoutManager->moveTarget(POS - PWINDOW->m_realPosition->goal(), PWINDOW->layoutTarget());

    return {};
}

SDispatchResult CKeybindManager::resizeWindow(std::string args) {

    const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1);
    const auto MOVECMD     = args.substr(0, args.find_first_of(','));

    const auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX);

    if (!PWINDOW) {
        Log::logger->log(Log::ERR, "resizeWindow: no window");
        return {.success = false, .error = "resizeWindow: no window"};
    }

    if (PWINDOW->isFullscreen())
        return {.success = false, .error = "Window is fullscreen"};

    const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_realSize->goal());

    if (SIZ.x < 1 || SIZ.y < 1)
        return {.success = false, .error = "Invalid size provided"};

    g_layoutManager->resizeTarget(SIZ - PWINDOW->m_realSize->goal(), PWINDOW->layoutTarget(), Layout::CORNER_NONE);

    if (PWINDOW->m_realSize->goal().x > 1 && PWINDOW->m_realSize->goal().y > 1)
        PWINDOW->setHidden(false);

    return {};
}

SDispatchResult CKeybindManager::circleNext(std::string arg) {
    if (!Desktop::focusState()->window()) {
        // if we have a clear focus, find the first window and get the next focusable.
        const auto PWS = Desktop::focusState()->monitor()->m_activeWorkspace;
        if (PWS && PWS->getWindows() > 0) {
            const auto PWINDOW = PWS->getFirstWindow();
            switchToWindow(PWINDOW);
        }

        return {};
    }

    CVarList            args{arg, 0, 's', true};

    const auto          PREV = args.contains("prev") || args.contains("p") || args.contains("last") || args.contains("l");

    std::optional<bool> floatStatus = {};
    if (args.contains("tile") || args.contains("tiled")) {
        // if we want just tiled, and we are on a tiled window, use layoutmsg for layouts that support it

        if (!Desktop::focusState()->window()->m_isFloating) {
            if (const auto SPACE = Desktop::focusState()->window()->layoutTarget()->space(); SPACE) {

                constexpr const std::array<const std::type_info*, 2> LAYOUTS_WITH_CYCLE_NEXT = {
                    &typeid(Layout::Tiled::CMonocleAlgorithm),
                    &typeid(Layout::Tiled::CMasterAlgorithm),
                };

                if (std::ranges::contains(LAYOUTS_WITH_CYCLE_NEXT, &typeid(*SPACE->algorithm()->tiledAlgo().get()))) {
                    CKeybindManager::layoutmsg(PREV ? "cyclenext, b" : "cyclenext");
                    return {};
                }
            }
        }
    }

    if (args.contains("float") || args.contains("floating"))
        floatStatus = true;

    const auto  VISIBLE = args.contains("visible") || args.contains("v");
    const auto  NEXT    = args.contains("next") || args.contains("n"); // prev is default in classic alt+tab
    const auto  HIST    = args.contains("hist") || args.contains("h");
    const auto& w       = HIST ? g_pCompositor->getWindowCycleHist(Desktop::focusState()->window(), true, floatStatus, VISIBLE, NEXT) :
                                 g_pCompositor->getWindowCycle(Desktop::focusState()->window(), true, floatStatus, VISIBLE, PREV);

    switchToWindow(w, HIST);

    return {};
}

SDispatchResult CKeybindManager::focusWindow(std::string regexp) {
    const auto PWINDOW = g_pCompositor->getWindowByRegex(regexp);

    if (!PWINDOW)
        return {.success = false, .error = "No such window found"};

    Log::logger->log(Log::DEBUG, "Focusing to window name: {}", PWINDOW->m_title);

    const auto PWORKSPACE = PWINDOW->m_workspace;
    if (!PWORKSPACE) {
        Log::logger->log(Log::ERR, "BUG THIS: null workspace in focusWindow");
        return {.success = false, .error = "BUG THIS: null workspace in focusWindow"};
    }

    updateRelativeCursorCoords();

    if (Desktop::focusState()->monitor() && Desktop::focusState()->monitor()->m_activeWorkspace != PWINDOW->m_workspace &&
        Desktop::focusState()->monitor()->m_activeSpecialWorkspace != PWINDOW->m_workspace) {
        Log::logger->log(Log::DEBUG, "Fake executing workspace to move focus");
        changeworkspace(PWORKSPACE->getConfigName());
    }

    Desktop::focusState()->fullWindowFocus(PWINDOW, Desktop::FOCUS_REASON_KEYBIND, nullptr, false);

    PWINDOW->warpCursor();

    return {};
}

SDispatchResult CKeybindManager::tagWindow(std::string args) {
    PHLWINDOW PWINDOW = nullptr;
    CVarList  vars{args, 0, 's', true};

    if (vars.size() == 1)
        PWINDOW = Desktop::focusState()->window();
    else if (vars.size() == 2)
        PWINDOW = g_pCompositor->getWindowByRegex(vars[1]);
    else
        return {.success = false, .error = "Invalid number of arguments, expected 1 or 2 arguments"};

    if (PWINDOW && PWINDOW->m_ruleApplicator->m_tagKeeper.applyTag(vars[0])) {
        PWINDOW->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_TAG);
        PWINDOW->updateDecorationValues();
    }

    return {};
}

SDispatchResult CKeybindManager::toggleSwallow(std::string args) {
    PHLWINDOWREF pWindow = Desktop::focusState()->window();

    if (!valid(pWindow) || !valid(pWindow->m_swallowed))
        return {};

    if (pWindow->m_swallowed->m_currentlySwallowed) {
        // Unswallow
        pWindow->m_swallowed->m_currentlySwallowed = false;
        pWindow->m_swallowed->setHidden(false);
        g_layoutManager->newTarget(pWindow->m_swallowed->layoutTarget(), pWindow->m_workspace->m_space);
    } else {
        // Reswallow
        pWindow->m_swallowed->m_currentlySwallowed = true;
        pWindow->m_swallowed->setHidden(true);
        g_layoutManager->removeTarget(pWindow->m_swallowed->layoutTarget());
    }

    return {};
}

SDispatchResult CKeybindManager::setSubmap(std::string submap) {
    if (submap == "reset" || submap.empty()) {
        m_currentSelectedSubmap.name = "";
        Log::logger->log(Log::DEBUG, "Reset active submap to the default one.");
        g_pEventManager->postEvent(SHyprIPCEvent{"submap", ""});
        Event::bus()->m_events.keybinds.submap.emit(m_currentSelectedSubmap.name);
        return {};
    }

    for (const auto& k : g_pKeybindManager->m_keybinds) {
        if (k->submap.name == submap) {
            m_currentSelectedSubmap.name = submap;
            Log::logger->log(Log::DEBUG, "Changed keybind submap to {}", submap);
            g_pEventManager->postEvent(SHyprIPCEvent{"submap", submap});
            Event::bus()->m_events.keybinds.submap.emit(m_currentSelectedSubmap.name);
            return {};
        }
    }

    Log::logger->log(Log::ERR, "Cannot set submap {}, submap doesn't exist (wasn't registered!)", submap);
    return {.success = false, .error = std::format("Cannot set submap {}, submap doesn't exist (wasn't registered!)", submap)};
}

SDispatchResult CKeybindManager::pass(std::string regexp) {

    // find the first window passing the regex
    const auto PWINDOW = g_pCompositor->getWindowByRegex(regexp);

    if (!PWINDOW) {
        Log::logger->log(Log::ERR, "pass: window not found");
        return {.success = false, .error = "pass: window not found"};
    }

    if (!g_pSeatManager->m_keyboard) {
        Log::logger->log(Log::ERR, "No kb in pass?");
        return {.success = false, .error = "No kb in pass?"};
    }

    const auto XWTOXW        = PWINDOW->m_isX11 && Desktop::focusState()->window() && Desktop::focusState()->window()->m_isX11;
    const auto LASTMOUSESURF = g_pSeatManager->m_state.pointerFocus.lock();
    const auto LASTKBSURF    = g_pSeatManager->m_state.keyboardFocus.lock();

    // pass all mf shit
    if (!XWTOXW) {
        if (g_pKeybindManager->m_lastCode != 0)
            g_pSeatManager->setKeyboardFocus(PWINDOW->wlSurface()->resource());
        else
            g_pSeatManager->setPointerFocus(PWINDOW->wlSurface()->resource(), {1, 1});
    }

    g_pSeatManager->sendKeyboardMods(g_pInputManager->getModsFromAllKBs(), 0, 0, 0);

    if (g_pKeybindManager->m_passPressed == 1) {
        if (g_pKeybindManager->m_lastCode != 0)
            g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_timeLastMs, g_pKeybindManager->m_lastCode - 8, WL_KEYBOARD_KEY_STATE_PRESSED);
        else
            g_pSeatManager->sendPointerButton(g_pKeybindManager->m_timeLastMs, g_pKeybindManager->m_lastMouseCode, WL_POINTER_BUTTON_STATE_PRESSED);
    } else if (g_pKeybindManager->m_passPressed == 0)
        if (g_pKeybindManager->m_lastCode != 0)
            g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_timeLastMs, g_pKeybindManager->m_lastCode - 8, WL_KEYBOARD_KEY_STATE_RELEASED);
        else
            g_pSeatManager->sendPointerButton(g_pKeybindManager->m_timeLastMs, g_pKeybindManager->m_lastMouseCode, WL_POINTER_BUTTON_STATE_RELEASED);
    else {
        // dynamic call of the dispatcher
        if (g_pKeybindManager->m_lastCode != 0) {
            g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_timeLastMs, g_pKeybindManager->m_lastCode - 8, WL_KEYBOARD_KEY_STATE_PRESSED);
            g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_timeLastMs, g_pKeybindManager->m_lastCode - 8, WL_KEYBOARD_KEY_STATE_RELEASED);
        } else {
            g_pSeatManager->sendPointerButton(g_pKeybindManager->m_timeLastMs, g_pKeybindManager->m_lastMouseCode, WL_POINTER_BUTTON_STATE_PRESSED);
            g_pSeatManager->sendPointerButton(g_pKeybindManager->m_timeLastMs, g_pKeybindManager->m_lastMouseCode, WL_POINTER_BUTTON_STATE_RELEASED);
        }
    }

    if (XWTOXW)
        return {};

    // Massive hack:
    // this will make g_pSeatManager NOT send the leave event to XWayland apps, provided we are not on an XWayland window already.
    // please kill me
    if (PWINDOW->m_isX11) {
        if (g_pKeybindManager->m_lastCode != 0) {
            g_pSeatManager->m_state.keyboardFocus.reset();
            g_pSeatManager->m_state.keyboardFocusResource.reset();
        } else {
            g_pSeatManager->m_state.pointerFocus.reset();
            g_pSeatManager->m_state.pointerFocusResource.reset();
        }
    }

    const auto SL = PWINDOW->m_realPosition->goal() - g_pInputManager->getMouseCoordsInternal();

    if (g_pKeybindManager->m_lastCode != 0)
        g_pSeatManager->setKeyboardFocus(LASTKBSURF);
    else
        g_pSeatManager->setPointerFocus(LASTMOUSESURF, SL);

    return {};
}

SDispatchResult CKeybindManager::sendshortcut(std::string args) {
    // args=<NEW_MODKEYS><NEW_KEY>[,WINDOW_RULES]
    const auto ARGS = CVarList(args, 3);
    if (ARGS.size() != 3) {
        Log::logger->log(Log::ERR, "sendshortcut: invalid args");
        return {.success = false, .error = "sendshortcut: invalid args"};
    }

    const auto MOD     = g_pKeybindManager->stringToModMask(ARGS[0]);
    const auto KEY     = ARGS[1];
    uint32_t   keycode = 0;
    bool       isMouse = false;

    // similar to parseKey in ConfigManager
    if (isNumber(KEY) && std::stoi(KEY) > 9)
        keycode = std::stoi(KEY);
    else if (KEY.compare(0, 5, "code:") == 0 && isNumber(KEY.substr(5)))
        keycode = std::stoi(KEY.substr(5));
    else if (KEY.compare(0, 6, "mouse:") == 0 && isNumber(KEY.substr(6))) {
        keycode = std::stoi(KEY.substr(6));
        isMouse = true;
        if (keycode < 272) {
            Log::logger->log(Log::ERR, "sendshortcut: invalid mouse button");
            return {.success = false, .error = "sendshortcut: invalid mouse button"};
        }
    } else {

        // here, we need to find the keycode from the key name
        // this is not possible through xkb's lib, so we need to iterate through all keycodes
        // once found, we save it to the cache

        const auto KEYSYM = xkb_keysym_from_name(KEY.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
        keycode           = 0;

        const auto KB = g_pSeatManager->m_keyboard;

        if (!KB) {
            Log::logger->log(Log::ERR, "sendshortcut: no kb");
            return {.success = false, .error = "sendshortcut: no kb"};
        }

        const auto KEYPAIRSTRING = std::format("{}{}", rc<uintptr_t>(KB.get()), KEY);

        if (!g_pKeybindManager->m_keyToCodeCache.contains(KEYPAIRSTRING)) {
            xkb_keymap*   km = KB->m_xkbKeymap;
            xkb_state*    ks = KB->m_xkbState;

            xkb_keycode_t keycode_min, keycode_max;
            keycode_min = xkb_keymap_min_keycode(km);
            keycode_max = xkb_keymap_max_keycode(km);

            for (xkb_keycode_t kc = keycode_min; kc <= keycode_max; ++kc) {
                xkb_keysym_t sym = xkb_state_key_get_one_sym(ks, kc);

                if (sym == KEYSYM) {
                    keycode                                            = kc;
                    g_pKeybindManager->m_keyToCodeCache[KEYPAIRSTRING] = keycode;
                }
            }

            if (!keycode) {
                Log::logger->log(Log::ERR, "sendshortcut: key not found");
                return {.success = false, .error = "sendshortcut: key not found"};
            }

        } else
            keycode = g_pKeybindManager->m_keyToCodeCache[KEYPAIRSTRING];
    }

    if (!keycode) {
        Log::logger->log(Log::ERR, "sendshortcut: invalid key");
        return {.success = false, .error = "sendshortcut: invalid key"};
    }

    const std::string regexp      = ARGS[2];
    PHLWINDOW         PWINDOW     = nullptr;
    const auto        LASTSURFACE = Desktop::focusState()->surface();

    //if regexp is not empty, send shortcut to current window
    //else, don't change focus
    if (!regexp.empty()) {
        PWINDOW = g_pCompositor->getWindowByRegex(regexp);

        if (!PWINDOW) {
            Log::logger->log(Log::ERR, "sendshortcut: window not found");
            return {.success = false, .error = "sendshortcut: window not found"};
        }

        if (!g_pSeatManager->m_keyboard) {
            Log::logger->log(Log::ERR, "No kb in sendshortcut?");
            return {.success = false, .error = "No kb in sendshortcut?"};
        }

        if (!isMouse)
            g_pSeatManager->setKeyboardFocus(PWINDOW->wlSurface()->resource());
        else
            g_pSeatManager->setPointerFocus(PWINDOW->wlSurface()->resource(), {1, 1});
    }

    //copied the rest from pass and modified it
    // if wl -> xwl, activate destination
    if (PWINDOW && PWINDOW->m_isX11 && Desktop::focusState()->window() && !Desktop::focusState()->window()->m_isX11)
        g_pXWaylandManager->activateSurface(PWINDOW->wlSurface()->resource(), true);
    // if xwl -> xwl, send to current. Timing issues make this not work.
    if (PWINDOW && PWINDOW->m_isX11 && Desktop::focusState()->window() && Desktop::focusState()->window()->m_isX11)
        PWINDOW = nullptr;

    g_pSeatManager->sendKeyboardMods(MOD, 0, 0, 0);

    if (g_pKeybindManager->m_passPressed == 1) {
        if (!isMouse)
            g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_timeLastMs, keycode - 8, WL_KEYBOARD_KEY_STATE_PRESSED);
        else
            g_pSeatManager->sendPointerButton(g_pKeybindManager->m_timeLastMs, keycode, WL_POINTER_BUTTON_STATE_PRESSED);
    } else if (g_pKeybindManager->m_passPressed == 0) {
        if (!isMouse)
            g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_timeLastMs, keycode - 8, WL_KEYBOARD_KEY_STATE_RELEASED);
        else
            g_pSeatManager->sendPointerButton(g_pKeybindManager->m_timeLastMs, keycode, WL_POINTER_BUTTON_STATE_RELEASED);
    } else {
        // dynamic call of the dispatcher
        if (!isMouse) {
            g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_timeLastMs, keycode - 8, WL_KEYBOARD_KEY_STATE_PRESSED);
            g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_timeLastMs, keycode - 8, WL_KEYBOARD_KEY_STATE_RELEASED);
        } else {
            g_pSeatManager->sendPointerButton(g_pKeybindManager->m_timeLastMs, keycode, WL_POINTER_BUTTON_STATE_PRESSED);
            g_pSeatManager->sendPointerButton(g_pKeybindManager->m_timeLastMs, keycode, WL_POINTER_BUTTON_STATE_RELEASED);
        }
    }

    g_pSeatManager->sendKeyboardMods(0, 0, 0, 0);

    if (!PWINDOW)
        return {};

    if (PWINDOW->m_isX11) { //xwayland hack, see pass
        if (!isMouse) {
            g_pSeatManager->m_state.keyboardFocus.reset();
            g_pSeatManager->m_state.keyboardFocusResource.reset();
        } else {
            g_pSeatManager->m_state.pointerFocus.reset();
            g_pSeatManager->m_state.pointerFocusResource.reset();
        }
    }

    const auto SL = PWINDOW->m_realPosition->goal() - g_pInputManager->getMouseCoordsInternal();

    if (!isMouse)
        g_pSeatManager->setKeyboardFocus(LASTSURFACE);
    else
        g_pSeatManager->setPointerFocus(LASTSURFACE, SL);

    return {};
}

SDispatchResult CKeybindManager::layoutmsg(std::string msg) {
    auto ret = g_layoutManager->layoutMsg(msg);
    if (!ret)
        return {.success = false, .error = ret.error()};
    return {};
}

SDispatchResult CKeybindManager::dpms(std::string arg) {
    SDispatchResult res;
    bool            enable = arg.starts_with("on");
    std::string     port   = "";

    bool            isToggle = arg.starts_with("toggle");
    if (arg.find_first_of(' ') != std::string::npos)
        port = arg.substr(arg.find_first_of(' ') + 1);

    for (auto const& m : g_pCompositor->m_realMonitors) {
        if (!m->m_enabled)
            continue;

        if (!port.empty() && m->m_name != port)
            continue;

        if (isToggle)
            enable = !m->m_dpmsStatus;

        m->setDPMS(enable);
    }

    g_pCompositor->m_dpmsStateOn = enable;

    g_pPointerManager->recheckEnteredOutputs();

    return res;
}

SDispatchResult CKeybindManager::swapnext(std::string arg) {

    PHLWINDOW toSwap = nullptr;

    if (!Desktop::focusState()->window())
        return {};

    const auto PLASTWINDOW = Desktop::focusState()->window();

    const auto PLASTCYCLED =
        validMapped(Desktop::focusState()->window()->m_lastCycledWindow) && Desktop::focusState()->window()->m_lastCycledWindow->m_workspace == PLASTWINDOW->m_workspace ?
        Desktop::focusState()->window()->m_lastCycledWindow.lock() :
        nullptr;

    const bool NEED_PREV = arg == "last" || arg == "l" || arg == "prev" || arg == "p";
    toSwap               = g_pCompositor->getWindowCycle(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW, true, std::nullopt, false, NEED_PREV);

    // sometimes we may come back to ourselves.
    if (toSwap == PLASTWINDOW)
        toSwap = g_pCompositor->getWindowCycle(PLASTWINDOW, true, std::nullopt, false, NEED_PREV);

    g_layoutManager->switchTargets(PLASTWINDOW->layoutTarget(), toSwap->layoutTarget(), false);

    PLASTWINDOW->m_lastCycledWindow = toSwap;

    Desktop::focusState()->fullWindowFocus(PLASTWINDOW, Desktop::FOCUS_REASON_KEYBIND);

    return {};
}

SDispatchResult CKeybindManager::swapActiveWorkspaces(std::string args) {
    const auto MON1 = args.substr(0, args.find_first_of(' '));
    const auto MON2 = args.substr(args.find_first_of(' ') + 1);

    const auto PMON1 = g_pCompositor->getMonitorFromString(MON1);
    const auto PMON2 = g_pCompositor->getMonitorFromString(MON2);

    if (!PMON1 || !PMON2)
        return {.success = false, .error = "No such monitor found"};

    if (PMON1 == PMON2)
        return {};

    g_pCompositor->swapActiveWorkspaces(PMON1, PMON2);

    return {};
}

SDispatchResult CKeybindManager::pinActive(std::string args) {

    PHLWINDOW PWINDOW = nullptr;

    if (args != "active" && args.length() > 1)
        PWINDOW = g_pCompositor->getWindowByRegex(args);
    else
        PWINDOW = Desktop::focusState()->window();

    if (!PWINDOW) {
        Log::logger->log(Log::ERR, "pin: window not found");
        return {.success = false, .error = "pin: window not found"};
    }

    if (!PWINDOW->m_isFloating || PWINDOW->isFullscreen())
        return {.success = false, .error = "Window does not qualify to be pinned"};

    PWINDOW->m_pinned = !PWINDOW->m_pinned;

    const auto PMONITOR = PWINDOW->m_monitor.lock();

    if (!PMONITOR) {
        Log::logger->log(Log::ERR, "pin: monitor not found");
        return {.success = false, .error = "pin: window not found"};
    }

    PWINDOW->layoutTarget()->assignToSpace(PMONITOR->m_activeWorkspace->m_space);

    PWINDOW->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_PINNED);

    const auto PWORKSPACE = PWINDOW->m_workspace;

    PWORKSPACE->m_lastFocusedWindow =
        g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), Desktop::View::RESERVED_EXTENTS | Desktop::View::INPUT_EXTENTS);

    g_pEventManager->postEvent(SHyprIPCEvent{"pin", std::format("{:x},{}", rc<uintptr_t>(PWINDOW.get()), sc<int>(PWINDOW->m_pinned))});
    Event::bus()->m_events.window.pin.emit(PWINDOW);

    g_pHyprRenderer->damageWindow(PWINDOW, true);

    return {};
}

SDispatchResult CKeybindManager::mouse(std::string args) {
    const auto ARGS    = CVarList(args.substr(1), 2, ' ');
    const auto PRESSED = args[0] == '1';

    if (!PRESSED) {
        return changeMouseBindMode(MBIND_INVALID);
    }

    if (ARGS[0] == "movewindow") {
        return changeMouseBindMode(MBIND_MOVE);
    } else {
        try {
            switch (std::stoi(ARGS[1])) {
                case 1: return changeMouseBindMode(MBIND_RESIZE_FORCE_RATIO); break;
                case 2: return changeMouseBindMode(MBIND_RESIZE_BLOCK_RATIO); break;
                default: return changeMouseBindMode(MBIND_RESIZE);
            }
        } catch (std::exception& e) { return changeMouseBindMode(MBIND_RESIZE); }
    }
}

SDispatchResult CKeybindManager::changeMouseBindMode(const eMouseBindMode MODE) {
    if (MODE != MBIND_INVALID) {
        if (g_layoutManager->dragController()->target())
            return {};

        const auto      MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
        const PHLWINDOW PWINDOW = g_pCompositor->vectorToWindowUnified(MOUSECOORDS, Desktop::View::RESERVED_EXTENTS | Desktop::View::INPUT_EXTENTS | Desktop::View::ALLOW_FLOATING);

        if (!PWINDOW)
            return SDispatchResult{.passEvent = true};

        if (!PWINDOW->isFullscreen() && MODE == MBIND_MOVE) {
            if (PWINDOW->checkInputOnDecos(INPUT_TYPE_DRAG_START, MOUSECOORDS))
                return SDispatchResult{.passEvent = false};
        }

        g_layoutManager->beginDragTarget(PWINDOW->layoutTarget(), MODE);
    } else {
        if (!g_layoutManager->dragController()->target())
            return {};

        g_layoutManager->endDragTarget();
    }

    return {};
}

SDispatchResult CKeybindManager::bringActiveToTop(std::string args) {
    if (Desktop::focusState()->window() && Desktop::focusState()->window()->m_isFloating)
        g_pCompositor->changeWindowZOrder(Desktop::focusState()->window(), true);

    g_pInputManager->simulateMouseMovement();

    return {};
}

SDispatchResult CKeybindManager::alterZOrder(std::string args) {
    const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1);
    const auto POSITION    = args.substr(0, args.find_first_of(','));
    auto       PWINDOW     = g_pCompositor->getWindowByRegex(WINDOWREGEX);

    if (!PWINDOW && Desktop::focusState()->window() && Desktop::focusState()->window()->m_isFloating)
        PWINDOW = Desktop::focusState()->window();

    if (!PWINDOW) {
        Log::logger->log(Log::ERR, "alterZOrder: no window");
        return {.success = false, .error = "alterZOrder: no window"};
    }

    if (POSITION == "top")
        g_pCompositor->changeWindowZOrder(PWINDOW, true);
    else if (POSITION == "bottom")
        g_pCompositor->changeWindowZOrder(PWINDOW, false);
    else {
        Log::logger->log(Log::ERR, "alterZOrder: bad position: {}", POSITION);
        return {.success = false, .error = "alterZOrder: bad position: {}"};
    }

    g_pInputManager->simulateMouseMovement();

    return {};
}

SDispatchResult CKeybindManager::lockGroups(std::string args) {
    if (args == "lock" || args.empty() || args == "lockgroups")
        g_pKeybindManager->m_groupsLocked = true;
    else if (args == "toggle")
        g_pKeybindManager->m_groupsLocked = !g_pKeybindManager->m_groupsLocked;
    else
        g_pKeybindManager->m_groupsLocked = false;

    g_pEventManager->postEvent(SHyprIPCEvent{"lockgroups", g_pKeybindManager->m_groupsLocked ? "1" : "0"});
    g_pCompositor->updateAllWindowsAnimatedDecorationValues();

    return {};
}

SDispatchResult CKeybindManager::lockActiveGroup(std::string args) {
    const auto PWINDOW = Desktop::focusState()->window();

    if (!PWINDOW)
        return {.success = false, .error = "No window found"};

    if (!PWINDOW->m_group)
        return {.success = false, .error = "Not a group"};

    if (args == "lock")
        PWINDOW->m_group->setLocked(true);
    else if (args == "toggle")
        PWINDOW->m_group->setLocked(!PWINDOW->m_group->locked());
    else
        PWINDOW->m_group->setLocked(false);

    PWINDOW->updateDecorationValues();

    return {};
}

void CKeybindManager::moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowInDirection) {
    if (!pWindowInDirection->m_group || pWindowInDirection->m_group->denied())
        return;

    updateRelativeCursorCoords();

    if (pWindow->m_monitor != pWindowInDirection->m_monitor) {
        pWindow->moveToWorkspace(pWindowInDirection->m_workspace);
        pWindow->m_monitor = pWindowInDirection->m_monitor;
    }

    if (pWindow->m_group)
        pWindow->m_group->remove(pWindow);
    pWindowInDirection->m_group->add(pWindow);

    pWindowInDirection->m_group->setCurrent(pWindow);
    pWindow->updateWindowDecos();
    Desktop::focusState()->fullWindowFocus(pWindow, Desktop::FOCUS_REASON_KEYBIND);
    pWindow->warpCursor();

    g_pEventManager->postEvent(SHyprIPCEvent{"moveintogroup", std::format("{:x}", rc<uintptr_t>(pWindow.get()))});
}

void CKeybindManager::moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string& dir) {
    static auto BFOCUSREMOVEDWINDOW = CConfigValue<Hyprlang::INT>("group:focus_removed_window");

    if (!pWindow->m_group)
        return;

    WP<Desktop::View::CGroup> group = pWindow->m_group;

    const auto                direction = !dir.empty() ? Math::fromChar(dir[0]) : Math::DIRECTION_DEFAULT;

    pWindow->m_group->remove(pWindow, direction);

    if (*BFOCUSREMOVEDWINDOW || !group) {
        Desktop::focusState()->fullWindowFocus(pWindow, Desktop::FOCUS_REASON_KEYBIND);
        pWindow->warpCursor();
    } else {
        Desktop::focusState()->fullWindowFocus(group->current(), Desktop::FOCUS_REASON_KEYBIND);
        group->current()->warpCursor();
    }

    g_pEventManager->postEvent(SHyprIPCEvent{"moveoutofgroup", std::format("{:x}", rc<uintptr_t>(pWindow.get()))});
}

SDispatchResult CKeybindManager::moveIntoGroup(std::string args) {
    static auto PIGNOREGROUPLOCK = CConfigValue<Hyprlang::INT>("binds:ignore_group_lock");

    if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_groupsLocked)
        return {};

    Math::eDirection dir = Math::fromChar(args[0]);
    if (dir == Math::DIRECTION_DEFAULT) {
        Log::logger->log(Log::ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0]);
        return {.success = false, .error = std::format("Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0])};
    }

    const auto PWINDOW = Desktop::focusState()->window();

    if (!PWINDOW)
        return {};

    auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, dir);

    if (!PWINDOWINDIR || !PWINDOWINDIR->m_group)
        return {};

    const auto GROUP = PWINDOWINDIR->m_group;

    // Do not move window into locked group if binds:ignore_group_lock is false
    if (!*PIGNOREGROUPLOCK && (GROUP->locked() || (PWINDOW->m_group && PWINDOW->m_group->locked())))
        return {};

    moveWindowIntoGroup(PWINDOW, PWINDOWINDIR);

    return {};
}

SDispatchResult CKeybindManager::moveIntoOrCreateGroup(std::string args) {
    static auto PIGNOREGROUPLOCK = CConfigValue<Hyprlang::INT>("binds:ignore_group_lock");

    if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_groupsLocked)
        return {};

    Math::eDirection dir = Math::fromChar(args[0]);
    if (dir == Math::DIRECTION_DEFAULT) {
        Log::logger->log(Log::ERR, "Cannot move into or create group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0]);
        return {.success = false, .error = std::format("Cannot move into or create group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0])};
    }

    const auto PWINDOW = Desktop::focusState()->window();

    if (!PWINDOW)
        return {};

    auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, dir);

    if (!PWINDOWINDIR)
        return {};

    if (!PWINDOWINDIR->m_group) {
        if (PWINDOWINDIR->isFullscreen())
            return {};

        PWINDOWINDIR->m_group = Desktop::View::CGroup::create({PWINDOWINDIR});
    }

    const auto GROUP = PWINDOWINDIR->m_group;

    if (!*PIGNOREGROUPLOCK && (GROUP->locked() || (PWINDOW->m_group && PWINDOW->m_group->locked())))
        return {};

    moveWindowIntoGroup(PWINDOW, PWINDOWINDIR);

    return {};
}

SDispatchResult CKeybindManager::moveOutOfGroup(std::string args) {
    static auto PIGNOREGROUPLOCK = CConfigValue<Hyprlang::INT>("binds:ignore_group_lock");

    if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_groupsLocked)
        return {.success = false, .error = "Groups locked"};

    PHLWINDOW PWINDOW = nullptr;

    if (args != "active" && args.length() > 1)
        PWINDOW = g_pCompositor->getWindowByRegex(args);
    else
        PWINDOW = Desktop::focusState()->window();

    if (!PWINDOW)
        return {.success = false, .error = "No window found"};

    if (!PWINDOW->m_group)
        return {.success = false, .error = "Window not in a group"};

    moveWindowOutOfGroup(PWINDOW);

    return {};
}

SDispatchResult CKeybindManager::moveWindowOrGroup(std::string args) {
    static auto      PIGNOREGROUPLOCK = CConfigValue<Hyprlang::INT>("binds:ignore_group_lock");

    Math::eDirection dir = Math::fromChar(args[0]);
    if (dir == Math::DIRECTION_DEFAULT) {
        Log::logger->log(Log::ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0]);
        return {.success = false, .error = std::format("Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", args[0])};
    }

    const auto PWINDOW = Desktop::focusState()->window();
    if (!PWINDOW)
        return {.success = false, .error = "No window found"};

    if (PWINDOW->isFullscreen())
        return {};

    if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_groupsLocked) {
        g_layoutManager->moveInDirection(PWINDOW->layoutTarget(), args);
        return {};
    }

    const auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, dir);

    const bool ISWINDOWGROUP       = PWINDOW->m_group;
    const bool ISWINDOWGROUPLOCKED = ISWINDOWGROUP && PWINDOW->m_group->locked();
    const bool ISWINDOWGROUPSINGLE = ISWINDOWGROUP && PWINDOW->m_group->size() == 1;
    const bool ISWINDOWGROUPDENIED = ISWINDOWGROUP && PWINDOW->m_group->denied();

    updateRelativeCursorCoords();

    // note: PWINDOWINDIR is not null implies !PWINDOW->m_isFloating
    if (PWINDOWINDIR && PWINDOWINDIR->m_group) { // target is group
        if (!*PIGNOREGROUPLOCK && (PWINDOWINDIR->m_group->locked() || ISWINDOWGROUPLOCKED || ISWINDOWGROUPDENIED)) {
            g_layoutManager->moveInDirection(PWINDOW->layoutTarget(), args);
            PWINDOW->warpCursor();
        } else
            moveWindowIntoGroup(PWINDOW, PWINDOWINDIR);
    } else if (PWINDOWINDIR) { // target is regular window
        if ((!*PIGNOREGROUPLOCK && ISWINDOWGROUPLOCKED) || !ISWINDOWGROUP || (ISWINDOWGROUPSINGLE && PWINDOW->m_groupRules & Desktop::View::GROUP_SET_ALWAYS)) {
            g_layoutManager->moveInDirection(PWINDOW->layoutTarget(), args);
            PWINDOW->warpCursor();
        } else
            moveWindowOutOfGroup(PWINDOW, args);
    } else if ((*PIGNOREGROUPLOCK || !ISWINDOWGROUPLOCKED) && ISWINDOWGROUP) { // no target window
        moveWindowOutOfGroup(PWINDOW, args);
    } else if (!PWINDOWINDIR && !ISWINDOWGROUP) { // no target in dir and not in group
        g_layoutManager->moveInDirection(PWINDOW->layoutTarget(), args);
        PWINDOW->warpCursor();
    }

    PWINDOW->updateDecorationValues();

    return {};
}

SDispatchResult CKeybindManager::setIgnoreGroupLock(std::string args) {
    // FIXME: this is no longer possible like this. It's redundant anyways. Can be easily scripted / lua'd
    // static auto      PIGNOREGROUPLOCK = CConfigValue<Hyprlang::INT>("binds:ignore_group_lock");

    // if (args == "toggle")
    //     *PIGNOREGROUPLOCK = !*PIGNOREGROUPLOCK;
    // else
    //     *PIGNOREGROUPLOCK = args == "on";

    // g_pEventManager->postEvent(SHyprIPCEvent{"ignoregrouplock", std::to_string(**PIGNOREGROUPLOCK)});

    return {};
}

SDispatchResult CKeybindManager::denyWindowFromGroup(std::string args) {
    const auto PWINDOW = Desktop::focusState()->window();
    if (!PWINDOW || (PWINDOW && PWINDOW->m_group))
        return {};

    if (args == "toggle")
        PWINDOW->m_group->setDenied(!PWINDOW->m_group->denied());
    else
        PWINDOW->m_group->setDenied(args == "on");

    PWINDOW->updateDecorationValues();

    return {};
}

SDispatchResult CKeybindManager::global(std::string args) {
    const auto APPID = args.substr(0, args.find_first_of(':'));
    const auto NAME  = args.substr(args.find_first_of(':') + 1);

    if (NAME.empty())
        return {};

    if (!PROTO::globalShortcuts->isTaken(APPID, NAME))
        return {};

    PROTO::globalShortcuts->sendGlobalShortcutEvent(APPID, NAME, g_pKeybindManager->m_passPressed);

    return {};
}

SDispatchResult CKeybindManager::moveGroupWindow(std::string args) {
    const auto BACK = args == "b" || args == "prev";

    const auto PLASTWINDOW = Desktop::focusState()->window();

    if (!PLASTWINDOW)
        return {.success = false, .error = "No window found"};

    if (!PLASTWINDOW->m_group)
        return {.success = false, .error = "Window not in a group"};

    const auto GROUP = PLASTWINDOW->m_group;

    if (BACK)
        GROUP->swapWithLast();
    else
        GROUP->swapWithNext();

    return {};
}

SDispatchResult CKeybindManager::event(std::string args) {
    g_pEventManager->postEvent(SHyprIPCEvent{"custom", args});
    return {};
}

#include <utility>
#include <type_traits>

template <typename T>
static void parsePropTrivial(Desktop::Types::COverridableVar<T>& prop, const std::string& s) {
    static_assert(std::is_same_v<T, bool> || std::is_same_v<T, Hyprlang::INT> || std::is_same_v<T, int> || std::is_same_v<T, Hyprlang::FLOAT> || std::is_same_v<T, std::string>,
                  "Invalid type passed to parsePropTrivial");

    if (s == "unset") {
        prop.unset(Desktop::Types::PRIORITY_SET_PROP);
        return;
    }

    try {
        if constexpr (std::is_same_v<T, bool>) {
            if (s == "toggle")
                prop.increment(true, Desktop::Types::PRIORITY_SET_PROP);
            else
                prop = Desktop::Types::COverridableVar<T>(truthy(s), Desktop::Types::PRIORITY_SET_PROP);
        } else if constexpr (std::is_same_v<T, Hyprlang::INT> || std::is_same_v<T, int>) {
            if (s.starts_with("relative")) {
                const auto VAL = std::stoi(s.substr(s.find(' ') + 1));
                prop.increment(VAL, Desktop::Types::PRIORITY_SET_PROP);
            } else
                prop = Desktop::Types::COverridableVar<T>(std::stoull(s), Desktop::Types::PRIORITY_SET_PROP);
        } else if constexpr (std::is_same_v<T, Hyprlang::FLOAT>) {
            if (s.starts_with("relative")) {
                const auto VAL = std::stof(s.substr(s.find(' ') + 1));
                prop.increment(VAL, Desktop::Types::PRIORITY_SET_PROP);
            } else
                prop = Desktop::Types::COverridableVar<T>(std::stof(s), Desktop::Types::PRIORITY_SET_PROP);
        } else if constexpr (std::is_same_v<T, std::string>)
            prop = Desktop::Types::COverridableVar<T>(s, Desktop::Types::PRIORITY_SET_PROP);
    } catch (...) { Log::logger->log(Log::ERR, "Hyprctl: parsePropTrivial: failed to parse setprop for {}", s); }
}

SDispatchResult CKeybindManager::setProp(std::string args) {
    CVarList vars(args, 3, ' ');

    if (vars.size() < 3)
        return {.success = false, .error = "Not enough args"};

    const auto PLASTWINDOW = Desktop::focusState()->window();
    const auto PWINDOW     = g_pCompositor->getWindowByRegex(vars[0]);

    if (!PWINDOW)
        return {.success = false, .error = "Window not found"};

    const auto PROP = vars[1];
    const auto VAL  = vars[2];

    bool       noFocus = PWINDOW->m_ruleApplicator->noFocus().valueOrDefault();

    try {
        if (PROP == "max_size") {
            const auto SIZE = PWINDOW->calculateExpression(VAL);
            if (!SIZE) {
                Log::logger->log(Log::ERR, "failed to parse {} as an expression", VAL);
                throw "failed to parse expression";
            }
            PWINDOW->m_ruleApplicator->maxSizeOverride(Desktop::Types::COverridableVar(*SIZE, Desktop::Types::PRIORITY_SET_PROP));
            PWINDOW->clampWindowSize(std::nullopt, PWINDOW->m_ruleApplicator->maxSize().value());
            PWINDOW->setHidden(false);
        } else if (PROP == "min_size") {
            const auto SIZE = PWINDOW->calculateExpression(VAL);
            if (!SIZE) {
                Log::logger->log(Log::ERR, "failed to parse {} as an expression", VAL);
                throw "failed to parse expression";
            }
            PWINDOW->m_ruleApplicator->minSizeOverride(Desktop::Types::COverridableVar(*SIZE, Desktop::Types::PRIORITY_SET_PROP));
            PWINDOW->clampWindowSize(PWINDOW->m_ruleApplicator->minSize().value(), std::nullopt);
            PWINDOW->setHidden(false);
        } else if (PROP == "active_border_color" || PROP == "inactive_border_color") {
            Config::CGradientValueData colorData = {};
            if (vars.size() > 4) {
                for (int i = 3; i < sc<int>(vars.size()); ++i) {
                    const auto TOKEN = vars[i];
                    if (TOKEN.ends_with("deg"))
                        colorData.m_angle = std::stoi(TOKEN.substr(0, TOKEN.size() - 3)) * (PI / 180.0);
                    else
                        configStringToInt(TOKEN).and_then([&colorData](const auto& e) {
                            colorData.m_colors.push_back(e);
                            return std::invoke_result_t<decltype(::configStringToInt), const std::string&>(1);
                        });
                }
            } else if (VAL != "-1")
                configStringToInt(VAL).and_then([&colorData](const auto& e) {
                    colorData.m_colors.push_back(e);
                    return std::invoke_result_t<decltype(::configStringToInt), const std::string&>(1);
                });

            colorData.updateColorsOk();

            if (PROP == "active_border_color")
                PWINDOW->m_ruleApplicator->activeBorderColorOverride(Desktop::Types::COverridableVar(colorData, Desktop::Types::PRIORITY_SET_PROP));
            else
                PWINDOW->m_ruleApplicator->inactiveBorderColorOverride(Desktop::Types::COverridableVar(colorData, Desktop::Types::PRIORITY_SET_PROP));
        } else if (PROP == "opacity") {
            PWINDOW->m_ruleApplicator->alphaOverride(Desktop::Types::COverridableVar(
                Desktop::Types::SAlphaValue{std::stof(VAL), PWINDOW->m_ruleApplicator->alpha().valueOrDefault().overridden}, Desktop::Types::PRIORITY_SET_PROP));
        } else if (PROP == "opacity_inactive") {
            PWINDOW->m_ruleApplicator->alphaInactiveOverride(Desktop::Types::COverridableVar(
                Desktop::Types::SAlphaValue{std::stof(VAL), PWINDOW->m_ruleApplicator->alphaInactive().valueOrDefault().overridden}, Desktop::Types::PRIORITY_SET_PROP));
        } else if (PROP == "opacity_fullscreen") {
            PWINDOW->m_ruleApplicator->alphaFullscreenOverride(Desktop::Types::COverridableVar(
                Desktop::Types::SAlphaValue{std::stof(VAL), PWINDOW->m_ruleApplicator->alphaFullscreen().valueOrDefault().overridden}, Desktop::Types::PRIORITY_SET_PROP));
        } else if (PROP == "opacity_override") {
            PWINDOW->m_ruleApplicator->alphaOverride(Desktop::Types::COverridableVar(
                Desktop::Types::SAlphaValue{PWINDOW->m_ruleApplicator->alpha().valueOrDefault().alpha, sc<bool>(configStringToInt(VAL).value_or(0))},
                Desktop::Types::PRIORITY_SET_PROP));
        } else if (PROP == "opacity_inactive_override") {
            PWINDOW->m_ruleApplicator->alphaInactiveOverride(Desktop::Types::COverridableVar(
                Desktop::Types::SAlphaValue{PWINDOW->m_ruleApplicator->alphaInactive().valueOrDefault().alpha, sc<bool>(configStringToInt(VAL).value_or(0))},
                Desktop::Types::PRIORITY_SET_PROP));
        } else if (PROP == "opacity_fullscreen_override") {
            PWINDOW->m_ruleApplicator->alphaFullscreenOverride(Desktop::Types::COverridableVar(
                Desktop::Types::SAlphaValue{PWINDOW->m_ruleApplicator->alphaFullscreen().valueOrDefault().alpha, sc<bool>(configStringToInt(VAL).value_or(0))},
                Desktop::Types::PRIORITY_SET_PROP));
        } else if (PROP == "allows_input")
            parsePropTrivial(PWINDOW->m_ruleApplicator->allowsInput(), VAL);
        else if (PROP == "decorate")
            parsePropTrivial(PWINDOW->m_ruleApplicator->decorate(), VAL);
        else if (PROP == "focus_on_activate")
            parsePropTrivial(PWINDOW->m_ruleApplicator->focusOnActivate(), VAL);
        else if (PROP == "keep_aspect_ratio")
            parsePropTrivial(PWINDOW->m_ruleApplicator->keepAspectRatio(), VAL);
        else if (PROP == "nearest_neighbor")
            parsePropTrivial(PWINDOW->m_ruleApplicator->nearestNeighbor(), VAL);
        else if (PROP == "no_anim")
            parsePropTrivial(PWINDOW->m_ruleApplicator->noAnim(), VAL);
        else if (PROP == "no_blur")
            parsePropTrivial(PWINDOW->m_ruleApplicator->noBlur(), VAL);
        else if (PROP == "no_dim")
            parsePropTrivial(PWINDOW->m_ruleApplicator->noDim(), VAL);
        else if (PROP == "no_focus")
            parsePropTrivial(PWINDOW->m_ruleApplicator->noFocus(), VAL);
        else if (PROP == "no_max_size")
            parsePropTrivial(PWINDOW->m_ruleApplicator->noMaxSize(), VAL);
        else if (PROP == "no_shadow")
            parsePropTrivial(PWINDOW->m_ruleApplicator->noShadow(), VAL);
        else if (PROP == "no_shortcuts_inhibit")
            parsePropTrivial(PWINDOW->m_ruleApplicator->noShortcutsInhibit(), VAL);
        else if (PROP == "dim_around")
            parsePropTrivial(PWINDOW->m_ruleApplicator->dimAround(), VAL);
        else if (PROP == "opaque")
            parsePropTrivial(PWINDOW->m_ruleApplicator->opaque(), VAL);
        else if (PROP == "force_rgbx")
            parsePropTrivial(PWINDOW->m_ruleApplicator->RGBX(), VAL);
        else if (PROP == "sync_fullscreen")
            parsePropTrivial(PWINDOW->m_ruleApplicator->syncFullscreen(), VAL);
        else if (PROP == "immediate")
            parsePropTrivial(PWINDOW->m_ruleApplicator->tearing(), VAL);
        else if (PROP == "xray")
            parsePropTrivial(PWINDOW->m_ruleApplicator->xray(), VAL);
        else if (PROP == "render_unfocused")
            parsePropTrivial(PWINDOW->m_ruleApplicator->renderUnfocused(), VAL);
        else if (PROP == "no_follow_mouse")
            parsePropTrivial(PWINDOW->m_ruleApplicator->noFollowMouse(), VAL);
        else if (PROP == "no_screen_share")
            parsePropTrivial(PWINDOW->m_ruleApplicator->noScreenShare(), VAL);
        else if (PROP == "no_vrr")
            parsePropTrivial(PWINDOW->m_ruleApplicator->noVRR(), VAL);
        else if (PROP == "persistent_size")
            parsePropTrivial(PWINDOW->m_ruleApplicator->persistentSize(), VAL);
        else if (PROP == "stay_focused")
            parsePropTrivial(PWINDOW->m_ruleApplicator->stayFocused(), VAL);
        else if (PROP == "idle_inhibit")
            parsePropTrivial(PWINDOW->m_ruleApplicator->idleInhibitMode(), VAL);
        else if (PROP == "border_size")
            parsePropTrivial(PWINDOW->m_ruleApplicator->borderSize(), VAL);
        else if (PROP == "rounding")
            parsePropTrivial(PWINDOW->m_ruleApplicator->rounding(), VAL);
        else if (PROP == "rounding_power")
            parsePropTrivial(PWINDOW->m_ruleApplicator->roundingPower(), VAL);
        else if (PROP == "scroll_mouse")
            parsePropTrivial(PWINDOW->m_ruleApplicator->scrollMouse(), VAL);
        else if (PROP == "scroll_touchpad")
            parsePropTrivial(PWINDOW->m_ruleApplicator->scrollTouchpad(), VAL);
        else if (PROP == "animation")
            parsePropTrivial(PWINDOW->m_ruleApplicator->animationStyle(), VAL);
        else
            return {.success = false, .error = "prop not found"};

    } catch (std::exception& e) { return {.success = false, .error = std::format("Error parsing prop value: {}", std::string(e.what()))}; }

    g_pCompositor->updateAllWindowsAnimatedDecorationValues();

    if (PWINDOW->m_ruleApplicator->noFocus().valueOrDefault() != noFocus) {
        // FIXME: what the fuck is going on here? -vax
        Desktop::focusState()->rawWindowFocus(nullptr, Desktop::FOCUS_REASON_KEYBIND);
        Desktop::focusState()->fullWindowFocus(PWINDOW, Desktop::FOCUS_REASON_KEYBIND);
        Desktop::focusState()->fullWindowFocus(PLASTWINDOW, Desktop::FOCUS_REASON_KEYBIND);
    }

    if (PROP == "no_vrr")
        Config::monitorRuleMgr()->ensureVRR();

    for (auto const& m : g_pCompositor->m_monitors) {
        if (m->m_activeWorkspace)
            m->m_activeWorkspace->m_space->recalculate();
    }

    return {};
}

SDispatchResult CKeybindManager::forceIdle(std::string args) {
    std::optional<float> duration = getPlusMinusKeywordResult(args, 0);

    if (!duration.has_value()) {
        Log::logger->log(Log::ERR, "Duration invalid in forceIdle!");
        return {.success = false, .error = "Duration invalid in forceIdle!"};
    }

    PROTO::idle->setTimers(duration.value() * 1000.0);

    return {};
}

SDispatchResult CKeybindManager::sendkeystate(std::string args) {
    // args=<NEW_MODKEYS><NEW_KEY><STATE>[,WINDOW_RULES]
    const auto ARGS = CVarList(args, 4);
    if (ARGS.size() != 4) {
        Log::logger->log(Log::ERR, "sendkeystate: invalid args");
        return {.success = false, .error = "sendkeystate: invalid args"};
    }

    const auto STATE = ARGS[2];

    if (STATE != "down" && STATE != "repeat" && STATE != "up") {
        Log::logger->log(Log::ERR, "sendkeystate: invalid state, must be 'down', 'repeat', or 'up'");
        return {.success = false, .error = "sendkeystate: invalid state, must be 'down', 'repeat', or 'up'"};
    }

    std::string modifiedArgs = ARGS[0] + "," + ARGS[1] + "," + ARGS[3];

    const int   oldPassPressed = g_pKeybindManager->m_passPressed;

    if (STATE == "down")
        g_pKeybindManager->m_passPressed = 1;
    else if (STATE == "up")
        g_pKeybindManager->m_passPressed = 0;
    else if (STATE == "repeat")
        g_pKeybindManager->m_passPressed = 1;

    auto result = sendshortcut(modifiedArgs);

    if (STATE == "repeat" && result.success)
        result = sendshortcut(modifiedArgs);

    g_pKeybindManager->m_passPressed = oldPassPressed;

    if (!result.success && !result.error.empty()) {
        size_t pos = result.error.find("sendshortcut:");
        if (pos != std::string::npos)
            result.error = "sendkeystate:" + result.error.substr(pos + 13);
    }

    return result;
}
