{ pkgs, getBins, writeExecline, runExeclineLocal, toNetstringKeyVal, ... }:

let
  inherit (pkgs) lib;
  bins = getBins pkgs.nodejs [ "node" ]
      // getBins pkgs.coreutils [ "echo" "ln" "mkdir" ]
      // getBins pkgs.dhall-json [ "json-to-dhall" ]
      // getBins pkgs.xorg.xrandr [ "xrandr" ]
      ;

  writeNodejs = {
    name,
    # an attrset of node dependency name to source directory;
    # will be made into a node_modules directory and set as `NODE_PATH`.
    dependencies
  }:
    let
      node_modules = runExeclineLocal "${name}-node_modules" {
        stdin = toNetstringKeyVal dependencies;
      } [
        "importas" "out" "out"
        "if" [ bins.mkdir "$out" ]
        "forstdin" "-o" "0" "-Ed" "" "dep"
        "multidefine" "-d" "" "$dep" [ "name" "source" ]
        "if" [ bins.echo "\${name} - \${source}" ]
        bins.ln "-sT" "\${source}" "\${out}/\${name}"
      ];

    in pkgs.writers.makeScriptWriter {
      interpreter = writeExecline "nodejs-with-modules" {} [
        "export" "NODE_PATH" node_modules
        bins.node "$@"
      ];
    } name;

  dhall-typecheck = {
    name,
    dhallType,
    recordsLoose ? false
  }:
    writeExecline name {} ([
      bins.json-to-dhall
    ]
    ++ lib.optional recordsLoose "--records-loose"
    ++ [
      dhallType
    ]);

  parse = writeNodejs {
    name = "xrandr-parse";
    dependencies = {
      xrandr-parse =
        (pkgs.fetchFromGitHub {
          owner = "lionep";
          repo = "xrandr-parse";
          rev = "a35bfd625c1b0834aa94f136cf8282b25624b3e6";
          sha256 = "0c8mfsvgg76ia2i9gsgdwy567xzba5274xpj8si37yah5qpp8dkm";
        });
    };
  } ''
    var parse = require('xrandr-parse');
    var exec = require('child_process').exec;

    exec('xrandr', function (err, stdout) {
        var query = parse(stdout);
        console.log(JSON.stringify(query, null, 2));
    });
  '';

  type = pkgs.writeText "type.dhall" ''
    let Resolution = {
      height: Text,
      width: Text,
      rate: Double
    }
    let Monitor =
      < NotConnected : {}
      | Connected : {
          connected: Bool,
          modes: List Resolution,
          index: Natural,
          native: Resolution
      }
      | Active : {
          modes: List Resolution,
          index: Natural,
          native: Resolution,
          current: Resolution
      } >

    in List {
      mapKey: Text,
      mapValue: Monitor
    }
  '';


  two-monitor-setup = writeExecline "test" {} [
    "backtick" "-Ei" "json" [ parse ]
    "if" [
      "pipeline" [ bins.echo "$json" ]
      "redirfd" "-w" "1" "/dev/null"
      (dhall-typecheck {
        name = "typecheck-xrandr";
        dhallType = type;
        recordsLoose = true;
      })
    ]
    "pipeline" [ bins.echo "$json" ]
    two-monitor-setup-script
  ];


  two-monitor-setup-script = pkgs.writers.writePython3 "xrandr-two-monitor-setup" {} ''
    import json
    import sys
    import os

    # TODO: use netencode for input
    monitors = json.load(sys.stdin)

    connected = {
      k: v for k, v in monitors.items()
      if 'connected' in v and v['connected']
    }

    if 'eDP1' not in connected:
        print("could not find eDP1 (laptop screen)", file=sys.stderr)
        sys.exit(1)

    if len(connected) != 2:
        print("only know how to configure two monitors")
        sys.exit(1)

    eDP1 = connected['eDP1']

    # laptop screen is active
    assert 'current' in eDP1

    # how far the laptop screen should be offset to end
    # at the bottom of the monitor
    h_offset = 0
    for k, v in connected.items():
        if k == 'eDP1':
            assert 'current' in v

        else:
            h = int(v['native']['height'])
            h_offset = h - int(eDP1['native']['height'])
            external_monitor = (k, v)
            # canâ€™t handle bigger laptop screens atm
            assert h_offset >= 0

    xrandr_command = [
        "--verbose",

        "--output", external_monitor[0],
        "--primary",
        "--mode", "{}x{}".format(
            external_monitor[1]['native']['width'],
            external_monitor[1]['native']['height']
        ),
        "--pos", "{}x{}".format(
            # offset by the laptop size to the right
            eDP1['native']['width'],
            # monitor starts at 0
            0
        ),

        "--output", "eDP1",
        "--mode", "{}x{}".format(
            eDP1['native']['width'],
            eDP1['native']['height'],
        ),
        "--pos", "{}x{}".format(
            # laptop is the leftmost screen
            0,
            # but offset to the bottom so that it always aligns on the left bottom
            h_offset
        ),
    ]

    os.execvp(
        "${bins.xrandr}",
        ["${bins.xrandr}"]
        + xrandr_command
    )
  '';

in {
  inherit
    parse
    two-monitor-setup
    ;
}
