{
  lib,
  pkgs,
  config,
  ...
}:
with lib;
let
  cfg = config.eboskma.programs.sway;
  mod = "Mod4";
  # swaylockcmd = "${pkgs.swaylock}/bin/swaylock --ignore-empty-password --daemonize --show-failed-attempts --indicator-caps-lock --image ${cfg.lock-wallpaper} --scaling fill";
  swaylockcmd = "${lib.getExe pkgs.swaylock}";
  rofiPower = pkgs.writeShellScriptBin "rofi-power" (
    # builtins.replaceStrings [ "{WALLPAPER}" ] [ (builtins.toString cfg.lock-wallpaper) ] (
    builtins.readFile ./powermenu.sh
    # )
  );
in
{
  options.eboskma.programs.sway = {
    enable = mkEnableOption "sway";
    package = mkPackageOption pkgs "sway" { };
    swayidle = mkEnableOption "swayidle" // {
      default = true;
    };

    # lock-wallpaper = mkOption {
    #   description = "Wallpaper to use for the lockscreen";
    #   type = types.path;
    # };
    terminal = mkOption {
      description = "Default terminal to run";
      type = types.str;
      default = lib.getExe pkgs.foot;
    };
    output = mkOption {
      description = "An attribute set that defines output modules. See the sway-output(5) manpage for options";
      type = types.attrsOf (types.attrsOf types.str);
      default = { };
    };
    input = mkOption {
      description = "An attribute set that defines input modules. See the sway-input(5) manpage for options";
      type = types.attrsOf (types.attrsOf types.str);
      default = { };
    };
    startup = mkOption {
      description = "Commands that should be executed at startup.";
      default = [ ];
      type = types.listOf (
        types.submodule {
          options = {
            command = mkOption {
              type = types.str;
              description = "Command that will be executed on startup.";
            };

            always = mkOption {
              type = types.bool;
              default = false;
              description = "Whether to run command on each ${moduleName} restart.";
            };
          };
        }
      );
    };
    workspaceOutputs = mkOption {
      description = "Assign workspaces to outputs";
      type = types.listOf (
        types.submodule {
          options = {
            output = mkOption {
              description = "Name(s) of the output to assign";
              type = with types; either str (listOf str);
              apply = lists.toList;
              default = "";
            };
            workspace = mkOption {
              description = "Name of the workspace to assign";
              type = types.str;
              default = "";
            };
          };
        }
      );
      default = [ ];
    };

    extraKeybindings = mkOption {
      description = "Extra keybindings";
      type = types.attrsOf types.str;
      default = { };
    };
  };

  config = mkIf cfg.enable {
    wayland.windowManager.sway = {
      enable = true;
      package = cfg.package;
      checkConfig = false; # Why is this even here?

      config = {
        modifier = mod;

        bars = [ ];

        # Dracula theme
        colors = {
          background = "#f8f8f2";
          focused = {
            border = "#6272a4";
            background = "#6272A4";
            text = "#f8f8f2";
            indicator = "#6272a4";
            childBorder = "#6272a4";
          };
          focusedInactive = {
            border = "#44475a";
            background = "#44475a";
            text = "#f8f8f2";
            indicator = "#44475a";
            childBorder = "#44475a";
          };
          unfocused = {
            border = "#282a36";
            background = "#282a36";
            text = "#bfbfbf";
            indicator = "#282a36";
            childBorder = "#282a36";
          };
          urgent = {
            border = "#44475a";
            background = "#ff5555";
            text = "#f8f8f2";
            indicator = "#ff5555";
            childBorder = "#ff5555";
          };
          placeholder = {
            border = "#282a36";
            background = "#282a36";
            text = "#f8f8f2";
            indicator = "#282a36";
            childBorder = "#282a36";
          };
        };

        defaultWorkspace = "workspace number 1";

        workspaceOutputAssign = cfg.workspaceOutputs;

        left = "n";
        down = "e";
        up = "i";
        right = "o";

        floating = {
          criteria = [
            { app_id = "gnome-calculator"; }
            { app_id = "dev.deedles.Trayscale"; }
          ];
          modifier = mod;
        };

        fonts = {
          names = [ "Iosevka Nerd Font" ];
          style = "Regular";
          size = 12.0;
        };

        gaps = {
          inner = 10;
          # outer = 5;
          smartBorders = "on";
        };

        input = cfg.input;
        output = cfg.output;

        # menu = "${pkgs.rofi}/bin/rofi -show drun -no-lazy-grab";
        menu = "${config.programs.anyrun.package}/bin/anyrun";

        keybindings = {
          "${mod}+Return" = "exec ${config.wayland.windowManager.sway.config.terminal}";
          "${mod}+Shift+q" = "kill";
          "${mod}+s" = "exec ${config.wayland.windowManager.sway.config.menu}";
          # "${mod}+Shift+s" = "exec ${pkgs.wofi}/bin/wofi --show run | ${pkgs.findutils}/bin/xargs swaymsg exec --";

          "${mod}+${config.wayland.windowManager.sway.config.left}" = "focus left";
          "${mod}+${config.wayland.windowManager.sway.config.down}" = "focus down";
          "${mod}+${config.wayland.windowManager.sway.config.up}" = "focus up";
          "${mod}+${config.wayland.windowManager.sway.config.right}" = "focus right";

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

          "${mod}+Shift+${config.wayland.windowManager.sway.config.left}" = "move left";
          "${mod}+Shift+${config.wayland.windowManager.sway.config.down}" = "move down";
          "${mod}+Shift+${config.wayland.windowManager.sway.config.up}" = "move up";
          "${mod}+Shift+${config.wayland.windowManager.sway.config.right}" = "move right";

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

          "${mod}+h" = "split h";
          "${mod}+v" = "split v";
          "${mod}+t" = "fullscreen toggle";
          "${mod}+a" = "focus parent";

          "${mod}+r" = "layout stacking";
          "${mod}+w" = "layout tabbed";
          "${mod}+f" = "layout toggle split";

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

          "${mod}+1" = "workspace number 1";
          "${mod}+2" = "workspace number 2";
          "${mod}+3" = "workspace number 3";
          "${mod}+4" = "workspace number 4";
          "${mod}+5" = "workspace number 5";
          "${mod}+6" = "workspace number 6";
          "${mod}+7" = "workspace number 7";
          "${mod}+8" = "workspace number 8";
          "${mod}+9" = "workspace number 9";
          "${mod}+0" = "workspace number 10";

          "${mod}+Shift+1" = "move container to workspace number 1";
          "${mod}+Shift+2" = "move container to workspace number 2";
          "${mod}+Shift+3" = "move container to workspace number 3";
          "${mod}+Shift+4" = "move container to workspace number 4";
          "${mod}+Shift+5" = "move container to workspace number 5";
          "${mod}+Shift+6" = "move container to workspace number 6";
          "${mod}+Shift+7" = "move container to workspace number 7";
          "${mod}+Shift+8" = "move container to workspace number 8";
          "${mod}+Shift+9" = "move container to workspace number 9";
          "${mod}+Shift+0" = "move container to workspace number 10";

          "${mod}+Shift+minus" = "move scratchpad";
          "${mod}+minus" = "scratchpad show";

          "${mod}+Shift+c" = "reload";

          "${mod}+Shift+f" = "exec --no-startup-id ${rofiPower}/bin/rofi-power";
          "${mod}+l" = "exec ${swaylockcmd}";
          "${mod}+p" = "mode resize";

          "${mod}+Pause" = "mode passthrough";

          "${mod}+c" =
            mkIf config.eboskma.programs.emacs.enable "exec ${config.programs.emacs.package}/bin/emacsclient -c";

          "${mod}+Print" =
            "exec ${pkgs.grim}/bin/grim -o $(${cfg.package}/bin/swaymsg -t get_outputs | ${pkgs.jaq}/bin/jaq -r '.[] | select(.focused) | .name')";
          "${mod}+Shift+Print" =
            ''exec ${pkgs.grim}/bin/grim -o $(${cfg.package}/bin/swaymsg -t get_outputs | ${pkgs.jaq}/bin/jaq -r '.[] | select(.focused) | .name') - | ${pkgs.wl-clipboard}/bin/wl-copy -t "image/png" -f'';
          "${mod}+Shift+Ctrl+Print" =
            ''exec ${pkgs.grim}/bin/grim -g "$(${pkgs.slurp}/bin/slurp)" - | ${pkgs.wl-clipboard}/bin/wl-copy -t "image/png" -f'';
          "${mod}+Shift+Alt+Print" = ''exec ${pkgs.grim}/bin/grim -g "$(${pkgs.slurp}/bin/slurp)"'';

          "XF86AudioRaiseVolume" = "exec ${pkgs.pamedia}/bin/pamedia up";
          "XF86AudioLowerVolume" = "exec ${pkgs.pamedia}/bin/pamedia down";
          "XF86AudioMute" = "exec ${pkgs.pamedia}/bin/pamedia mute";
          "XF86Calculator" = "exec ${pkgs.gnome-calculator}/bin/gnome-calculator";

          "${mod}+d" = "exec ${pkgs.swaynotificationcenter}/bin/swaync-client --toggle-panel --skip-wait";
          "${mod}+Shift+d" = "exec ${pkgs.swaynotificationcenter}/bin/swaync-client --toggle-dnd --skip-wait";
        } // cfg.extraKeybindings;

        modes = {
          passthrough = {
            "${mod}+Pause" = "mode default";
          };
        };

        # terminal = "${pkgs.foot}/bin/foot";
        terminal = cfg.terminal;

        window = {
          border = 1;
          titlebar = false;
        };

        workspaceAutoBackAndForth = true;

        seat = {
          "seat0" = {
            hide_cursor = "when-typing disable";
            xcursor_theme = "${config.home.pointerCursor.name} ${toString config.home.pointerCursor.size}";
          };
        };

        startup = cfg.startup;
      };
      extraConfig = builtins.concatStringsSep "\n" (
        [
          ''
            for_window [app_id="^.*"] inhibit_idle fullscreen
            for_window [class="^.*"] inhibit_idle fullscreen
            for_window [app_id="org.gnome.Calculator"] floating enable
            for_window [shell="xwayland"] title_format "%title [XWayland]"
            for_window [app_id="^.*iwgtk$"] floating enable

            include /etc/sway/config.d/*
          ''
        ]
        ++ lib.optional (cfg.package == pkgs.swayfx) ''
          blur enable
          blur_xray disable

          shadows enable

          default_dim_inactive 0.2

          corner_radius 10
        ''
      );
      # exec --no-startup-id ${pkgs.swaynotificationcenter}/bin/swaync
      # exec --no-startup-id ${pkgs.networkmanagerapplet}/bin/nm-applet --indicator
      # exec --no-startup-id ${pkgs.swayidle}/bin/swayidle -w timeout 900 "${swaylockcmd}"
      # exec --no-startup-id ${pkgs.swayidle}/bin/swayidle -w timeout 1200 "${pkgs.sway}/bin/swaymsg 'output * dpms off'" resume "${pkgs.sway}/bin/swaymsg 'output * dpms on'"
      # exec_always --no-startup-id systemctl --user import-environment _JAVA_AWT_WM_NONREPARENTING MOZ_ENABLE_WAYLAND MOZ_DBUS_REMOTE QT_QPA_PLATFORM QT_WAYLAND_DISABLE_WINDOWDECORATION QT_QPA_PLATFORMTHEME SDL_VIDEODRIVER SSH_AUTH_SOCK
      # exec_always --no-startup-id dbus-update-activation-environment --systemd _JAVA_AWT_WM_NONREPARENTING MOZ_ENABLE_WAYLAND MOZ_DBUS_REMOTE QT_QPA_PLATFORM QT_WAYLAND_DISABLE_WINDOWDECORATION QT_QPA_PLATFORMTHEME SDL_VIDEODRIVER SSH_AUTH_SOCK

      # extraSessionCommands =
      #   ''
      #     export _JAVA_AWT_WM_NONREPARENTING=1
      #     export MOZ_ENABLE_WAYLAND=1
      #     export MOZ_DBUS_REMOTE=1
      #     export QT_QPA_PLATFORM=wayland
      #     export QT_WAYLAND_DISABLE_WINDOWDECORATION="1"
      #     export QT_QPA_PLATFORMTHEME=qt5ct
      #     export SDL_VIDEODRIVER=wayland
      #     export SSH_AUTH_SOCK="''${XDG_RUNTIME_DIR}/gnupg/S.gpg-agent.ssh"
      #   '';

      wrapperFeatures = {
        base = true;
        gtk = true;
      };

      xwayland = true;

      systemd = {
        enable = true;
        xdgAutostart = true;
      };
    };

    services = {
      swayidle = mkIf cfg.swayidle {
        enable = true;
        events = [
          {
            event = "lock";
            command = swaylockcmd;
          }
        ];

        timeouts =
          let
            poweroffOpts = builtins.concatStringsSep ", " (
              builtins.map (name: "output ${name} power off") (builtins.attrNames cfg.output)
            );
            resumeOpts = builtins.concatStringsSep ", " (
              builtins.map (name: "output ${name} power on") (builtins.attrNames cfg.output)
            );
          in
          [
            {
              timeout = 900;
              command = swaylockcmd;
            }
            {
              timeout = 1200;
              command = "${cfg.package}/bin/swaymsg '${poweroffOpts}'";
              resumeCommand = "${cfg.package}/bin/swaymsg '${resumeOpts}'";
            }
          ];
      };
    };

  };
}