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

with pkgs;

let hybrid-codec-vaapiIntel = vaapiIntel.override { enableHybridCodec = true; };

in {
  # Kernel configuration
  boot = {
    kernelPackages = linuxPackages_zen;
    kernelParams = [
      "zfs.zfs_arc_max=1073741824"
      "zfs.zfs_arc_meta_limit_percent=90"
      "i915.i915_enable_fbc=1"
      "workqueue.power_efficient=y"
    ];
    kernelModules = [ "i915" "acpi_call" "kvm-intel" ];
    extraModulePackages = with config.boot.kernelPackages; [ acpi_call ];
    blacklistedKernelModules = [ "btusb" ];
    supportedFilesystems = [ "zfs" ];
    zfs = {
      requestEncryptionCredentials = true;
      enableUnstable = true;
    };
  };

  # Intel CPU tweaks
  hardware.cpu.intel.updateMicrocode =
    lib.mkDefault config.hardware.enableRedistributableFirmware;
  services.fwupd.enable = true;

  # GPU Hardware acceleration
  hardware.opengl.extraPackages =
    [ intel-media-driver hybrid-codec-vaapiIntel vaapiVdpau libvdpau-va-gl ];

  # Bootloader configuration
  boot.loader = {
    efi.canTouchEfiVariables = true;
    systemd-boot = {
      enable = true;
      configurationLimit = 50;
      editor = false;
    };
    timeout = 3;
  };

  # Run Nix garbage collector and enable flakes
  nix = {
    settings = {
      auto-optimise-store = true;
      trusted-users = [ "root" "coolneng" ];
    };
    gc = {
      automatic = true;
      options = "--delete-older-than 7d";
      dates = "Tue 23:00";
    };
    extraOptions = ''
      keep-outputs = true
      keep-derivations = true
      gc-keep-outputs = true
      experimental-features = nix-command flakes
    '';
    package = nixUnstable;
  };

  # Clean tmp directory on shutdown
  boot.cleanTmpDir = true;

  # Rotate logs after 7 days
  services.journald.extraConfig = "SystemMaxFiles=7";

  # Allow propietary software and build packages with Pulseaudio support
  nixpkgs.config = {
    allowUnfree = true;
    pulseaudio = true;
  };

  # Scrub zpool monthly
  services.zfs.autoScrub = {
    enable = true;
    interval = "monthly";
  };

  # Set timezone and synchronize NTP
  time.timeZone = "Europe/Brussels";
  services.chrony.enable = true;

  # NixOS version
  system.stateVersion = "20.09";

  # Create coolneng user
  users.users.coolneng = {
    isNormalUser = true;
    home = "/home/coolneng";
    extraGroups = [ "wheel" "video" "audio" "libvirtd" "lp" ];
    shell = fish;
  };

  # Set shell for root user
  users.users.root.shell = fish;

  # Specify secrets
  age = {
    secrets.wireguard.file = secrets/wireguard.age;
    secrets.syncthing.file = secrets/syncthing.age;
    secrets.samba-ugent.file = secrets/samba-ugent.age;
    secrets.msmtp.file = secrets/msmtp.age;
    identityPaths = [ "/etc/ssh/id_ed25519" ];
  };

  # Enable internal microphone when headphones are plugged in and add workaround for frequent WiFi disconnects
  hardware.firmware = [
    (writeTextDir "/lib/firmware/hda-jack-retask.fw" ''
      [codec]
      0x10ec0293 0x17aa2233 0

      [pincfg]
      0x12 0x90a60130
      0x13 0x40000000
      0x14 0x90170110
      0x15 0x03211040
      0x16 0x21211010
      0x18 0x411111f0
      0x19 0x21a11010
      0x1a 0x40f000f0
      0x1b 0x411111f0
      0x1d 0x40738105
      0x1e 0x411111f0
    '')
  ];
  boot.extraModprobeConfig = ''
    options snd-hda-intel patch=hda-jack-retask.fw
    options mac80211 beacon_loss_count=500
  '';

  # Use same version of nixpkgs for nix-shell
  nix.nixPath = let path = toString ./.;
  in [ "nixpkgs=${inputs.nixpkgs}" "nixos-config=${path}/configuration.nix" ];

  # Auto-upgrade the system
  system.autoUpgrade = {
    enable = true;
    dates = "22:30";
    flake = "/home/coolneng/Projects/panacea";
    flags = [
      "--update-input"
      "agenix"
      "--update-input"
      "nixpkgs"
      "--commit-lock-file"
    ];
  };

  # Configure git for auto-upgrade
  programs.git = {
    enable = true;
    config = {
      user.name = "coolneng";
      user.email = "akasroua@gmail.com";
      safe.directory = "/home/coolneng/Projects/panacea";
    };
  };

  # Import other configuration modules
  imports = [
    ./modules/hardware-configuration.nix
    ./modules/software.nix
    ./modules/networking.nix
    ./modules/gui.nix
    ./modules/datasync.nix
    ./modules/audio.nix
    ./modules/development.nix
    ./modules/printing.nix
    ./modules/periodic.nix
    ./modules/power.nix
    ./modules/monitoring.nix
    ./overlays/nix-direnv.nix
    ./overlays/openconnect-sso.nix
    ./overlays/cyrus-sasl-oauth2.nix
  ];

}