{
  nix-config,
  config,
  pkgs,
  nixpkgs,
  inputs,
  ...
}:

{

  imports = with nix-config.nixosModules; [
    ./hardware-configuration.nix
    ./razer-speaker-fix.nix

    sops-config
    niri
    kanata
    filesystems-filez
    filesystems-media-server
    sound
  ];

  nixpkgs = {
    config = {
      allowUnfree = true;
    };
    overlays = builtins.attrValues nix-config.overlays ++ [
      inputs.niri.overlays.niri
      inputs.emacs-overlay.overlays.default
      inputs.nix-rice.overlays.default
      inputs.nh.overlays.default
      inputs.emacs-lsp-booster.overlays.default

      (final: prev: {
        # use unmerged pr's
        inherit (inputs.nixpkgs-zotero.legacyPackages.${prev.system}) zotero;
      })

      (final: prev: {
        wineWowPackages.stagingFull = nix-config.pkgs-stable.wineWowPackages.stagingFull.overrideAttrs
          (old: {
            patches = old.patches ++ [ ../../patches/wine-6006.patch ];
            waylandSupport = true;
            fontconfigSupport = true;
            vulkanSupport = true;
          });
      })

      (final: prev: {
        bitwig-studio5-3 = nix-config.packages.x86_64-linux.bitwig-studio.bitwig-bubblewrap.override {
          bitwig-studio = nix-config.packages.x86_64-linux.bitwig-studio.bitwig-studio5-3-unwrapped;
        };
      })
    ];
  };

  nix = {
    settings = {
      experimental-features = [
        "nix-command"
        "flakes"
      ];
      substituters = [
        "https://nix-community.cachix.org"
        "https://cache.garnix.io"
      ];
      trusted-public-keys = [
        "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
        "cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g="
      ];
    };

    registry = {
      emenel-templates.flake = inputs.emenel-templates;
    };

    channel.enable = false; # remove nix-channel related tools & configs, we use flakes instead.
  };

  # Set your time zone.
  time.timeZone = "America/Toronto";

  # Select internationalisation properties.
  i18n.defaultLocale = "en_CA.UTF-8";

  sops-config = {
    key-file = "/home/emenel/.config/sops/age/keys.txt";
  };

  console = {
    earlySetup = true;
    colors =
      with pkgs.lib.nix-rice;
      let
        theme = palette.toRgbShortHex pkgs.rice.colorPalette;
      in
      with theme;
      [
        # normal.black
        # normal.red
        # normal.green
        # normal.yellow
        # normal.blue
        # normal.magenta
        # normal.cyan
        # normal.white
        # bright.black
        # bright.red
        # bright.green
        # bright.yellow
        # bright.blue
        # bright.magenta
        # bright.cyan
        # bright.white

        "111111"
        "e06c75"
        "98c379"
        "e5c07b"
        "61afef"
        "c678dd"
        "56b6c2"
        "abb2bf"
        "545862"
        "e06c75"
        "98c379"
        "e5c07b"
        "61afef"
        "c678dd"
        "56b6c2"
        "c8ccd4"
      ];
  };

  environment.systemPackages = with pkgs; [
    wget
    home-manager
    curl
    git-lfs
    rsync
    gnupg
    alsa-utils
    alsa-tools
    util-linux
    appimage-run
    xwayland-run
    cifs-utils
    ddcutil
    greetd.tuigreet
    bluez-tools
    bluetuith
    qemu
    quickemu
    borgbackup
    virt-viewer
    spice
    spice-gtk
    spice-protocol
    win-virtio
    win-spice

    xwayland-satellite-unstable
  ];

  # Bootloader.
  boot = {
    loader = {
      systemd-boot = {
        enable = true;
        configurationLimit = 8;
        # consoleMode = "max";
      };
      efi.canTouchEfiVariables = true;
    };
    kernelPackages = pkgs.linuxPackages_latest;
    kernelModules = [
      "i2c-dev"
      "ddcci-backlight"
      "amd_3d_vcache"
      "uinput"
      "hid-playstation"
      "xpadneo"
      "amd_pstate=active"
    ];
    extraModulePackages = with config.boot.kernelPackages; [
      ddcci-driver
      xpadneo
      openrazer
    ];
    extraModprobeConfig = ''
      options bluetooth disable_ertm=Y
    '';
    initrd.systemd.enable = true;
    initrd.kernelModules = [
      "nvidia"
      "nvidia_modeset"
      "nvidia_uvm"
      "nvidia_drm"
      "snd-virmidi"
    ];
    kernelParams = [
      "nvidia_drm.fbdev=1"
      "nvidia_drm.modeset=1"
    ];
    supportedFilesystems = [ "nfs" ];
  };

  systemd.services.tailscaled.after = [ "NetworkManager-wait-online.service" ];
  systemd.sleep.extraConfig = ''
    HibernateDelaySec=2h
  '';

  documentation = {
    dev.enable = true;
    man.generateCaches = true;
  };

  hardware = {
    sane = {
      enable = true;
      extraBackends = [
        pkgs.hplipWithPlugin
        pkgs.sane-airscan
        pkgs.epkowa
        pkgs.utsushi
      ];
    };
    i2c.enable = true;
    uinput.enable = true;
    openrazer = {
      enable = true;
      users = [ "emenel" ];
    };
    graphics = {
      enable = true;
      enable32Bit = true;
      extraPackages = [
        pkgs.rocmPackages.clr.icd
        # pkgs.amdvlk
      ];

      # extraPackages32 = [
      #   pkgs.driversi686Linux.amdvlk
      # ];
    };

    enableAllFirmware = true;
    firmware = [
      pkgs.sof-firmware
      pkgs.alsa-firmware
    ];

    amdgpu.initrd.enable = true;

    nvidia = {
      open = true;
      # Modesetting is required.
      modesetting.enable = true;
      powerManagement.enable = true;
      powerManagement.finegrained = true;

      # forceFullCompositionPipeline = true;

      package = config.boot.kernelPackages.nvidiaPackages.beta;

      prime = {
        amdgpuBusId = "PCI:101:0:0";
        nvidiaBusId = "PCI:1:0:0";
        offload = {
          enable = true;
          enableOffloadCmd = true;
        };

        #reverseSync.enable = true;
        #sync.enable = true;
      };
      nvidiaSettings = true;
    };
    brillo.enable = true;
    steam-hardware.enable = true;
    bluetooth = {
      enable = true;
      settings = {
        General = {
          Enable = "Source,Sink,Media,Socket";
          ControllerMode = "bredr";
          JustWorksRepairing = "always";
        };
      };
    };
  };
  # services.blueman.enable = true;

  services.fstrim.enable = true;

  services.logind = {
    extraConfig = ''
      IdleAction=lock
      IdleActionSec=15m
    '';
  };
  services.udev = {
    extraRules = ''
    KERNEL=="uinput", MODE="0660", GROUP="uinput", OPTIONS+="static_node=uinput"
    DEVPATH=="/devices/virtual/misc/cpu_dma_latency", OWNER="root", GROUP="audio", MODE="0660"
    ACTION=="add", SUBSYSTEM=="backlight", KERNEL=="ddcci*", RUN+="${pkgs.coreutils-full}/bin/chgrp video /sys/class/backlight/%k/brightness"
    ACTION=="add", SUBSYSTEM=="backlight", KERNEL=="ddcci*", RUN+="${pkgs.coreutils-full}/bin/chmod a+w /sys/class/backlight/%k/brightness"
    ACTION=="add", SUBSYSTEM=="i2c-dev", ATTR{name}=="AMDGPU DM*", TAG+="ddcci", TAG+="systemd", ENV{SYSTEMD_WANTS}+="ddcci@$kernel.service"
    ACTION=="add", SUBSYSTEM=="i2c-dev", ATTR{name}=="NVIDIA i2c adapter*", TAG+="ddcci", TAG+="systemd", ENV{SYSTEMD_WANTS}+="ddcci@$kernel.service"
    SUBSYSTEM=="i2c", ACTION=="add", ATTR{name}=="AMDGPU DM aux hw bus 3", RUN+="${pkgs.bash}/bin/bash -c 'sleep 30; printf ddcci\ 0x37 > /sys/bus/i2c/devices/i2c-17/new_device'"
    '';
    packages = [
      pkgs.via
      pkgs.vial
      pkgs.ddcutil
      pkgs.game-devices-udev-rules
      pkgs.sane-airscan
      pkgs.utsushi

      (pkgs.writeTextFile {
        name = "on-battery";
        text = ''
          # Rule for when switching to battery
          SUBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="0", RUN+="${pkgs.power-profiles-daemon}/bin/powerprofilesctl set balanced"
        '';
        destination = "/etc/udev/rules.d/60-onbattery.rules";
      })
      (pkgs.writeTextFile {
        name = "on-power";
        text = ''
          # Rule for when switching to ac
          SUBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="1", RUN+="${pkgs.power-profiles-daemon}/bin/powerprofilesctl set performance"
        '';
        destination = "/etc/udev/rules.d/61-onpower.rules";
      })
      (pkgs.writeTextFile {
        name = "hibernate-low-battery";
        text = ''
          # Suspend the system when battery level drops to 5% or lower
          SUBSYSTEM=="power_supply", ATTR{status}=="Discharging", ATTR{capacity}=="[0-5]", RUN+="${pkgs.systemd}/bin/systemctl hibernate"
        '';
        destination = "/etc/udev/rules.d/99-hibernate-low-battery.rules";
      })
      (pkgs.writeTextFile {
        name = "on-battery-power-saver";
        text = ''
          # Switch to power-saver when battery below 50%
          SUBSYSTEM=="power_supply", ATTR{status}=="Discharging", ATTR{capacity}=="[0-5][0-9]", RUN+="${pkgs.power-profiles-daemon}/bin/powerprofilesctl set power-saver"
        '';
        destination = "/etc/udev/rules.d/62-power-save-battery.rules";
      })
    ];
  };

  security.polkit.enable = true;
  security.rtkit.enable = true;
  security.pam.services.swaylock = { };
  security.pam.services.hyprlock = { };
  security.pam.services.greetd.enableGnomeKeyring = true;

  services.xserver.videoDrivers = [
    "nvidia"
    "modesetting"
  ];

  networking = {
    hostName = "eddie";
    domain = "local";
    nameservers = [
      "9.9.9.9"
      "149.112.112.112"
      "2620:fe::fe"
      "2620:fe::9"
    ];
    networkmanager = {
      enable = true;
      wifi.powersave = true;
    };
  };

  services.resolved = {
    enable = true;
    extraConfig = ''
      LLMNR=no
      ReadEtcHosts=no
      DNSSEC=no
    '';
  };

  services.xserver.enable = true;

  services.greetd = {
    enable = true;
    settings = {
      default_session = {
        command = "${pkgs.greetd.tuigreet}/bin/tuigreet --time --sessions ${config.services.displayManager.sessionData.desktops}/share/xsessions:${config.services.displayManager.sessionData.desktops}/share/wayland-sessions --remember --remember-user-session --user-menu --window-padding 5 --asterisks --asterisks-char ^ --greeting '<~welcome~>' --theme 'button=yellow'";
        # --theme 'border=magenta;prompt=green;time=red;action=blue;button=yellow;container=black;input=red'";
        user = "greeter";
      };
    };
  };

  # Enable the GNOME Desktop Environment.
  # services.xserver.displayManager.gdm.enable = true;
  services.xserver.desktopManager.gnome.enable = true;
  services.xserver.deviceSection = ''Option "TearFree" "true"''; # For amdgpu.
  services.gnome.gnome-keyring.enable = true;
  services.gnome.gnome-settings-daemon.enable = true;

  services.picom = {
    enable = true;
    vSync = true;
  };

  programs.labwc.enable = true;
  programs.ssh.startAgent = true;

  programs.npm = {
    enable = true;
    npmrc = "prefix=~/.npm-packages";
  };

  programs.nh = {
    enable = true;
    clean = {
      enable = true;
      dates = "daily";
      extraArgs = "--keep 4";
    };
    flake = "/home/emenel/source/nixos-config";
    package = pkgs.nh;
  };

  programs.dconf.enable = true;
  programs.xwayland.enable = true;

  services.xserver.xkb = {
    layout = "us";
    variant = "";
  };

  services.printing = {
    enable = true;
    drivers = [
      pkgs.epson-escpr
      pkgs.epson-escpr2
    ];
  };
  services.tailscale.enable = true;
  services.envfs.enable = true;

  services.gnome.sushi.enable = true;

  xdg.portal = {
    enable = true;
    xdgOpenUsePortal = true;
    extraPortals = [
      pkgs.xdg-desktop-portal-gnome
      pkgs.xdg-desktop-portal-gtk
      pkgs.xdg-desktop-portal
      pkgs.xdg-desktop-portal-wlr
      pkgs.gnome-keyring
    ];
  };

  programs.gamemode.enable = true;
  programs.gamescope = {
    enable = true;
    capSysNice = true;
  };

  environment.sessionVariables = {
    STEAM_EXTRA_COMPAT_TOOLS_PATHS = "\${HOME}/.steam/root/compatibilitytools.d";
  };

  programs.steam = {
    enable = true;
    protontricks.enable = true;
    extraCompatPackages = [ pkgs.proton-ge-bin ];
    gamescopeSession.enable = true;
  };

  programs.java.enable = true;

  # enable fish and launch it from bash for interactive shells
  programs.fish.enable = true;
  environment.pathsToLink = [ "/share/fish" ];
  programs.bash = {
    interactiveShellInit = ''
      if [[ $(${pkgs.procps}/bin/ps --no-header --pid=$PPID --format=comm) != "fish" && -z ''${BASH_EXECUTION_STRING} ]]
       then
         shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION=""
         exec ${pkgs.fish}/bin/fish $LOGIN_OPTION
       fi
    '';
  };

  services.flatpak.enable = true;
  services.dbus.implementation = "broker";

  #programs.gnupg.enable = true;
  programs.git.enable = true;

  environment.gnome.excludePackages = with pkgs; [
    cheese
    geary
    gnome-music
    gnome-tour
  ];

  services.accounts-daemon.enable = true;
  services.gnome.gnome-online-accounts.enable = true;

  programs.virt-manager.enable = true;
  systemd.tmpfiles.rules = [ "L+ /var/lib/qemu/firmware - - - - ${pkgs.qemu}/share/qemu/firmware" ];
  virtualisation = {
    libvirtd = {
      enable = true;
      qemu = {
        package = pkgs.qemu_kvm;
        swtpm.enable = true;
        ovmf.enable = true;
        ovmf.packages = [ pkgs.OVMFFull.fd ];
      };
    };
    spiceUSBRedirection.enable = true;
  };

  services.qemuGuest.enable = true;
  services.spice-vdagentd.enable = true;

  programs.appimage = {
    enable = true;
    binfmt = true;
    package = pkgs.appimage-run.override {
      extraPkgs = pkgs: [ pkgs.libxcrypt.out ];
    };
  };

  programs.nix-ld.enable = true;
  programs.nix-ld.libraries = with pkgs; [
    zlib
    zstd
    stdenv.cc.cc
    curlFull
    openssl.out
    attr
    libssh
    libxcrypt.out
    bzip2
    libxml2
    acl
    libsodium
    util-linux
    xz
    systemd
    fontconfig
    freetype
    gnutls
    util-linux
    libGL.dev
    psutils
    egl-wayland
    eglexternalplatform
    glfw-wayland
    glfw
    libGL.dev
    libuv.out
    libressl.out
    libudev-zero.out
    mesa.out
    gst_all_1.gstreamer
    gst_all_1.gst-plugins-base
    glib
  ];

  fonts = {
    enableDefaultPackages = true;
    fontDir.enable = true;
    fontconfig = {
      enable = true;
      useEmbeddedBitmaps = true;
    };
    packages = with pkgs; [
      fira-code
      font-awesome
      fira
      cooper-hewitt
      ibm-plex
      jetbrains-mono
      iosevka
      spleen
      fira-code-symbols
      blackout
      powerline-fonts
      noto-fonts-color-emoji
      noto-fonts
      noto-fonts-cjk-sans
      noto-fonts-emoji
      nerd-fonts.jetbrains-mono
      nerd-fonts.fira-code
      nerd-fonts._0xproto
      nerd-fonts.symbols-only
    ];
  };

  powerManagement = {
    enable = true;
  };

  services.power-profiles-daemon = {
    enable = true;
    package = pkgs.power-profiles-daemon;
  };

  # enable the OpenSSH daemon.
  services.openssh.enable = true;

  services.avahi = {
    enable = true;
    publish.enable = true;
    publish.userServices = true;
    openFirewall = true;
    nssmdns4 = true;
  };
  services.samba = {
    enable = true;
    package = pkgs.sambaFull;
    openFirewall = true;
  };
  services.samba-wsdd = {
    enable = true;
    openFirewall = true;
  };

  users.groups.uinput = { };
  # add user accounts
  users.users.emenel = {
    isNormalUser = true;
    description = "emenel";
    extraGroups = [
      "networkmanager"
      "network"
      "wheel"
      "uinput"
      "uucp"
      "dialout"
      "input"
      "audio"
      "video"
      "libvirtd"
      "nvidia"
      "cups"
      "openrazer"
      "plugdev"
      "i2c-dev"
      "scanner"
      "lp"
    ];
    packages = with pkgs; [
      git
    ];
  };







  #do not change
  system.stateVersion = "24.05";

}
