{
  config,
  pkgs,
  lib,
  ...
}: let
  cfg = config.sway;

  rotate_lisgd = pkgs.writeShellScriptBin "rotate_lisgd" ''
    # PREV_ORIENTATION and ORIENTATION are given by rot8

    LISGD_INPUT=/dev/input/event14
    # open nwggrid by swiping up from the bottom edge
    LISGD_ACTIONS=("1,DU,B,*,R,${pkgs.sway}/bin/swaymsg exec ${pkgs.nwg-launchers}/bin/nwggrid -client")
    # close window by swiping down with 3 fingers
    LISGD_ACTIONS+=("3,UD,*,L,R,${pkgs.sway}/bin/swaymsg kill")

    # move window left by swiping left with 2 fingers
    LISGD_ACTIONS+=("2,UD,*,*,R,${pkgs.sway}/bin/swaymsg move left")
    # move window down by swiping down with 2 fingers
    LISGD_ACTIONS+=("2,UD,*,*,R,${pkgs.sway}/bin/swaymsg move down")
    # move window up by swiping up with 2 fingers
    LISGD_ACTIONS+=("2,UD,*,*,R,${pkgs.sway}/bin/swaymsg move up")
    # move window right by swiping right with 2 fingers
    LISGD_ACTIONS+=("2,UD,*,*,R,${pkgs.sway}/bin/swaymsg move right")

    LISGD_ACTION_OPTIONS=()
    for str in "''${LISGD_ACTIONS[@]}"; do
     LISGD_ACTION_OPTIONS+=("-g" "$str")
    done

    ${pkgs.killall}/bin/killall lisgd

    ${pkgs.lisgd}/bin/lisgd -v -d "$LISGD_INPUT" "''${LISGD_ACTION_OPTIONS[@]}" &
  '';

  # bash script to let dbus know about impotant env variables and
  # propagate them to relevent services run at the end of sway config
  dbus-sway-environment = pkgs.writeShellScriptBin "dbus-sway-environment" ''
    dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=sway
    systemctl --user stop pipewire pipewire-media-session xdg-desktop-portal xdg-desktop-portal-wlr
    systemctl --user start pipewire pipewire-media-session xdg-desktop-portal xdg-desktop-portal-wlr
  '';
in {
  imports = [./kanshi.nix ./waybar.nix ./theme.nix ./mako.nix];

  options = {
    sway.enable = lib.mkEnableOption "sway, a lightweight window manager";
    sway.laptop = lib.mkEnableOption "laptop config";
  };

  config = lib.mkIf cfg.enable {
    sway.kanshi.enable = lib.mkDefault true;
    sway.waybar.enable = lib.mkDefault true;
    sway.theming.enable = lib.mkDefault true;
    sway.mako.enable = lib.mkDefault true;
    sway.waybar.battery = lib.mkIf cfg.laptop (lib.mkDefault true);
    sway.waybar.backlight = lib.mkIf cfg.laptop (lib.mkDefault true);
    sway.waybar.squeekboard = lib.mkIf cfg.laptop (lib.mkDefault true);

    home.packages = with pkgs; [
      swaylock # screen locking
      swayidle # automatic screen locking after system idle time
      foot # terminal
      keepassxc # used for secrets instead of gnome-keyring
    ];

    wayland.windowManager.sway = {
      enable = true;
      systemd = {
        enable = true;
        xdgAutostart = false;
      };

      wrapperFeatures = {
        gtk = true;
      };

      config = {
        output = let
          bgdir = ../../../assets;
          bg1080 = bgdir + "/bg1080.png";
          bg1080vert = bgdir + "/bg1080vert.png";
          bg4k = bgdir + "/bg4k.png";
        in
          lib.mkIf cfg.laptop {
            eDP-1 = {
              bg = "'${bg1080}' fit";
            };
            HDMI-A-1 = {
              bg = "'${bg4k}' fit";
            };
            DP-3 = {
              bg = "'${bg1080}' fit";
            };
            DP-4 = {
              bg = "'${bg1080}' fit";
            };
            DP-5 = {
              bg = "'${bg1080vert}' fit";
            };
            DP-6 = {
              bg = "'${bg1080}' fit";
            };
            DP-7 = {
              bg = "'${bg1080vert}' fit";
            };
          };

        input = {
          "*" = {
            xkb_layout = "de";
            xkb_options = "caps:ctrl_modifier";
            xkb_numlock = "enable";
          };
          "type:touchpad" = lib.mkIf cfg.laptop {
            tap = "enable";
            natural_scroll = "enable";
          };
          # map laptop touchscreen to laptop display
          "1267:11676:ELAN2513:00_04F3:2D9C" = lib.mkIf cfg.laptop {
            map_to_output = "'AU Optronics 0x4B2D Unknown'";
          };
          # map laptop stylus to laptop display
          "1267:11676:ELAN2513:00_04F3:2D9C_Stylus" = lib.mkIf cfg.laptop {
            map_to_output = "'AU Optronics 0x4B2D Unknown'";
          };
        };

        modifier = "Mod4";
        keybindings = let
          modifier = config.wayland.windowManager.sway.config.modifier;
        in
          lib.mkOptionDefault {
            # special workspaces
            "${modifier}+1" = "workspace main";
            "${modifier}+2" = "workspace term";
            "${modifier}+3" = "workspace msg";
            "${modifier}+4" = "workspace music";
            "${modifier}+Shift+1" = "move container to workspace main";
            "${modifier}+Shift+2" = "move container to workspace term";
            "${modifier}+Shift+3" = "move container to workspace msg";
            "${modifier}+Shift+4" = "move container to workspace music";

            # screen capture
            "${modifier}+Print" = ''exec ${pkgs.grim}/bin/grim -g "$(${pkgs.slurp}/bin/slurp)" - | ${pkgs.wl-clipboard}/bin/wl-copy'';
            "${modifier}+Shift+Print" = ''exec ${pkgs.wf-recorder}/bin/wf-recorder -g "$(${pkgs.slurp}/bin/slurp)" -f "$HOME/Videos/screencapture_$(${pkgs.coreutils}/bin/date +%F-%T).mp4"'';

            # brightness
            "XF86MonBrightnessDown" = "exec ${pkgs.light}/bin/light -U 5";
            "XF86MonBrightnessUp" = "exec ${pkgs.light}/bin/light -A 5";
            # volume
            "XF86AudioRaiseVolume" = "exec '${pkgs.pulseaudio}/bin/pactl set-sink-volume @DEFAULT_SINK@ +1%'";
            "XF86AudioLowerVolume" = "exec '${pkgs.pulseaudio}/bin/pactl set-sink-volume @DEFAULT_SINK@ -1%'";
            "XF86AudioMute" = "exec '${pkgs.pulseaudio}/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle'";

            # custom pause mode similar to typical system shutdown menus
            "${modifier}+F12" = "mode pause-break";
          };
        menu = "${pkgs.nwg-launchers}/bin/nwggrid -client";

        # use foot as default terminal
        terminal = "${pkgs.foot}/bin/foot";
        assigns = {
          "main" = [{app_id = "firefox";}];
          "term" = [{app_id = "foot-startup";}];
          "msg" = [{title = "\\[Locked\\] - KeePassXC$";}];
        };
        bars = [];

        modes = {
          pause-break = {
            e = "exec --no-startup-id swaymsg exit, mode default";
            s = "exec --no-startup-id ${pkgs.dash}/bin/dash -c '${pkgs.swaylock}/bin/swaylock & systemctl suspend-then-hibernate', mode default";
            r = "exec --no-startup-id systemctl reboot";
            End = "exec --no-startup-id systemctl poweroff";
            Return = "mode default";
            Escape = "mode default";
          };
        };

        startup =
          [
            {command = "${dbus-sway-environment}/bin/dbus-sway-environment";}
            {command = "${pkgs.nwg-launchers}/bin/nwggrid-server -fp";}
            {command = "${pkgs.keepassxc}/bin/keepassxc";}
            {command = "${pkgs.foot}/bin/foot -a foot-startup";}
            {command = "${pkgs.networkmanagerapplet}/bin/nm-applet";}
          ]
          ++ lib.optionals cfg.laptop [
            {command = "${pkgs.squeekboard}/bin/squeekboard";}
            {command = "${pkgs.rot8}/bin/rot8 -n 10 -h ${rotate_lisgd}/bin/rotate_lisgd";}
            {command = "${rotate_lisgd}/bin/rotate_lisgd";}
          ];

        defaultWorkspace = "main";
        workspaceAutoBackAndForth = true;
        workspaceOutputAssign = lib.mkIf cfg.laptop [
          {
            workspace = "main";
            output = ["DP-3" "DP-4" "DP-6" "HDMI-A-1" "eDP-1"];
          }
          {
            workspace = "term";
            output = ["DP-5" "DP-4" "DP-7" "eDP-1"];
          }
          {
            workspace = "msg";
            output = ["eDP-1"];
          }
          {
            workspace = "music";
            output = ["eDP-1"];
          }
          {
            workspace = "5";
            output = ["DP-3" "DP-4" "DP-6" "HDMI-A-1" "eDP-1"];
          }
        ];
      };

      extraConfig = lib.mkIf cfg.laptop ''
        bindswitch --reload --locked lid:on exec "[ $(${pkgs.sway}/bin/swaymsg -t get_outputs | ${pkgs.jq}/bin/jq '. | length') -gt 1 ] && ${pkgs.sway}/bin/swaymsg output eDP-1 disable"
        bindswitch --reload --locked lid:off output eDP-1 enable
      '';
    };
  };
}
