#Access Internet using:
#nmcli device wifi list
#nmcli device wifi connect <ssid> password <password>
# or if no password (open wifi)
#nmcli device wifi connect <ssid>

{ inputs, config, pkgs, lib, username, project, host, version, system, ... }:
{
  #Assign Swap to the PC
  #swapDevices = [{
  #  device = "/swapfile";
  #  size = 16 * 1024; # 16GB
  #}];

  imports =
  [
    inputs.home-manager.nixosModules.home-manager
    inputs.grub2-themes.nixosModules.default
    inputs.nix-flatpak.nixosModules.nix-flatpak
    ./hardware-configuration.nix

    ./firefox.nix
    ./boot-splash.nix
    ./zsh.nix
    ./neovim
    ./packages
  ];

  # Bootloader.
  boot = {
    kernelParams = [ "quiet" "splash" ];
    initrd = {
      verbose = false;
      kernelModules = [ "amdgpu" ];
    };
    loader = {
      systemd-boot.enable = false;
      efi.canTouchEfiVariables = true;
      #boot.loader.efi.efiSysMountPoint = "/boot/efi";

      grub = {
        enable = true;
        device = "/dev/nvme0n1";		#Needs to be changed when using a new computer! (Make grub partition - look below!)
        #devices = [ "nodev" ];
        efiSupport = true;
        useOSProber = true;
        configurationLimit = 5;
      };

      grub2-theme = {
          enable = true;
          theme = "whitesur";
          footer = true;
      };

      timeout = 10;
    };
  };
  
  #Ensure there is a grub_bios partition: (gparted)
  #Create a new parititon. File System: Unformatted - Size: ~5 Mib
  #Apply
  #Manage flags -> Add bios_grub

  networking = {
  
    # Enable networking
    networkmanager.enable = true;

    extraHosts = ''
      100.89.141.79 tail-rpi
    '';

    hostName = host;
    # Define your hostname.
    # wireless.enable = true;  # Enables wireless support via wpa_supplicant.

    # Configure network proxy if necessary
    # proxy.default = "http://user:password@proxy:port/";
    # proxy.noProxy = "127.0.0.1,localhost,internal.domain";

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

  home-manager = {
    useGlobalPkgs = true;
    useUserPackages = true;
    users.${username} = ./home.nix;
    backupFileExtension = "backup";		# Automatically backs up conflicting files during activation
    extraSpecialArgs = { inherit inputs username project version system host; };
    sharedModules = [ inputs.plasma-manager.homeModules.plasma-manager ];
  };

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

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

  i18n.extraLocaleSettings = {
    LC_ADDRESS = "de_DE.UTF-8";
    LC_IDENTIFICATION = "de_DE.UTF-8";
    LC_MEASUREMENT = "de_DE.UTF-8";
    LC_MONETARY = "de_DE.UTF-8";
    LC_NAME = "de_DE.UTF-8";
    LC_NUMERIC = "de_DE.UTF-8";
    LC_PAPER = "de_DE.UTF-8";
    LC_TELEPHONE = "de_DE.UTF-8";
    LC_TIME = "de_DE.UTF-8";
  };
  
  # List services that you want to enable:
  services = {
    ollama = {
      enable = true;
      # Optional: load models on startup
      #loadModels = [ ... ];
    };

    open-webui = {
      enable = true;
      package = pkgs.open-webui;
      #environment = {
      #  DATA_DIR = "/var/lib/open-webui";  # System-wide writable dir
      #  OLLAMA_API_BASE_URL = "http://127.0.0.1:11434";
      #};
      #openFirewall = true;
    };

    fprintd.enable = true;
    fprintd.tod.enable = true;
    fprintd.tod.driver = pkgs.libfprint-2-tod1-goodix;

    fwupd.enable = true;   #Allows BIOS updates

    locate = {
      enable = true;
      package = pkgs.plocate;
    };

    tailscale = {
      enable = true;
      useRoutingFeatures = "client";
      extraSetFlags = [
          "--operator=${username}"
          "--accept-routes"
      ];
    };

    # security.rtkit.enable = true;
    pipewire = {
      enable = true;
      alsa.enable = true;
      pulse.enable = true;
      #jack.enable = true;
    };

    pipewire.wireplumber = {
      enable = true;
      extraConfig = {
        "10-bluez-monitor.properties" = {
          "bluez5.msbc-support" = false;
          "bluez5.hfphsp-support" = false;
          "bluez5.hfphsp-backend" = "none";  # Key addition: no backend
          "bluez5.roles" = [ "a2dp_sink" ];
        };
        "11-bluetooth-policy" = {
          "wireplumber.settings" = {
            "bluetooth.autoswitch-to-headset-profile" = false;
          };
        };
      };
    };
    
    #Enable CUPS to print documents.
    printing.enable = true;
    
    # Enable the OpenSSH daemon.
    openssh.enable = true;
  };

  fonts = {
    packages = with pkgs; [
      font-awesome
      nerd-fonts.jetbrains-mono
      meslo-lgs-nf
      noto-fonts
      noto-fonts-cjk-sans
      noto-fonts-color-emoji
      inter
    ];

    fontconfig = {
      enable = true;
      
      defaultFonts = {
        monospace = [ "JetBrainsMono Nerd Font" "MesloLGS NF" ];
        sansSerif = [ "Inter" "Noto Sans" ];
        serif = [ "Noto Serif" ];
      };
    };
  };

  programs = {
    steam.enable = true;

    ssh.askPassword = lib.mkForce "${pkgs.kdePackages.ksshaskpass}/bin/ksshaskpass";

    #In order for dynamically linked executables to work
    nix-ld.enable = true;
  };

  # Configure console keymap
  console.keyMap = "de";

  hardware = {
    #Enables proprietary, redistributable firmware so hardware devices function properly
    enableRedistributableFirmware = true;

    graphics = {
      enable = true;
      # Mesa should be enabled by default for Vulkan, but you can be explicit
      enable32Bit = true; # For 32-bit applications
      extraPackages = with pkgs; [
        rocmPackages.clr.icd
        rocmPackages.rocm-smi
      ];
    };

    cpu.amd.updateMicrocode = true;

    amdgpu.opencl.enable = true;

    bluetooth = {
      enable = true;
      powerOnBoot = true;
      settings = {
        General = {
          # Shows battery charge of connected devices on supported
          # Bluetooth adapters. Defaults to 'false'.
          Experimental = true;
          # When enabled other devices can connect faster to us, however
          # the tradeoff is increased power consumption. Defaults to
          # 'false'.
          FastConnectable = true;
        };
        Policy = {
          # Enable all controllers when they are found. This includes
          # adapters present on start as well as adapters that are plugged
          # in later on. Defaults to 'true'.
          AutoEnable = true;
        };
      };
    };
  };

  # Define a user account. Don't forget to set a password with ‘passwd’.
  users.users.${username} = {
    isNormalUser = true;
    description = "Cookiez";
    extraGroups = [ "networkmanager" "wheel" "docker" ];
    packages = with pkgs; [
      #User Packages Here
    ];
  };

  virtualisation = {
    docker.enable = true;

    #podman = {
    #  enable = true;
    #  dockerCompat = true;
    #};

    waydroid.enable = true;
  };

  environment = {
    etc."gitconfig".text = ''
      [init]
        defaultBranch = main
    '';

    variables = {
      EDITOR = "nvim";
      # XKB_DEFAULT_LAYOUT = "de";
    };

    sessionVariables = {
      NIXOS_OZONE_WL = "1";   #For chromium to work under wayland and with virtual Keyboards (Only really needed for virtual keyboards, but doest hurt ...)
      TERMINAL = "kitty";
    };
  };

  #So no user in the group Wheel has to input the password in order to use sudo
  security = {
    sudo.wheelNeedsPassword = false;

    pam.services = {
      login.fprintAuth = true;
      sudo.fprintAuth = true;
      kde.fprintAuth = false;
      hyprlock = {};
    };
  };

  #Allow Nix Commands
  nix.settings.experimental-features = [ "nix-command" "flakes" ];
  
  # Allow unfree packages
  nixpkgs.config.allowUnfree = true;

  # This value determines the NixOS release from which the default
  # settings for stateful data, like file locations and database versions
  # on your system were taken. It‘s perfectly fine and recommended to leave
  # this value at the release version of the first install of this system.
  # Before changing this value read the documentation for this option
  # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
  system.stateVersion = version; # Did you read the comment?
}
