{
  pkgs,
  lib,
  ...
}: let
  colors = import ./colors.nix;
in {
  home-manager.users.buffet = {
    wayland.windowManager.sway = {
      enable = true;
      package = pkgs.unstable.sway;
      systemd.enable = true;
      wrapperFeatures.gtk = true;

      config = let
        mod = "Mod4";
      in {
        input."*" = {
          xkb_layout = "us";
          xkb_options = "compose:prsc";
        };

        seat."*" = {hide_cursor = "when-typing enable";};
        floating.modifier = mod;

        keybindings = let
          makeWorkspaceBinds = num: let
            ws = toString num;
          in {
            "${mod}+${ws}" = "workspace ${ws}";
            "${mod}+Shift+${ws}" = "move container to workspace ${ws}";
          };

          joinAttrSets = builtins.foldl' (x: y: x // y) {};
        in
          {
            "${mod}+Return" = "exec ${pkgs.foot}/bin/foot";
            "${mod}+i" = "exec ${pkgs.firefox-wayland}/bin/firefox";
            "${mod}+Shift+y" = "exec swaylock";
            "${mod}+d" = "exec ${pkgs.fuzzel}/bin/fuzzel";
            "${mod}+Equal" = "exec ${pkgs.foot}/bin/foot --app-id todolist ${pkgs.oed}/bin/ed ~/todo";

            "${mod}+p" = "exec ${pkgs.unstable.sway-contrib.grimshot}/bin/grimshot copy area";
            "${mod}+Alt+p" = "exec ${pkgs.unstable.sway-contrib.grimshot}/bin/grimshot copy window";
            "${mod}+Shift+p" = "exec ${pkgs.unstable.sway-contrib.grimshot}/bin/grimshot copy output";

            "${mod}+z" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set 1%-";
            "${mod}+x" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set +1%";
            "${mod}+Shift+z" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set 5%-";
            "${mod}+Shift+x" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set +5%";

            "${mod}+Shift+q" = "kill";
            "${mod}+Shift+c" = "reload";
            "${mod}+Shift+e" = "exit";

            "${mod}+h" = "focus left";
            "${mod}+j" = "focus down";
            "${mod}+k" = "focus up";
            "${mod}+l" = "focus right";

            "${mod}+Left" = "focus left";
            "${mod}+Down" = "focus down";
            "${mod}+Up" = "focus up";
            "${mod}+Right" = "focus right";

            "${mod}+Shift+h" = "move left";
            "${mod}+Shift+j" = "move down";
            "${mod}+Shift+k" = "move up";
            "${mod}+Shift+l" = "move right";

            "${mod}+o" = "splith";
            "${mod}+u" = "splitv";

            "${mod}+s" = "layout stacking";
            "${mod}+t" = "layout tabbed";
            "${mod}+e" = "layout toggle split";
            "${mod}+f" = "fullscreen";

            "${mod}+Shift+space" = "floating toggle";
            "${mod}+space" = "focus mode_toggle";

            "${mod}+Shift+minus" = "move scratchpad";
            "${mod}+minus" = "scratchpad show";
          }
          // (joinAttrSets (map makeWorkspaceBinds (lib.range 1 9)));

        output."*" = {
          bg = "${colors.wallpaper} solid_color";
        };

        gaps = {
          inner = 12;
          left = 8;
          right = 8;
          bottom = 8;
          top = 0;
        };

        window.border = 1;
        fonts = {
          names = ["APL386 Unicode"];
          style = "Regular";
          size = 8.0;
        };

        colors = rec {
          focused = rec {
            border = colors.focused;
            childBorder = border;
            background = border;
            text = border;
            indicator = border;
          };

          unfocused = rec {
            border = colors.unfocused;
            childBorder = border;
            background = border;
            text = border;
            indicator = border;
          };

          focusedInactive = unfocused;
        };

        bars = [
          {
            position = "top";

            fonts = {
              names = ["APL386 Unicode"];
              style = "Regular";
              size = 8.0;
            };

            statusCommand = toString (pkgs.writeScript "status_command" ''
              #!/bin/sh

              while :; do
                  energy_full=0
                  energy_now=0
                  charging=

                  for bat in /sys/class/power_supply/*/capacity; do
                      bat="''${bat%/*}"
                      read -r full <"$bat/energy_full"
                      read -r now <"$bat/energy_now"
                      energy_full=$((energy_full + full))
                      energy_now=$((energy_now + now))
                  done

                  if cat /sys/class/power_supply/*/status | grep -q Charging; then
                      charging=+
                  fi

                  percentage=$((energy_now * 100 / energy_full))

                  printf '%s %s ' "$charging$percentage%" "$(date +'%H:%M:%S')"
                  sleep 1
              done
            '');

            colors = rec {
              statusline = colors.primary.foreground;
              inherit (colors.primary) background;

              focusedWorkspace = rec {
                background = colors.focused;
                border = background;
                text = colors.primary.background;
              };

              inactiveWorkspace = rec {
                inherit (colors.primary) background;
                border = background;
                text = colors.primary.foreground;
              };
            };

            extraConfig = ''
              gaps 16 20
            '';
          }
        ];
      };

      # TODO: use window.commands instead
      extraConfig = ''
        for_window [all] title_format ""
        for_window [title="^oyster$"] floating enable
        for_window [app_id="^pavucontrol$"] floating enable
        for_window [app_id="^todolist$"] floating enable
        for_window [app_id="^firefox$" title="^Developer Tools"] floating enable
      '';
    };

    programs.swaylock = {
      enable = true;
      settings = with colors; {
        ignore-empty-password = true;
        color = bright.white;
        key-hl-color = normal.green;
        bs-hl-color = normal.red;
        caps-lock-key-hl-color = normal.green;
        caps-lock-bs-hl-color = normal.red;
        inside-color = bright.white;
        inside-clear-color = bright.white;
        inside-caps-lock-color = bright.white;
        inside-ver-color = bright.white;
        inside-wrong-color = bright.white;
        ring-color = bright.white;
        ring-clear-color = bright.white;
        ring-caps-lock-color = bright.white;
        ring-ver-color = bright.white;
        ring-wrong-color = bright.white;
      };
    };
  };
}