{ lib, config, pkgs, userName, ... }:
{
    options.swaywm = {
        enable = lib.mkEnableOption "Enable sway window manager.";
        useNonFree = lib.mkOption {
            default = false;
            example = true;
            description = "Whether to enable non-free software in the sway config";
        };
        installGaming = lib.mkOption {
            default = false;
            example = true;
            description = "Whether to install gaming software on the system.";
        };
        systemPackages = lib.mkOption {
            default = [];
            description = "Add any additional packages desired. Merged with sway defaults.";
        };

    };

    ###
    ##  Configuration
    ###
    config = lib.mkIf config.swaywm.enable {

        programs.sway.enable = true;
        programs.sway.wrapperFeatures.gtk = true;

        nixpkgs.config.allowUnfree = config.swaywm.useNonFree;
        # For R2ModMan
        # nixpkgs.config.permittedInsecurePackages = [
        #     "electron-25.9.0"
        # ];
        
        ###
        ##  XDG portal setup
        ###
        xdg.portal = {
            config = {
                common = {
                  default = [
                    "wlr"
                  ];
                };
            };
            extraPortals = with pkgs; [
                # xdg-desktop-portal-kde
                xdg-desktop-portal-gtk
            ];
            wlr.enable = true;
            enable = true;
        };
        xdg.sounds.enable = true;

        ###
        ##  System Packages
        ###
        environment.systemPackages = with pkgs; lib.lists.flatten [
            [
               bash
               foot
               git
               glib # gsettings
               grim
               sway-contrib.grimshot
               libnotify
               mako
               man-pages
               man-pages-posix
               ncspot
               networkmanagerapplet
               pavucontrol
               slurp
               syncthingtray
               swaylock
               swayidle
               swaybg
               # swww
               tailscale-systray
               wl-clipboard
               waybar
               wdisplays
               wofi
               xdg-utils
               zsh
               lxqt.lxqt-policykit
               # Fonts
            ]
            config.swaywm.systemPackages
        ];
        environment.variables.QT_STYLE_OVERRIDE = "kvantum";

        # adds additional man pages
        documentation.dev.enable = true;

        # Thunar config
        programs.thunar = {
            enable = true;
            plugins = with pkgs.xfce; [
                thunar-archive-plugin
                thunar-volman
            ];
        };
        programs.xfconf.enable = true;

        programs.zsh.enable = true;
        programs.steam.enable = config.swaywm.installGaming;
        programs.gamemode.enable = true;

        programs.adb.enable = true;
        # programs.kdeconnect.enable = true;
        # service file to start the sshAgent
        programs.ssh.startAgent = false; # using gnome keyring

        ###
        ##  Services
        ###
        virtualisation = {
            # docker.enable = true;
            podman = {
                enable = true;
                dockerCompat = true;
            };
        };

        services.blueman.enable = true;
        services.flatpak.enable = true;
        services.gvfs.enable = true;  # thunar mount, trash, etc
        services.tumbler.enable = true; # thunar thumbnails
        services.openssh.enable = true;
        services.dbus.enable = true;
        services.syncthing.enable = true;
        services.gnome.gnome-keyring.enable = true;
        services.usbmuxd.enable = true;
        services.tailscale = {
            enable = true;
            openFirewall = true;
        };
        services.udev.extraRules = ''
            # For betaflight configurator
            # DFU (Internal bootloader for STM32 and AT32 MCUs)
            SUBSYSTEM=="usb", ATTRS{idVendor}=="2e3c", ATTRS{idProduct}=="df11", MODE="0664", GROUP="dialout"
            SUBSYSTEM=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", MODE="0664", GROUP="dialout"
            # For ddcutil monitor controls
            KERNEL=="i2c-[0-9]*", GROUP="i2c", MODE="0660"
        '';
        # For yubioath desktop
        services.pcscd.enable = true;
        # Audio
        security.rtkit.enable = true;
        services.pipewire = {
          enable = true;
          alsa.enable = true;
          pulse.enable = true;
          wireplumber.enable = true;
        };
        sound.enable = false;

        ###
        ##  Misc
        ###
        # Necessary for home-manager sway setup
        security.polkit.enable = true;

        services.greetd = {
          enable = true;
          settings = rec {
            initial_session = {
              command = "${pkgs.sway}/bin/sway";
              user = "nate";
            };
            default_session = initial_session;
          };
        };

        # Enable OpenGL
        hardware.opengl = {
          enable = true;
        };

        # Load nvidia driver for Xorg and Wayland
        services.xserver.videoDrivers = ["nouveau"];
        hardware.nvidia = {
          # Modesetting is required.
          modesetting.enable = true;
          # Nvidia power management. Experimental, and can cause sleep/suspend to fail.
          # Enable this if you have graphical corruption issues or application crashes after waking
          # up from sleep. This fixes it by saving the entire VRAM memory to /tmp/ instead 
          # of just the bare essentials.
          powerManagement.enable = false;

          # Fine-grained power management. Turns off GPU when not in use.
          # Experimental and only works on modern Nvidia GPUs (Turing or newer).
          powerManagement.finegrained = false;

          # Use the NVidia open source kernel module (not to be confused with the
          # independent third-party "nouveau" open source driver).
          # Support is limited to the Turing and later architectures. Full list of 
          # supported GPUs is at: 
          # https://github.com/NVIDIA/open-gpu-kernel-modules#compatible-gpus 
          # Only available from driver 515.43.04+
          # Currently alpha-quality/buggy, so false is currently the recommended setting.
          open = false;

          # Enable the Nvidia settings menu,
    	    # accessible via `nvidia-settings`.
          nvidiaSettings = true;

          # Optionally, you may need to select the appropriate driver version for your specific GPU.
          package = config.boot.kernelPackages.nvidiaPackages.stable;
          prime = {
            sync.enable = true;
            intelBusId = "PCI:0:2:0";
            nvidiaBusId = "PCI:1:0:0";
          };
        };

        hardware.bluetooth.enable = true; # enables support for Bluetooth
        hardware.bluetooth.powerOnBoot = true; # powers up the default Bluetooth controller on boot

        # Create an extra boot option for on-the-go, disabling the nvidia GPU
        specialisation = {
          on-the-go.configuration = {
            system.nixos.tags = [ "on-the-go" ];
            hardware.nvidia = {
              prime.offload.enable = lib.mkForce true;
              prime.offload.enableOffloadCmd = lib.mkForce true;
              powerManagement.finegrained = lib.mkForce true;
              prime.sync.enable = lib.mkForce false;
            };
          };
        };
    };
}
