// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "keyboard_report_util.hpp"
#include "keycode.h"
#include "test_common.hpp"
#include "action_tapping.h"
#include "test_fixture.hpp"
#include "test_keymap_key.hpp"

using testing::_;
using testing::AnyNumber;
using testing::InSequence;

extern "C" bool get_speculative_hold(uint16_t keycode, keyrecord_t *record) {
    return true;
}

class SpeculativeHoldFlowTapTest : public TestFixture {};

TEST_F(SpeculativeHoldFlowTapTest, tap_mod_tap) {
    TestDriver driver;
    InSequence s;
    auto       mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_P));

    set_keymap({mod_tap_key});

    // Press mod-tap-hold key. Mod is held speculatively.
    EXPECT_REPORT(driver, (KC_LSFT));
    mod_tap_key.press();
    idle_for(10);
    VERIFY_AND_CLEAR(driver);
    EXPECT_EQ(get_speculative_mods(), MOD_BIT_LSHIFT);

    // Release mod-tap-hold key.
    EXPECT_EMPTY_REPORT(driver); // Speculative mod canceled.
    EXPECT_REPORT(driver, (KC_P));
    EXPECT_EMPTY_REPORT(driver);
    mod_tap_key.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_speculative_mods(), 0);
    EXPECT_EQ(get_mods(), 0);

    // Idle for tapping term of mod tap hold key.
    idle_for(TAPPING_TERM - 10);
    VERIFY_AND_CLEAR(driver);
}

TEST_F(SpeculativeHoldFlowTapTest, hold_two_mod_taps) {
    TestDriver driver;
    InSequence s;
    auto       mod_tap_key1 = KeymapKey(0, 1, 0, LCTL_T(KC_A));
    auto       mod_tap_key2 = KeymapKey(0, 2, 0, RALT_T(KC_B));

    set_keymap({mod_tap_key1, mod_tap_key2});

    // Press first mod-tap key.
    EXPECT_REPORT(driver, (KC_LCTL));
    mod_tap_key1.press();
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);
    EXPECT_EQ(get_speculative_mods(), MOD_BIT_LCTRL);

    // Press second mod-tap key.
    EXPECT_REPORT(driver, (KC_LCTL, KC_RALT));
    mod_tap_key2.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
    EXPECT_EQ(get_speculative_mods(), MOD_BIT_LCTRL | MOD_BIT_RALT);

    EXPECT_NO_REPORT(driver);
    idle_for(TAPPING_TERM + 1);
    VERIFY_AND_CLEAR(driver);
    EXPECT_EQ(get_speculative_mods(), 0);
    EXPECT_EQ(get_mods(), MOD_BIT_LCTRL | MOD_BIT_RALT);

    // Release first mod-tap key.
    EXPECT_REPORT(driver, (KC_RALT));
    mod_tap_key1.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Release second mod-tap key.
    EXPECT_EMPTY_REPORT(driver);
    mod_tap_key2.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
}

TEST_F(SpeculativeHoldFlowTapTest, two_mod_taps_same_mods) {
    TestDriver driver;
    InSequence s;
    auto       mod_tap_key1 = KeymapKey(0, 1, 0, GUI_T(KC_A));
    auto       mod_tap_key2 = KeymapKey(0, 2, 0, GUI_T(KC_B));

    set_keymap({mod_tap_key1, mod_tap_key2});

    // Press first mod-tap key.
    EXPECT_REPORT(driver, (KC_LGUI));
    mod_tap_key1.press();
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    // Tap second mod-tap key.
    EXPECT_NO_REPORT(driver);
    mod_tap_key2.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_REPORT(driver, (KC_LGUI, KC_B));
    EXPECT_REPORT(driver, (KC_LGUI));
    mod_tap_key2.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Release first mod-tap key.
    EXPECT_EMPTY_REPORT(driver);
    mod_tap_key1.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

// Test an input of quick distinct taps. All should be settled as tapped.
TEST_F(SpeculativeHoldFlowTapTest, distinct_taps) {
    TestDriver driver;
    InSequence s;
    auto       regular_key  = KeymapKey(0, 0, 0, KC_A);
    auto       mod_tap_key1 = KeymapKey(0, 1, 0, SFT_T(KC_B));
    auto       mod_tap_key2 = KeymapKey(0, 2, 0, CTL_T(KC_C));
    auto       mod_tap_key3 = KeymapKey(0, 3, 0, ALT_T(KC_D));

    set_keymap({regular_key, mod_tap_key1, mod_tap_key2, mod_tap_key3});

    // Tap regular key.
    EXPECT_REPORT(driver, (KC_A));
    EXPECT_EMPTY_REPORT(driver);
    tap_key(regular_key, FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    // Tap mod-tap 1.
    EXPECT_REPORT(driver, (KC_B));
    mod_tap_key1.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_EMPTY_REPORT(driver);
    idle_for(FLOW_TAP_TERM + 1);
    mod_tap_key1.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Tap mod-tap 2.
    EXPECT_REPORT(driver, (KC_C));
    mod_tap_key2.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_EMPTY_REPORT(driver);
    idle_for(FLOW_TAP_TERM + 1);
    mod_tap_key2.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Tap mod-tap 3.
    EXPECT_REPORT(driver, (KC_D));
    mod_tap_key3.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_EMPTY_REPORT(driver);
    idle_for(FLOW_TAP_TERM + 1);
    mod_tap_key3.release();
    idle_for(FLOW_TAP_TERM + 1); // Pause between taps.
    VERIFY_AND_CLEAR(driver);

    // Tap mod-tap 1.
    EXPECT_REPORT(driver, (KC_LSFT));
    mod_tap_key1.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_EMPTY_REPORT(driver);
    EXPECT_REPORT(driver, (KC_B));
    EXPECT_EMPTY_REPORT(driver);
    idle_for(FLOW_TAP_TERM + 1);
    mod_tap_key1.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Tap mod-tap 2.
    EXPECT_REPORT(driver, (KC_C));
    mod_tap_key2.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_EMPTY_REPORT(driver);
    idle_for(TAPPING_TERM + 1);
    mod_tap_key2.release();
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

// By default, Flow Tap is disabled when mods other than Shift and AltGr are on.
TEST_F(SpeculativeHoldFlowTapTest, hotkey_taps) {
    TestDriver driver;
    InSequence s;
    auto       ctrl_key    = KeymapKey(0, 0, 0, KC_LCTL);
    auto       shft_key    = KeymapKey(0, 1, 0, KC_LSFT);
    auto       alt_key     = KeymapKey(0, 2, 0, KC_LALT);
    auto       gui_key     = KeymapKey(0, 3, 0, KC_LGUI);
    auto       regular_key = KeymapKey(0, 4, 0, KC_A);
    auto       mod_tap_key = KeymapKey(0, 5, 0, RCTL_T(KC_B));

    set_keymap({ctrl_key, shft_key, alt_key, gui_key, regular_key, mod_tap_key});

    for (KeymapKey *mod_key : {&ctrl_key, &alt_key, &gui_key}) {
        // Hold mod key.
        EXPECT_REPORT(driver, (mod_key->code));
        mod_key->press();
        run_one_scan_loop();

        // Tap regular key.
        EXPECT_REPORT(driver, (mod_key->code, KC_A));
        regular_key.press();
        run_one_scan_loop();
        VERIFY_AND_CLEAR(driver);

        EXPECT_REPORT(driver, (mod_key->code));
        regular_key.release();
        run_one_scan_loop();
        VERIFY_AND_CLEAR(driver);

        // Press mod-tap, where Flow Tap is disabled due to the held mod.
        EXPECT_REPORT(driver, (mod_key->code, KC_RCTL));
        mod_tap_key.press();
        idle_for(TAPPING_TERM + 1);
        VERIFY_AND_CLEAR(driver);

        // Release mod-tap.
        EXPECT_REPORT(driver, (mod_key->code));
        mod_tap_key.release();
        run_one_scan_loop();

        // Release mod key.
        EXPECT_EMPTY_REPORT(driver);
        mod_key->release();
        run_one_scan_loop();
        VERIFY_AND_CLEAR(driver);
    }

    // Hold Shift key.
    EXPECT_REPORT(driver, (KC_LSFT));
    shft_key.press();
    run_one_scan_loop();

    // Tap regular key.
    EXPECT_REPORT(driver, (KC_LSFT, KC_A));
    regular_key.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_REPORT(driver, (KC_LSFT));
    regular_key.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Press mod-tap, where Flow Tap applies to settle as tapped.
    EXPECT_REPORT(driver, (KC_LSFT, KC_B));
    mod_tap_key.press();
    idle_for(TAPPING_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    // Release mod-tap.
    EXPECT_REPORT(driver, (KC_LSFT));
    mod_tap_key.release();
    run_one_scan_loop();

    // Release Shift key.
    EXPECT_EMPTY_REPORT(driver);
    shft_key.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

// Test input with two mod-taps in a rolled press quickly after a regular key.
TEST_F(SpeculativeHoldFlowTapTest, rolled_press) {
    TestDriver driver;
    InSequence s;
    auto       regular_key  = KeymapKey(0, 0, 0, KC_A);
    auto       mod_tap_key1 = KeymapKey(0, 1, 0, SFT_T(KC_B));
    auto       mod_tap_key2 = KeymapKey(0, 2, 0, CTL_T(KC_C));

    set_keymap({regular_key, mod_tap_key1, mod_tap_key2});

    // Tap regular key.
    EXPECT_REPORT(driver, (KC_A));
    EXPECT_EMPTY_REPORT(driver);
    tap_key(regular_key);
    VERIFY_AND_CLEAR(driver);

    // Press mod-tap key 1 quickly after regular key. The mod-tap should settle
    // immediately as tapped, sending `KC_B`.
    EXPECT_REPORT(driver, (KC_B));
    mod_tap_key1.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Press mod-tap key 2 quickly.
    EXPECT_REPORT(driver, (KC_B, KC_C));
    mod_tap_key2.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Hold for longer than the tapping term.
    EXPECT_NO_REPORT(driver);
    idle_for(TAPPING_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    // Release mod-tap keys.
    EXPECT_REPORT(driver, (KC_C));
    EXPECT_EMPTY_REPORT(driver);
    mod_tap_key1.release();
    run_one_scan_loop();
    mod_tap_key2.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

TEST_F(SpeculativeHoldFlowTapTest, long_flow_tap_settled_as_held) {
    TestDriver driver;
    InSequence s;
    auto       regular_key = KeymapKey(0, 0, 0, KC_A);
    auto       mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_B));

    set_keymap({regular_key, mod_tap_key});

    // Tap regular key.
    EXPECT_REPORT(driver, (KC_A));
    EXPECT_EMPTY_REPORT(driver);
    tap_key(regular_key);
    VERIFY_AND_CLEAR(driver);

    EXPECT_NO_REPORT(driver);
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    // Press mod-tap key.
    EXPECT_REPORT(driver, (KC_LSFT));
    mod_tap_key.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Hold for the tapping term.
    EXPECT_NO_REPORT(driver);
    idle_for(TAPPING_TERM);
    VERIFY_AND_CLEAR(driver);

    // Release mod-tap key.
    EXPECT_EMPTY_REPORT(driver);
    mod_tap_key.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

TEST_F(SpeculativeHoldFlowTapTest, holding_multiple_mod_taps) {
    TestDriver driver;
    InSequence s;
    auto       regular_key  = KeymapKey(0, 0, 0, KC_A);
    auto       mod_tap_key1 = KeymapKey(0, 1, 0, SFT_T(KC_B));
    auto       mod_tap_key2 = KeymapKey(0, 2, 0, CTL_T(KC_C));

    set_keymap({regular_key, mod_tap_key1, mod_tap_key2});

    // Tap regular key.
    EXPECT_REPORT(driver, (KC_A));
    EXPECT_EMPTY_REPORT(driver);
    tap_key(regular_key);
    VERIFY_AND_CLEAR(driver);

    EXPECT_NO_REPORT(driver);
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    // Press mod-tap keys.
    EXPECT_REPORT(driver, (KC_LSFT));
    mod_tap_key1.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_REPORT(driver, (KC_LSFT, KC_LCTL));
    mod_tap_key2.press();
    idle_for(TAPPING_TERM - 5); // Hold almost until tapping term.
    VERIFY_AND_CLEAR(driver);

    // Press regular key.
    EXPECT_REPORT(driver, (KC_LSFT, KC_LCTL, KC_A));
    regular_key.press();
    idle_for(10);
    VERIFY_AND_CLEAR(driver);

    // Release keys.
    EXPECT_REPORT(driver, (KC_LSFT, KC_LCTL));
    EXPECT_REPORT(driver, (KC_LCTL));
    EXPECT_EMPTY_REPORT(driver);
    regular_key.release();
    run_one_scan_loop();
    mod_tap_key1.release();
    run_one_scan_loop();
    mod_tap_key2.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

TEST_F(SpeculativeHoldFlowTapTest, holding_mod_tap_with_regular_mod) {
    TestDriver driver;
    InSequence s;
    auto       regular_key = KeymapKey(0, 0, 0, KC_A);
    auto       mod_key     = KeymapKey(0, 1, 0, KC_LSFT);
    auto       mod_tap_key = KeymapKey(0, 2, 0, CTL_T(KC_C));

    set_keymap({regular_key, mod_key, mod_tap_key});

    // Tap regular key.
    EXPECT_REPORT(driver, (KC_A));
    EXPECT_EMPTY_REPORT(driver);
    tap_key(regular_key);
    VERIFY_AND_CLEAR(driver);

    EXPECT_NO_REPORT(driver);
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    // Press mod and mod-tap keys.
    EXPECT_REPORT(driver, (KC_LSFT));
    mod_key.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_REPORT(driver, (KC_LSFT, KC_LCTL));
    mod_tap_key.press();
    idle_for(TAPPING_TERM - 5); // Hold almost until tapping term.
    VERIFY_AND_CLEAR(driver);

    // Press regular key.
    EXPECT_REPORT(driver, (KC_LSFT, KC_LCTL, KC_A));
    regular_key.press();
    idle_for(10);
    VERIFY_AND_CLEAR(driver);

    // Release keys.
    EXPECT_REPORT(driver, (KC_LSFT, KC_LCTL));
    EXPECT_REPORT(driver, (KC_LCTL));
    EXPECT_EMPTY_REPORT(driver);
    regular_key.release();
    run_one_scan_loop();
    mod_key.release();
    run_one_scan_loop();
    mod_tap_key.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

TEST_F(SpeculativeHoldFlowTapTest, layer_tap_ignored_with_disabled_key) {
    TestDriver driver;
    InSequence s;
    auto       no_key        = KeymapKey(0, 0, 0, KC_NO);
    auto       regular_key   = KeymapKey(1, 0, 0, KC_ESC);
    auto       layer_tap_key = KeymapKey(0, 1, 0, LT(1, KC_A));
    auto       mod_tap_key   = KeymapKey(0, 2, 0, CTL_T(KC_B));

    set_keymap({no_key, regular_key, layer_tap_key, mod_tap_key});

    EXPECT_REPORT(driver, (KC_ESC));
    EXPECT_EMPTY_REPORT(driver);
    layer_tap_key.press();
    idle_for(TAPPING_TERM + 1);
    tap_key(regular_key);
    layer_tap_key.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_REPORT(driver, (KC_LCTL));
    mod_tap_key.press();
    idle_for(TAPPING_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    EXPECT_EMPTY_REPORT(driver);
    mod_tap_key.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

TEST_F(SpeculativeHoldFlowTapTest, layer_tap_ignored_with_disabled_key_complex) {
    TestDriver driver;
    InSequence s;
    auto       regular_key1  = KeymapKey(0, 0, 0, KC_Q);
    auto       layer_tap_key = KeymapKey(0, 1, 0, LT(1, KC_SPC));
    auto       mod_tap_key1  = KeymapKey(0, 2, 0, CTL_T(KC_T));
    // Place RALT_T(KC_I), where Flow Tap is enabled, in the same position on
    // layer 0 as KC_RGHT, where Flow Tap is disabled. This tests that Flow Tap
    // tracks the keycode from the correct layer.
    auto mod_tap_key2 = KeymapKey(0, 3, 0, RALT_T(KC_I));
    auto regular_key2 = KeymapKey(1, 3, 0, KC_RGHT);

    set_keymap({regular_key1, layer_tap_key, mod_tap_key1, mod_tap_key2, regular_key2});

    // Tap regular key 1.
    EXPECT_REPORT(driver, (KC_Q));
    EXPECT_EMPTY_REPORT(driver);
    tap_key(regular_key1);
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    // Hold layer-tap key.
    EXPECT_NO_REPORT(driver);
    layer_tap_key.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Tap regular key 2.
    EXPECT_REPORT(driver, (KC_RALT));
    EXPECT_EMPTY_REPORT(driver);
    EXPECT_REPORT(driver, (KC_RGHT));
    EXPECT_EMPTY_REPORT(driver);
    tap_key(regular_key2);
    VERIFY_AND_CLEAR(driver);

    // Release layer-tap key.
    EXPECT_NO_REPORT(driver);
    layer_tap_key.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Quickly hold mod-tap key 1.
    EXPECT_REPORT(driver, (KC_LCTL));
    mod_tap_key1.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_REPORT(driver, (KC_LCTL, KC_Q));
    EXPECT_REPORT(driver, (KC_LCTL));
    tap_key(regular_key1);
    VERIFY_AND_CLEAR(driver);

    EXPECT_EMPTY_REPORT(driver);
    mod_tap_key1.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

TEST_F(SpeculativeHoldFlowTapTest, layer_tap_ignored_with_enabled_key) {
    TestDriver driver;
    InSequence s;
    auto       no_key        = KeymapKey(0, 0, 0, KC_NO);
    auto       regular_key   = KeymapKey(1, 0, 0, KC_C);
    auto       layer_tap_key = KeymapKey(0, 1, 0, LT(1, KC_A));
    auto       mod_tap_key   = KeymapKey(0, 2, 0, CTL_T(KC_B));

    set_keymap({no_key, regular_key, layer_tap_key, mod_tap_key});

    EXPECT_REPORT(driver, (KC_C));
    EXPECT_EMPTY_REPORT(driver);
    layer_tap_key.press();
    idle_for(TAPPING_TERM + 1);
    tap_key(regular_key);
    layer_tap_key.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_REPORT(driver, (KC_B));
    mod_tap_key.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_EMPTY_REPORT(driver);
    idle_for(TAPPING_TERM + 1);
    mod_tap_key.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

TEST_F(SpeculativeHoldFlowTapTest, quick_tap) {
    TestDriver driver;
    InSequence s;
    auto       mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_A));

    set_keymap({mod_tap_key});

    EXPECT_REPORT(driver, (KC_LSFT));
    EXPECT_EMPTY_REPORT(driver);
    EXPECT_REPORT(driver, (KC_A));
    EXPECT_EMPTY_REPORT(driver);
    tap_key(mod_tap_key);
    VERIFY_AND_CLEAR(driver);

    EXPECT_REPORT(driver, (KC_A));
    mod_tap_key.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_NO_REPORT(driver);
    idle_for(TAPPING_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    // Release mod-tap key.
    EXPECT_EMPTY_REPORT(driver);
    mod_tap_key.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

TEST_F(SpeculativeHoldFlowTapTest, rolling_mt_mt) {
    TestDriver driver;
    InSequence s;
    auto       mod_tap_key1 = KeymapKey(0, 1, 0, SFT_T(KC_A));
    auto       mod_tap_key2 = KeymapKey(0, 2, 0, CTL_T(KC_B));

    set_keymap({mod_tap_key1, mod_tap_key2});

    EXPECT_NO_REPORT(driver);
    EXPECT_REPORT(driver, (KC_LSFT));
    EXPECT_REPORT(driver, (KC_LSFT, KC_LCTL));
    idle_for(FLOW_TAP_TERM + 1);
    mod_tap_key1.press();
    run_one_scan_loop();
    mod_tap_key2.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_EMPTY_REPORT(driver);
    EXPECT_REPORT(driver, (KC_A));
    EXPECT_REPORT(driver, (KC_A, KC_B));
    EXPECT_REPORT(driver, (KC_B));
    mod_tap_key1.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Hold for longer than the tapping term.
    EXPECT_NO_REPORT(driver);
    idle_for(TAPPING_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    // Release mod-tap keys.
    EXPECT_EMPTY_REPORT(driver);
    mod_tap_key2.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

TEST_F(SpeculativeHoldFlowTapTest, rolling_lt_mt_regular) {
    TestDriver driver;
    InSequence s;
    auto       layer_tap_key = KeymapKey(0, 0, 0, LT(1, KC_A));
    auto       mod_tap_key   = KeymapKey(0, 1, 0, CTL_T(KC_B));
    auto       regular_key   = KeymapKey(0, 2, 0, KC_C);

    set_keymap({layer_tap_key, mod_tap_key, regular_key});

    EXPECT_REPORT(driver, (KC_LCTL));
    idle_for(FLOW_TAP_TERM + 1);
    layer_tap_key.press();
    run_one_scan_loop();
    mod_tap_key.press();
    run_one_scan_loop();
    regular_key.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_EMPTY_REPORT(driver);
    EXPECT_REPORT(driver, (KC_A));
    EXPECT_REPORT(driver, (KC_A, KC_B));
    EXPECT_REPORT(driver, (KC_A, KC_B, KC_C));
    EXPECT_REPORT(driver, (KC_B, KC_C));
    layer_tap_key.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Hold for longer than the tapping term.
    EXPECT_NO_REPORT(driver);
    idle_for(TAPPING_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    // Release mod-tap keys.
    EXPECT_REPORT(driver, (KC_C));
    EXPECT_EMPTY_REPORT(driver);
    mod_tap_key.release();
    run_one_scan_loop();
    regular_key.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

TEST_F(SpeculativeHoldFlowTapTest, rolling_lt_regular_mt) {
    TestDriver driver;
    InSequence s;
    auto       layer_tap_key = KeymapKey(0, 0, 0, LT(1, KC_A));
    auto       regular_key   = KeymapKey(0, 1, 0, KC_B);
    auto       mod_tap_key   = KeymapKey(0, 2, 0, CTL_T(KC_C));

    set_keymap({layer_tap_key, regular_key, mod_tap_key});

    EXPECT_NO_REPORT(driver);
    idle_for(FLOW_TAP_TERM + 1);
    layer_tap_key.press();
    run_one_scan_loop();
    regular_key.press();
    run_one_scan_loop();
    mod_tap_key.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_REPORT(driver, (KC_A));
    EXPECT_REPORT(driver, (KC_A, KC_B));
    EXPECT_REPORT(driver, (KC_A, KC_B, KC_C));
    EXPECT_REPORT(driver, (KC_B, KC_C));
    layer_tap_key.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Hold for longer than the tapping term.
    EXPECT_NO_REPORT(driver);
    idle_for(TAPPING_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    // Release mod-tap keys.
    EXPECT_REPORT(driver, (KC_C));
    EXPECT_EMPTY_REPORT(driver);
    regular_key.release();
    run_one_scan_loop();
    mod_tap_key.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

TEST_F(SpeculativeHoldFlowTapTest, rolling_mt_mt_mt) {
    TestDriver driver;
    InSequence s;
    auto       mod_tap_key1 = KeymapKey(0, 0, 0, CTL_T(KC_A));
    auto       mod_tap_key2 = KeymapKey(0, 1, 0, GUI_T(KC_B));
    auto       mod_tap_key3 = KeymapKey(0, 2, 0, ALT_T(KC_C));

    set_keymap({mod_tap_key1, mod_tap_key2, mod_tap_key3});

    // Press mod-tap keys.
    EXPECT_REPORT(driver, (KC_LCTL));
    EXPECT_REPORT(driver, (KC_LCTL, KC_LGUI));
    EXPECT_REPORT(driver, (KC_LCTL, KC_LGUI, KC_LALT));
    idle_for(FLOW_TAP_TERM + 1);
    mod_tap_key1.press();
    run_one_scan_loop();
    mod_tap_key2.press();
    run_one_scan_loop();
    mod_tap_key3.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Release first mod-tap key.
    EXPECT_EMPTY_REPORT(driver);
    EXPECT_REPORT(driver, (KC_A));
    EXPECT_REPORT(driver, (KC_A, KC_B));
    EXPECT_REPORT(driver, (KC_A, KC_B, KC_C));
    EXPECT_REPORT(driver, (KC_B, KC_C));
    mod_tap_key1.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Hold for longer than the tapping term.
    EXPECT_NO_REPORT(driver);
    idle_for(TAPPING_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    // Release other mod-tap keys.
    EXPECT_REPORT(driver, (KC_C));
    EXPECT_EMPTY_REPORT(driver);
    mod_tap_key2.release();
    run_one_scan_loop();
    mod_tap_key3.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

TEST_F(SpeculativeHoldFlowTapTest, roll_release_132) {
    TestDriver driver;
    InSequence s;
    auto       mod_tap_key1 = KeymapKey(0, 0, 0, CTL_T(KC_A));
    auto       mod_tap_key2 = KeymapKey(0, 1, 0, GUI_T(KC_B));
    auto       mod_tap_key3 = KeymapKey(0, 2, 0, ALT_T(KC_C));

    set_keymap({mod_tap_key1, mod_tap_key2, mod_tap_key3});

    // Press mod-tap keys.
    EXPECT_REPORT(driver, (KC_LCTL));
    EXPECT_REPORT(driver, (KC_LCTL, KC_LGUI));
    EXPECT_REPORT(driver, (KC_LCTL, KC_LGUI, KC_LALT));
    idle_for(FLOW_TAP_TERM + 1);
    mod_tap_key1.press();
    run_one_scan_loop();
    mod_tap_key2.press();
    idle_for(FLOW_TAP_TERM + 1);
    mod_tap_key3.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Release first mod-tap key.
    EXPECT_EMPTY_REPORT(driver);
    EXPECT_REPORT(driver, (KC_A));
    EXPECT_REPORT(driver, (KC_A, KC_B));
    EXPECT_REPORT(driver, (KC_B));
    mod_tap_key1.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Release other mod-tap keys.
    EXPECT_REPORT(driver, (KC_B, KC_C));
    EXPECT_REPORT(driver, (KC_B));
    EXPECT_EMPTY_REPORT(driver);
    mod_tap_key3.release();
    run_one_scan_loop();
    mod_tap_key2.release();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

// Test with layer tap and speculative mod tap keys on the same layer, rolling
// from LT to MT key:
// "LT down, MT down, (wait out tapping term), LT up, MT up."
TEST_F(SpeculativeHoldFlowTapTest, lt_mt_same_layer_roll) {
    TestDriver driver;
    InSequence s;
    auto       layer_tap_key = KeymapKey(0, 0, 0, LT(1, KC_A));
    auto       mod_tap_key   = KeymapKey(0, 1, 0, SFT_T(KC_B));
    auto       regular_key   = KeymapKey(1, 1, 0, KC_C);

    set_keymap({layer_tap_key, mod_tap_key, regular_key});

    // Press layer tap key.
    EXPECT_NO_REPORT(driver);
    layer_tap_key.press();
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    // Press mod-tap key, after flow tap term but within tapping term. The
    // speculative mod activates.
    EXPECT_REPORT(driver, (KC_LSFT));
    mod_tap_key.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    // Wait for the layer tap key to settle.
    EXPECT_EMPTY_REPORT(driver);
    EXPECT_REPORT(driver, (KC_C));
    idle_for(TAPPING_TERM - FLOW_TAP_TERM);
    VERIFY_AND_CLEAR(driver);

    // Release keys.
    EXPECT_EMPTY_REPORT(driver);
    layer_tap_key.release();
    run_one_scan_loop();
    mod_tap_key.release();
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

// Test with layer tap and speculative mod tap keys on the same layer, trying
// a nested press from LT to MT key:
// "LT down, MT down, (wait out tapping term), MT up, LT up."
TEST_F(SpeculativeHoldFlowTapTest, lt_mt_same_layer_nested_press) {
    TestDriver driver;
    InSequence s;
    auto       layer_tap_key = KeymapKey(0, 0, 0, LT(1, KC_A));
    auto       mod_tap_key   = KeymapKey(0, 1, 0, SFT_T(KC_B));
    auto       regular_key   = KeymapKey(1, 1, 0, KC_C);

    set_keymap({layer_tap_key, mod_tap_key, regular_key});

    EXPECT_NO_REPORT(driver);
    layer_tap_key.press();
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    EXPECT_REPORT(driver, (KC_LSFT));
    mod_tap_key.press();
    run_one_scan_loop();
    VERIFY_AND_CLEAR(driver);

    EXPECT_EMPTY_REPORT(driver);
    EXPECT_REPORT(driver, (KC_C));
    idle_for(TAPPING_TERM - FLOW_TAP_TERM);
    VERIFY_AND_CLEAR(driver);

    // Release keys: MT first, LT second.
    EXPECT_EMPTY_REPORT(driver);
    mod_tap_key.release();
    run_one_scan_loop();
    layer_tap_key.release();
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

// Test with layer tap and speculative mod tap keys on the same layer, trying
// a nested press with the MT first:
// "MT down, LT down, (wait out tapping term), LT up, MT up."
TEST_F(SpeculativeHoldFlowTapTest, mt_lt_same_layer_nested_press) {
    TestDriver driver;
    InSequence s;
    auto       layer_tap_key = KeymapKey(0, 0, 0, LT(1, KC_A));
    auto       mod_tap_key   = KeymapKey(0, 1, 0, SFT_T(KC_B));
    auto       regular_key   = KeymapKey(1, 1, 0, KC_C);

    set_keymap({layer_tap_key, mod_tap_key, regular_key});

    EXPECT_REPORT(driver, (KC_LSFT));
    mod_tap_key.press();
    run_one_scan_loop();

    EXPECT_NO_REPORT(driver);
    layer_tap_key.press();
    idle_for(TAPPING_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    EXPECT_EMPTY_REPORT(driver);
    layer_tap_key.release();
    run_one_scan_loop();
    mod_tap_key.release();
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

// Test with a speculative mod tap key reached by a layer tap key, rolling from
// LT to MT key:
// "LT down, MT down, (wait out tapping term), LT up, MT up."
TEST_F(SpeculativeHoldFlowTapTest, lt_mt_different_layer_roll) {
    TestDriver driver;
    InSequence s;
    auto       layer_tap_key   = KeymapKey(0, 0, 0, LT(1, KC_A));
    auto       regular_key     = KeymapKey(0, 1, 0, KC_B);
    auto       placeholder_key = KeymapKey(1, 0, 0, KC_NO);
    auto       mod_tap_key     = KeymapKey(1, 1, 0, SFT_T(KC_C));

    set_keymap({layer_tap_key, regular_key, placeholder_key, mod_tap_key});

    // Press layer tap key.
    EXPECT_NO_REPORT(driver);
    layer_tap_key.press();
    idle_for(FLOW_TAP_TERM + 1);
    // Press mod tap key.
    mod_tap_key.press();
    idle_for(TAPPING_TERM - FLOW_TAP_TERM);
    VERIFY_AND_CLEAR(driver);

    // Release keys.
    EXPECT_REPORT(driver, (KC_B));
    layer_tap_key.release();
    idle_for(TAPPING_TERM);
    VERIFY_AND_CLEAR(driver);

    EXPECT_EMPTY_REPORT(driver);
    mod_tap_key.release();
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

// Test with a speculative mod tap key reached by a layer tap key, slowly
// rolling from LT to MT key:
// "LT down, (wait), MT down, (wait), LT up, MT up."
TEST_F(SpeculativeHoldFlowTapTest, lt_mt_different_layer_slow_roll) {
    TestDriver driver;
    InSequence s;
    auto       layer_tap_key   = KeymapKey(0, 0, 0, LT(1, KC_A));
    auto       regular_key     = KeymapKey(0, 1, 0, KC_B);
    auto       placeholder_key = KeymapKey(1, 0, 0, KC_NO);
    auto       mod_tap_key     = KeymapKey(1, 1, 0, SFT_T(KC_C));

    set_keymap({layer_tap_key, regular_key, placeholder_key, mod_tap_key});

    EXPECT_NO_REPORT(driver);
    layer_tap_key.press();
    idle_for(TAPPING_TERM + 1);

    EXPECT_REPORT(driver, (KC_LSFT));
    mod_tap_key.press();
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    EXPECT_EMPTY_REPORT(driver);
    EXPECT_REPORT(driver, (KC_B));
    EXPECT_EMPTY_REPORT(driver);
    layer_tap_key.release();
    run_one_scan_loop();
    mod_tap_key.release();
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

// Test with a speculative mod tap key reached by a layer tap key, trying a
// nested press:
// "LT down, MT down, (wait out tapping term), MT up, LT up."
TEST_F(SpeculativeHoldFlowTapTest, lt_mt_different_layer_nested_press) {
    TestDriver driver;
    InSequence s;
    auto       layer_tap_key   = KeymapKey(0, 0, 0, LT(1, KC_A));
    auto       regular_key     = KeymapKey(0, 1, 0, KC_B);
    auto       placeholder_key = KeymapKey(1, 0, 0, KC_NO);
    auto       mod_tap_key     = KeymapKey(1, 1, 0, SFT_T(KC_C));

    set_keymap({layer_tap_key, regular_key, placeholder_key, mod_tap_key});

    EXPECT_NO_REPORT(driver);
    layer_tap_key.press();
    idle_for(FLOW_TAP_TERM + 1);
    mod_tap_key.press();
    idle_for(TAPPING_TERM - FLOW_TAP_TERM);
    VERIFY_AND_CLEAR(driver);

    // Release keys.
    EXPECT_REPORT(driver, (KC_C));
    EXPECT_EMPTY_REPORT(driver);
    mod_tap_key.release();
    run_one_scan_loop();
    layer_tap_key.release();
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}

// Test with a speculative mod tap key reached by a layer tap key, trying a
// slow nested press:
// "LT down, (wait), MT down, MT up, LT up."
TEST_F(SpeculativeHoldFlowTapTest, lt_mt_different_layer_slow_nested_press) {
    TestDriver driver;
    InSequence s;
    auto       layer_tap_key   = KeymapKey(0, 0, 0, LT(1, KC_A));
    auto       regular_key     = KeymapKey(0, 1, 0, KC_B);
    auto       placeholder_key = KeymapKey(1, 0, 0, KC_NO);
    auto       mod_tap_key     = KeymapKey(1, 1, 0, SFT_T(KC_C));

    set_keymap({layer_tap_key, regular_key, placeholder_key, mod_tap_key});

    EXPECT_NO_REPORT(driver);
    layer_tap_key.press();
    idle_for(TAPPING_TERM + 1);

    EXPECT_REPORT(driver, (KC_LSFT));
    mod_tap_key.press();
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);

    EXPECT_EMPTY_REPORT(driver);
    EXPECT_REPORT(driver, (KC_C));
    EXPECT_EMPTY_REPORT(driver);
    mod_tap_key.release();
    run_one_scan_loop();
    layer_tap_key.release();
    idle_for(FLOW_TAP_TERM + 1);
    VERIFY_AND_CLEAR(driver);
    // All mods are released.
    EXPECT_EQ(get_mods() | get_speculative_mods(), 0);
}
