{
  config,
  lib,
  pkgs,
  ...
}:

let
  sway-config = pkgs.writeTextFile {
    name = "config";
    text = ''
      # Default config for sway
      #
      # Copy this to ~/.config/sway/config and edit it to your liking.
      #
      # Read `man 5 sway` for a complete reference.

      ### Variables
      #
      # Logo key. Use Mod1 for Alt.
      set $mod Mod4
      # set $mod Mod1
      # Home row direction keys, like vim
      set $left h
      set $down j
      set $up k
      set $right l
      # Your preferred terminal emulator
      set $term ${pkgs.alacritty}/bin/alacritty
      # Your preferred application launcher
      # Note: it's recommended that you pass the final command to sway
      # set $menu dmenu_path | dmenu | xargs swaymsg exec
      set $menu ${pkgs.wofi}/bin/wofi --show drun --gtk-dark

      # Do not show a title bar on windows
      default_border pixel 2

      bindsym $mod+grave exec $term

      include ${base-hotkeys}
      include ${display-configs}
      include ${window-management}
      include ${movement}
      include ${disable-focus-follows-mouse}
      include ${background}
      include ${touchpad_input}
      include ${waybar}
      include ${announce_sway_start}
    '';
  };
  base-hotkeys = pkgs.writeTextFile {
    name = "base-hotkeys.conf";
    text = ''
      ### Key bindings
      #
      # Basics:
      #
          # kill focused window
          bindsym $mod+Shift+q kill

          # start your launcher
          bindsym $mod+Return exec $menu

          # Drag floating windows by holding down $mod and left mouse button.
          # Resize them with right mouse button + $mod.
          # Despite the name, also works for non-floating windows.
          # Change normal to inverse to use left mouse button for resizing and right
          # mouse button for dragging.
          floating_modifier $mod normal

          # reload the configuration file
          bindsym $mod+Shift+c reload

          # exit sway (logs you out of your Wayland session)
          bindsym $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'
    '';
  };
  display-configs = pkgs.writeTextFile {
    name = "display-configs.conf";
    text = ''
      output 'Unknown 0x095F 0x00000000' scale 1.5
      output 'BOE 0x095F Unknown' scale 1.5
      output 'BOE 0x0BCA Unknown' scale 1.5
    '';
  };
  window-management = pkgs.writeTextFile {
    name = "window-management.conf";
    text = ''
      #
      # Layout stuff:
      #
          # You can "split" the current object of your focus with
          # $mod+b or $mod+v, for horizontal and vertical splits
          # respectively.
          bindsym $mod+h splith
          bindsym $mod+v splitv

          # Switch the current container between different layout styles
          bindsym $mod+s layout stacking
          bindsym $mod+w layout tabbed
          bindsym $mod+e layout toggle split

          # Make the current focus fullscreen
          bindsym $mod+f fullscreen

          # Toggle the current focus between tiling and floating mode
          bindsym $mod+Shift+space floating toggle

          # Swap focus between the tiling area and the floating area
          bindsym $mod+space focus mode_toggle

          # move focus to the parent container
          bindsym $mod+a focus parent
      #
      # Scratchpad:
      #
          # Sway has a "scratchpad", which is a bag of holding for windows.
          # You can send windows there and get them back later.

          # Move the currently focused window to the scratchpad
          bindsym $mod+Shift+minus move scratchpad

          # Show the next scratchpad window or hide the focused scratchpad window.
          # If there are multiple scratchpad windows, this command cycles through them.
          bindsym $mod+minus scratchpad show
      #
      # Resizing containers:
      #
      mode "resize" {
          # left will shrink the containers width
          # right will grow the containers width
          # up will shrink the containers height
          # down will grow the containers height
          bindsym $left resize shrink width 10px
          bindsym $down resize grow height 10px
          bindsym $up resize shrink height 10px
          bindsym $right resize grow width 10px

          # ditto, with arrow keys
          bindsym Left resize shrink width 10px
          bindsym Down resize grow height 10px
          bindsym Up resize shrink height 10px
          bindsym Right resize grow width 10px

          # return to default mode
          bindsym Return mode "default"
          bindsym Escape mode "default"
      }
      bindsym $mod+r mode "resize"
    '';
  };
  movement = pkgs.writeTextFile {
    name = "movement.conf";
    text = ''
      #
      # Moving around:
      #
          # Move your focus around
          # bindsym $mod+$left focus left
          # bindsym $mod+$down focus down
          # bindsym $mod+$up focus up
          # bindsym $mod+$right focus right
          # or use $mod+[up|down|left|right]
          bindsym $mod+Left focus left
          bindsym $mod+Down focus down
          bindsym $mod+Up focus up
          bindsym $mod+Right focus right

          # _move_ the focused window with the same, but add Shift
          bindsym $mod+Shift+$left move left
          bindsym $mod+Shift+$down move down
          bindsym $mod+Shift+$up move up
          bindsym $mod+Shift+$right move right
          # ditto, with arrow keys
          bindsym $mod+Shift+Left move left
          bindsym $mod+Shift+Down move down
          bindsym $mod+Shift+Up move up
          bindsym $mod+Shift+Right move right
      #
      # Workspaces:
      #
          # switch to workspace
          bindsym $mod+1 workspace 1
          bindsym $mod+2 workspace 2
          bindsym $mod+3 workspace 3
          bindsym $mod+4 workspace 4
          bindsym $mod+5 workspace 5
          bindsym $mod+6 workspace 6
          bindsym $mod+7 workspace 7
          bindsym $mod+8 workspace 8
          bindsym $mod+9 workspace 9
          bindsym $mod+0 workspace 10
          # move focused container to workspace
          bindsym $mod+Shift+1 move container to workspace 1
          bindsym $mod+Shift+2 move container to workspace 2
          bindsym $mod+Shift+3 move container to workspace 3
          bindsym $mod+Shift+4 move container to workspace 4
          bindsym $mod+Shift+5 move container to workspace 5
          bindsym $mod+Shift+6 move container to workspace 6
          bindsym $mod+Shift+7 move container to workspace 7
          bindsym $mod+Shift+8 move container to workspace 8
          bindsym $mod+Shift+9 move container to workspace 9
          bindsym $mod+Shift+0 move container to workspace 10
          # Note: workspaces can have any name you want, not just numbers.
          # We just use 1-10 as the default.
    '';
  };
  disable-focus-follows-mouse = pkgs.writeTextFile {
    name = "disable-focus-follows-mouse.conf";
    text = ''
      # Disable focus following mouse
      focus_follows_mouse no
    '';
  };
  background = pkgs.writeTextFile {
    name = "background.conf";
    text = ''
      output * bg ${./files/bliss.jpg} fill
    '';
  };
  touchpad_input = pkgs.writeTextFile {
    name = "touchpad_input.conf";
    text = ''
      input * xkb_rules "evdev"

      # All touchpads
      input type:touchpad {
            dwt enabled
            click_method clickfinger
            tap enabled
      }
    '';
  };
  waybar = pkgs.writeTextFile {
    name = "waybar.conf";
    text = ''
      #
      # Status Bar:
      #
      # Read `man 5 sway-bar` for more information about this section.
      bar {
          position top

          font pango:Cascadia Mono, FontAwesome 10
          swaybar_command waybar

          colors {
              statusline #ffffff
              background #323232
              inactive_workspace #32323200 #32323200 #5c5c5c
          }
      }
    '';
  };
  announce_sway_start = pkgs.writeTextFile {
    name = "announce_sway_start.conf";
    text = ''
      # announce a running sway session to systemd
      exec systemctl --user import-environment XDG_SESSION_TYPE XDG_CURRENT_DESKTOP
      exec dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=sway
    '';
  };

  start_screen_share = pkgs.writeShellScriptBin "start_screen_share" ''
    # Disable displaying notifications. This is useful for video conference screen sharing.
    set -euo pipefail
    IFS=$'\n\t'
    DIR="$( cd "$( dirname "''${BASH_SOURCE[0]}" )" && pwd )"

    makoctl set-mode do-not-disturb

    swaymsg output "'Dell Inc. DELL U3014 P1V6N35M329L'" scale 2
  '';
  stop_screen_share = pkgs.writeShellScriptBin "stop_screen_share" ''
    # Allow mako to show notifications again.
    set -euo pipefail
    IFS=$'\n\t'
    DIR="$( cd "$( dirname "''${BASH_SOURCE [ 0 ]}" )" && pwd )"

    makoctl set-mode default

    swaymsg output "'Dell Inc. DELL U3014 P1V6N35M329L'" scale 1
  '';
in
{
  imports = [ ];

  environment.systemPackages = with pkgs; [
    alacritty
    pcmanfm
    start_screen_share
    stop_screen_share
  ];

  # Probably would be cleaner to use environment.sessionVariables but programs.sway.extraSessionCommands is sway-specific.
  programs.sway.extraSessionCommands =
    if config.me.buildingIso then
      ''
        export WLR_RENDERER_ALLOW_SOFTWARE=1
        export NIXOS_OZONE_WL=1 # Wayland support for chromium and electron
        export QT_QPA_PLATFORMTHEME=gtk3 # Use gtk theme in Qt applications
      ''
    else
      ''
        export WLR_RENDERER=vulkan
        export NIXOS_OZONE_WL=1 # Wayland support for chromium and electron
        export QT_QPA_PLATFORMTHEME=gtk3 # Use gtk theme in Qt applications
      '';

  programs.sway = {
    enable = true;
    wrapperFeatures.gtk = true;
    extraOptions =
      if config.me.buildingIso then
        [
          "--debug"
          "--config"
          "${sway-config}"
          "--unsupported-gpu"
        ]
      else
        [
          "--debug"
          "--config"
          "${sway-config}"
        ];
  };

  environment.persistence."/state" = lib.mkIf (!config.me.buildingIso) {
    hideMounts = true;
    users.talexander = {
      files = [
        ".cache/wofi-drun" # Execution history for wofi to sort results
      ];
    };
  };

  xdg = {
    portal = {
      enable = true;
      extraPortals = with pkgs; [
        xdg-desktop-portal-wlr
        xdg-desktop-portal-gtk
      ];
      wlr = {
        enable = true;
        settings = {
          # uninteresting for this problem, for completeness only
          screencast = {
            # output_name = "eDP-1";
            max_fps = 30;
            exec_before = "${start_screen_share}";
            exec_after = "${stop_screen_share}";
            chooser_type = "simple";
            chooser_cmd = "${pkgs.slurp}/bin/slurp -f %o -or";
          };
        };
      };
    };
  };

  # Configure default programs (for example, default browser)
  home-manager.users.talexander =
    { pkgs, ... }:
    {
      home.file = {
        ".config/mimeapps.list" = {
          source = ./files/mimeapps.list;
        };
      };
      home.file = {
        ".config/gtk-3.0/settings.ini" = {
          source = ./files/settings.ini;
        };
      };
    };

  # For mounting drives in pcmanfm
  services.gvfs.enable = true;
}