private: Yes


# TODO icons
# TODO X11 cursor
# TODO dmenu pass(1)
# TODO wayland clipboard in nvim
{ config, pkgs, lib, ... }:

let
  # sway script started by systemd
  startSway = pkgs.writeTextFile {
    name = "start-sway";
    destination = "/bin/start-sway";
    executable = true;
    text = ''
      #!${pkgs.stdenv.shell}
      systemctl --user import-environment
      "${pkgs.dbus}/bin/dbus-run-session" "${pkgs.sway}/bin/sway" --debug
    '';
  };

  # reduce repition in sway config by generating workspace switches
  wsConfig = lib.concatMapStringsSep "\n" (n: ''
    bindsym $mod+${toString n} workspace number ${toString n}
    bindsym $mod+Shift+${toString n} move container to workspace number ${toString n}
  '') [1 2 3 4 5 6 7 8 9];

  # .Xresources file to fix DPI issues in Xwayland
  xResources = pkgs.writeText "Xresources" ''
    Xft.dpi: 96
  '';
in

{
  config = {
    programs.sway = {
      enable = true;
      extraPackages = with pkgs; [
        dmenu-wayland
        xwayland qt5.qtwayland
        wl-clipboard            # instead of xsel
        grim slurp              # screenshots
      ];
      extraSessionCommands = ''
        # correct DPI after hotplugging
        ${pkgs.xorg.xrdb} -load ${xResources}
        # SDL
        export SDL_VIDEODRIVER=wayland
        # QT
        export QT_QPA_PLATFORM=wayland
        export QT_WAYLAND_DISABLE_WINDOWDECORATION="1"
      '';
      wrapperFeatures = {
        gtk = true;
        base = true;
      };
    };

    environment.etc = {
      "sway/config".text = ''
        set $mod Mod4
        set $term ${pkgs.kitty}/bin/kitty
        set $menu ${pkgs.dmenu-wayland}/bin/dmenu-wl_path | ${pkgs.dmenu-wayland}/bin/dmenu-wl | xargs swaymsg exec --

        # neo arrow keys
        set $left i
        set $right e
        set $up l
        set $down a

        bindsym $mod+Shift+c reload

        bindsym $mod+Return exec $term
        bindsym $mod+d exec $menu

        bindsym $mod+Shift+q kill

        bindsym $mod+h splith
        bindsym $mod+v splitv

        bindsym $mod+s layout stacking
        bindsym $mod+t layout tabbed
        bindsym $mod+n layout toggle split

        bindsym $mod+f fullscreen

        bindsym $mod+Shift+space floating toggle
        bindsym $mod+space focus mode_toggle
        floating_modifier $mod normal

        bindsym $mod+$left focus left
        bindsym $mod+$down focus down
        bindsym $mod+$up focus up
        bindsym $mod+$right focus right

        bindsym $mod+Shift+$left move left
        bindsym $mod+Shift+$down move down
        bindsym $mod+Shift+$up move up
        bindsym $mod+Shift+$right move right

        mode "resize" {
          bindsym $left resize shrink width 10px
          bindsym $down resize grow height 10px
          bindsym $up resize shrink height 10px
          bindsym $right resize grow width 10px

          bindsym Return mode "default"
          bindsym Escape mode "default"
        }
        bindsym $mod+r mode "resize"

        # workspace shortcuts
        ${wsConfig}

        set $pactl ${config.hardware.pulseaudio.package}/bin/pactl
        bindsym XF86AudioRaiseVolume exec $pactl set-sink-volume @DEFAULT_SINK@ +5%
        bindsym XF86AudioLowerVolume exec $pactl set-sink-volume @DEFAULT_SINK@ -5%
        bindsym XF86AudioMute exec $pactl set-sink-mute @DEFAULT_SINK@ toggle
        bindsym XF86AudioMicMute exec $pactl set-source-mute @DEFAULT_SOURCE@ toggle

        set $brightnessctl ${pkgs.brightnessctl}/bin/brightnessctl
        bindsym XF86MonBrightnessDown exec $brightnessctl set 5%-
        bindsym XF86MonBrightnessUp exec $brightnessctl set +5%

        bindsym $mod+0 exec ${pkgs.swaylock}/bin/swaylock -c FFC0CB -k -l

        font "DejaVu Sans Mono normal 10"

        gaps inner 10

        output * bg #000000 solid_color

        client.focused #ffffff #ffffff #000000
        client.focused_inactive #000000 #000000 #ffffff
        client.unfocused #000000 #000000 #ffffff
        client.urgent #900000 #900000 #ffffff

        bar {
          status_command ${pkgs.i3status}/bin/i3status
          position top
          colors {
            font "DejaVu Sans Mono normal 10"
            statusline #ffffff
            background #000000
            focused_workspace #ffffff #ffffff #000000
            active_workspace #ffffff #ffffff #c4c4c4
            inactive_workspace #000000 #000000 #ffffff
            urgent_workspace #900000 #900000 #ffffff
          }
        }
      '';
      "xdg/i3status/config".text = ''
        # TODO replace i3status?
        general {
          output_format = "i3bar"
          colors = true
          interval = 1
        }

        order += "volume master"
        order += "battery all"
        order += "tztime dotdate"
        order += "tztime dottime"
        order += "tztime offset"

        volume master {
          format = "๐Ÿ”Š: %volume"
          format_muted = "๐Ÿ”ˆ: %volume"
          device = "pulse"
        }

        battery all {
          format = "%status: %percentage"
          status_chr = "โšก"
          status_bat = "๐Ÿ”‹"
          status_unk = "โ“"
          status_full = "๐Ÿ’ฏ"
          low_threshold = 10
        }

        tztime dotdate {
          timezone = "UTC"
          format = "%Y-%m-%d"
        }

        tztime dottime {
          timezone = "UTC"
          format = "%Hยท%M"
        }

        tztime offset {
          format = "%z"
        }
      '';
    };

    environment.variables = {
      XKB_DEFAULT_LAYOUT = "de";
      XKB_DEFAULT_VARIANT = "neo";
      # TODO user env?
      SWAYSOCK = "/run/user/${toString config.users.users.lukas.uid}/sway.sock";
    };

    environment.systemPackages = with pkgs; [
      networkmanagerapplet # for nm-connection-ediotr
      imv zathura
    ];

    # based on https://nixos.wiki/Sway
    systemd.user = {
      services.sway = {
        bindsTo = [ "graphical-session.target" ];
        wants = [ "graphical-session-pre.target" ];
        after = [ "graphical-session-pre.target" ];
        environment = {
          PATH = lib.mkForce null; # systemctl import-environment doesn't handle PATH
        };
        serviceConfig = {
          Type = "simple";
          ExecStart = "${startSway}/bin/start-sway";
          ExecStop = ''
            ${pkgs.sway}/bin/swaymsg exit
          '';
        };
      };
      # TODO multi displays, notifications?

    };
  };
}