# The test template is taken from the `./keymap.nix`
{ system ? builtins.currentSystem
, config ? { }
, pkgs ? import ../.. { inherit system config; }
}:

with import ../lib/testing-python.nix { inherit system pkgs; };

let
  readyFile = "/tmp/readerReady";
  resultFile = "/tmp/readerResult";

  testReader = pkgs.writeScript "test-input-reader" ''
    rm -f ${resultFile} ${resultFile}.tmp
    logger "testReader: START: Waiting for $1 characters, expecting '$2'."
    touch ${readyFile}
    read -r -N $1 chars
    rm -f ${readyFile}
    if [ "$chars" == "$2" ]; then
      logger -s "testReader: PASS: Got '$2' as expected." 2>${resultFile}.tmp
    else
      logger -s "testReader: FAIL: Expected '$2' but got '$chars'." 2>${resultFile}.tmp
    fi
    # rename after the file is written to prevent a race condition
    mv  ${resultFile}.tmp ${resultFile}
  '';


  mkKeyboardTest = name: { settings, test }: with pkgs.lib; makeTest {
    inherit name;

    nodes.machine = {
      services.keyd = {
        enable = true;
        inherit settings;
      };
    };

    testScript = ''
      import shlex

      machine.wait_for_unit("keyd.service")

      def run_test_case(cmd, test_case_name, inputs, expected):
          with subtest(test_case_name):
              assert len(inputs) == len(expected)
              machine.execute("rm -f ${readyFile} ${resultFile}")
              # set up process that expects all the keys to be entered
              machine.succeed(
                  "{} {} {} {} >&2 &".format(
                      cmd,
                      "${testReader}",
                      len(inputs),
                      shlex.quote("".join(expected)),
                  )
              )
              # wait for reader to be ready
              machine.wait_for_file("${readyFile}")
              # send all keys
              for key in inputs:
                  machine.send_key(key)
              # wait for result and check
              machine.wait_for_file("${resultFile}")
              machine.succeed("grep -q 'PASS:' ${resultFile}")
      test = ${builtins.toJSON test}
      run_test_case("openvt -sw --", "${name}", test["press"], test["expect"])
    '';
  };

in
pkgs.lib.mapAttrs mkKeyboardTest {
  swap-ab_and_ctrl-as-shift = {
    test.press = [ "a" "ctrl-b" "c" ];
    test.expect = [ "b" "A" "c" ];

    settings.main = {
      "a" = "b";
      "b" = "a";
      "control" = "oneshot(shift)";
    };
  };
}