{
  # Snowfall Lib provides a customized `lib` instance with access to your flake's library
  # as well as the libraries available from your flake's inputs.
  lib,
  # An instance of `pkgs` with your overlays and packages applied is also available.
  pkgs,
  # You also have access to your flake's inputs.
  inputs,

  # Additional metadata is provided by Snowfall Lib.
  namespace, # The namespace used for your flake, defaulting to "internal" if not set.
  system, # The system architecture for this host (eg. `x86_64-linux`).
  target, # The Snowfall Lib target for this system (eg. `x86_64-iso`).
  format, # A normalized name for the system target (eg. `iso`).
  virtual, # A boolean to determine whether this system is a virtual target using nixos-generators.
  systems, # An attribute map of your defined hosts.

  # All other arguments come from the system system.
  config,
  ...
}:
{
  imports = [ ./hardware-configuration.nix ];

  # nix.buildMachines = [
  #   {
  #     hostName = "192.168.3.118";
  #     system = "x86_64-linux";
  #     protocol = "ssh";
  #     # if the builder supports building for multiple architectures,
  #     # replace the previous line by, e.g.
  #     # systems = ["x86_64-linux" "aarch64-linux"];
  #     maxJobs = 4;
  #     speedFactor = 3;
  #     supportedFeatures = [
  #       "nixos-test"
  #       "benchmark"
  #       "big-parallel"
  #       "kvm"
  #     ];
  #     mandatoryFeatures = [ ];
  #   }
  # ];
  # nix.distributedBuilds = true;
  # # optional, useful when the builder has a faster internet connection than yours
  # nix.extraOptions = "  builders-use-substitutes = true\n";

  # Bootloader
  modules.system.boot-efi.enable = true;

  boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
  boot.supportedFilesystems = [
    "btrfs"
    "ntfs"
    "nfs"
    "cifs"
  ];

  boot.blacklistedKernelModules = [ "pcspkr" ]; # Disables "beep"

  networking.hostName = "aspi";
  # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
  networking.networkmanager.enable = true;

  topology.self = {
    hardware.info = "ThinkPad L430, 8GB RAM";
  };

  # Set your time zone.
  time.timeZone = "Europe/Berlin";

  modules = {
    locales.enable = true;
    # thunar.enable = true;
    pcmanfm.enable = true;
    # wayland.enable = true;
    # hyprland.enable = true;
  };

  nix.settings.auto-optimise-store = true;
  nix.settings.experimental-features = [
    "nix-command"
    "flakes"
  ];

  # Setup binary caches
  nix.settings = {
    substituters = [
      "https://nix-community.cachix.org"
      "https://cache.nixos.org/"
      "https://hyprland.cachix.org"
    ];
    trusted-public-keys = [
      "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
      "hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc="
    ];
  };

  # Enable the X11 windowing system.
  hardware.opengl.enable = true;

  nix.gc = {
    automatic = true;
    dates = "weekly";
    options = "--delete-older-than 30d";
  };

  # Enable the XFCE Desktop Environment.
  security.pam.services.gdm.enableGnomeKeyring = true;

  # services.displayManager.sddm.wayland.enable = true;
  # services.xserver.desktopManager = {
  #   xterm.enable = false;
  #   xfce = {
  #     enable = true;
  #     noDesktop = true;
  #     enableXfwm = false;
  #   };
  # };
  # services.xserver.displayManager.gdm.enable = true;
  services.xserver.windowManager.i3.enable = true;
  services.xserver.windowManager.i3.package = pkgs.i3-gaps;

  services.xserver.wacom.enable = true;

  services.blueman.enable = true;
  services.upower.enable = true;

  # TODO: move into i3 module
  programs.xss-lock = {
    # responds to "loginctl lock-session" via dbus
    enable = true;
    lockerCommand = "${pkgs.i3lock}/bin/i3lock --ignore-empty-password --color=000000";
  };
  # services.xserver.xautolock = { # TODO: does not work
  #   enable = true;
  #   time = 1;
  # };
  programs.dconf.enable = true;
  services.logind.lidSwitch = "lock";
  services.logind.lidSwitchDocked = "lock";

  programs.kdeconnect.enable = true;

  # Configure keymap in X11
  services.xserver = {
    enable = true;
    displayManager.gdm.enable = true;
    xkb.layout = "de";
    xkb.variant = "";
  };

  # Enable touchpad support (enabled default in most desktopManager).
  services.libinput.enable = true;

  # Configure console keymap
  console.keyMap = "de";
  # or use this
  # console.useXkbConfig = true;

  # Enable sound with pipewire and alsa
  sound.enable = true;
  hardware.pulseaudio.enable = false;
  security.polkit.enable = true;

  systemd = {
    user.services.polkit-gnome-authentication-agent-1 = {
      description = "polkit-gnome-authentication-agent-1";
      wantedBy = [ "graphical-session.target" ];
      wants = [ "graphical-session.target" ];
      after = [ "graphical-session.target" ];
      serviceConfig = {
        Type = "simple";
        ExecStart = "${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1";
        Restart = "on-failure";
        RestartSec = 1;
        TimeoutStopSec = 10;
      };
    };
  };

  # Sound
  security.rtkit.enable = true;
  services.pipewire = {
    enable = true;
    alsa.enable = true;
    alsa.support32Bit = true;
    pulse.enable = true;
    jack.enable = true;
    extraConfig.pipewire = {
      "99-no-bell" = {
        # Disable bell sound
        "context.properties" = {
          "module.x11.bell" = false;
        };
      };
    };
  };

  # needed only on aspi, otherwise soundcard is not detected
  boot.kernelParams = [ "snd-intel-dspcfg.dsp_driver=1" ];

  # Define a user account. Don't forget to set a password with ‘passwd’.
  users.users.julian = {
    isNormalUser = true;
    description = "Julian";
    uid = 1000;
    group = "julian";
    shell = pkgs.fish;
    extraGroups = [
      "networkmanager"
      "wheel"
      "docker"
      "audio"
    ];
  };

  # home-manager.useGlobalPkgs = true; # make overlays for nixpkgs work for home-manager, not only the system
  # home-manager.useUserPackages = true;

  programs.fish.enable = true;

  programs.nix-ld.enable = true;

  users.groups.julian = {
    gid = 1000;
  };

  programs.seahorse.enable = true;
  services.gnome.gnome-keyring.enable = true;

  # systemd.services."wg-quick@julian".enable = true;
  # networking.wireguard.enable = true;

  # This interface is started on boot / switch
  networking.wg-quick.interfaces = {
    julian = {
      configFile = "/etc/wireguard/julian.conf";
    };
  };

  # List services that you want to enable:
  # Enable the OpenSSH daemon.
  services.openssh.enable = false;

  services.syncthing.enable = true;
  services.syncthing.user = "julian";
  services.syncthing.openDefaultPorts = true;
  services.syncthing.configDir = "/home/julian/.config/syncthing";
  # services.syncthing.
  #services.syncthing.key = config.sops.secrets."aspi/syncthing/key".path;
  #services.syncthing.cert = config.sops.secrets."aspi/syncthing/cert".path;
  services.syncthing.overrideDevices = false; # overrides any devices added or deleted through the WebUI
  services.syncthing.overrideFolders = false; # overrides any folders added or deleted through the WebUI
  # services.syncthing.settings = {
  #   devices = {
  #     "pianopi" = {
  #       id = "FD3XSFW-7LQSCIQ-KHZPLNQ-7VZYGKH-RJ2ZKTJ-BG67NRH-36TQIZM-CXDYWAH";
  #     };
  #   };
  #   folders = {
  #     "Documents" = {
  #       # Name of folder in Syncthing, also the folder ID
  #       path = "/home/myusername/Documents"; # Which folder to add to Syncthing
  #       devices = [
  #         "device1"
  #         "device2"
  #       ]; # Which devices to share the folder with
  #     };
  #     "Example" = {
  #       path = "/home/myusername/Example";
  #       devices = [ "device1" ];
  #       ignorePerms = false; # By default, Syncthing doesn't sync file permissions. This line enables it for this folder.
  #     };
  #   };
  # };

  services.flatpak.enable = true;

  xdg.portal.enable = true;
  xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
  xdg.portal.config.common.default = "*"; # Use first portal implementation found
  # hyprland desktop portal added automatically

  # services.emacs.enable = true;

  # services.gnome.gnome-keyring.enable = true;

  # List packages installed in system profile. To search, run:
  # $ nix search wget

  # Packages needed as root
  environment.systemPackages = with pkgs; [
    vim
    htop
    mc
    xorg.xhost
    pavucontrol
    frajul.pulseaudio-popup
    gparted-xhost # needs to be installed as system package so it can be actually opened
    xclip

    brightnessctl
  ];

  virtualisation.docker.enable = true;

  virtualisation.virtualbox.host.enable = true;
  # virtualisation.virtualbox.host.enableExtensionPack = true;
  # virtualisation.virtualbox.guest.enable = true;
  # virtualisation.virtualbox.guest.x11 = true;
  users.extraGroups.vboxusers.members = [ "julian" ];

  # Some programs need SUID wrappers, can be configured further or are
  # started in user sessions.
  # programs.mtr.enable = true;
  # programs.gnupg.agent = {
  #   enable = true;
  #   enableSSHSupport = true;
  # };

  # Open ports in the firewall.
  # networking.firewall.allowedTCPPorts = [ ... ];
  # networking.firewall.allowedUDPPorts = [ ... ];
  # Or disable the firewall altogether.
  # networking.firewall.enable = false;

  # ======================== DO NOT CHANGE THIS ========================
  system.stateVersion = "24.05";
  # ======================== DO NOT CHANGE THIS ========================
}
