# Edit this configuration file to define what should be installed on
# your system.  Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running ‘nixos-help’).

# New TODO: 
# - investigate tmux-session-wizard, and tpm
# - see if zoxide can import .z file (from z.sh)
# - so far, have added aliases and bashrc directly, along with bin folder and ssh setup.
# - aaaaaah! so much

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

{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
      inputs.home-manager.nixosModules.default
      ./main-user.nix
    ];

  #fileSystems."/mnt/arch" =
  #  { device = "/dev/disk/by-uuid/72db20ba-4dbd-4fb7-891c-b457e2cf9648";
  #    fsType = "btrfs";
  #    options = [ "subvol=5" ];
  #  };
  #fileSystems."/mnt/arch/home" =
  #  { device = "/dev/disk/by-uuid/4eda05c2-d434-495d-97a0-8a81e8a533ec";
  #    fsType = "btrfs";
  #    options = [ "subvol=5" ];
  #  };
  #fileSystems."/mnt/bulk" =
  #  { device = "/dev/disk/by-uuid/xxxx";
  #    fsType = "ext4";
  #  };
  #fileSystems."/mnt/slow" =
  #  { device = "/dev/disk/by-uuid/xxxx";
  #    fsType = "etx4";
  #  };

  boot.initrd.luks.devices."nvme2n1p2_oldcrypt".device = "/dev/disk/by-uuid/44235dca-99e8-4ea8-9516-97d9f5a2d702";

  # Temporarily pin to 6.12 to fix llvm/rocm build
  # https://github.com/NixOS/nixpkgs/issues/368672#issuecomment-2608697421
  # boot.kernelPackages = pkgs.linuxPackages_6_12;
  boot.kernelPackages = pkgs.linuxPackages_zen;
  # nct6775 - for monitoring functions on ASUS ROG STRIX B550-F GAMING WIFI II
  # kvm-amd - AMD virtualization support
  boot.kernelModules = [ "kvm-amd" "nct6775" ];

  # Direct patching for enabling for async reprojection (for SteamVR) on AMD
  boot.kernelPatches = [
    {
      name = "amdgpu-ignore-ctx-privileges";
      patch = pkgs.fetchpatch {
        name = "cap_sys_nice_begone.patch";
        url = "https://github.com/Frogging-Family/community-patches/raw/master/linux61-tkg/cap_sys_nice_begone.mypatch";
        hash = "sha256-Y3a0+x2xvHsfLax/uwycdJf3xLxvVfkfDVqjkxNaYEo=";
      };
    }
  ];
  services.fwupd.enable = true;
  services.hardware.openrgb.enable = true;
  # Add flakes
  nix.settings.experimental-features = [ "nix-command" "flakes" ];

  # Feel like I should be sure this is safe w/flakes first:
  #system.autoUpgrade.enable = true;

  # sets up things so envs can do shebang whatever
  # instead of #!/usr/bin/env whatever
  #services.envfs.enable = true;

  # Bootloader.
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  # System name
  networking.hostName = "supercell"; # Define your hostname.
  # networking.wireless.enable = true;  # Enables wireless support via wpa_supplicant.

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

  # Enable networking
  networking.networkmanager.enable = true;

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

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

  i18n.extraLocaleSettings = {
    LC_ADDRESS = "en_US.UTF-8";
    LC_IDENTIFICATION = "en_US.UTF-8";
    LC_MEASUREMENT = "en_US.UTF-8";
    LC_MONETARY = "en_US.UTF-8";
    LC_NAME = "en_US.UTF-8";
    LC_NUMERIC = "en_US.UTF-8";
    LC_PAPER = "en_US.UTF-8";
    LC_TELEPHONE = "en_US.UTF-8";
    LC_TIME = "en_US.UTF-8";
  };

  # Enable the X11 windowing system.
  # You can disable this if you're only using the Wayland session.
  # services.xserver.enable = true;

  # Enable the KDE Plasma Desktop Environment.
  services.displayManager.sddm.enable = true;
  services.displayManager.sddm.wayland.enable = true;
  services.desktopManager.plasma6.enable = true;

  # Configure keymap in X11 (presumably, XWayland uses something different?)
  #services.xserver.xkb = {
  #  layout = "us";
  #  variant = "";
  #};

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

  # Enable CUPS to print documents.
  # ...no. Recent security issues, prefer disabled
  # apps like e.g. LibreOffice can still generate pdf's (e.g. to stand in [generally] for Print to pdf)
  # services.printing.enable = true;

  # Enable sound with pipewire.
  services.pulseaudio.enable = false;
  security.rtkit.enable = true;
  services.pipewire = {
    enable = true;
    alsa.enable = true;
    alsa.support32Bit = true;
    pulse.enable = true;
    # If you want to use JACK applications, uncomment this
    #jack.enable = true;

    # use the example session manager (no others are packaged yet so this is enabled by default,
    # no need to redefine it in your config for now)
    #media-session.enable = true;
  };

  # Enable touchpad support (enabled default in most desktopManager).
  # services.xserver.libinput.enable = true;
  # Define a user account. Don't forget to set a password with ‘passwd’.
  # Note that extraGroups overrides the module defaults entirely (they don't merge...probably a lib.* thing for that?)
  # Pull defaults from main-user:
  main-user.enable = true;
  main-user.userName = "wolcen";
  # And system-specific settings:
  users.users.wolcen = {
    description = "Chris Thompson";
    openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEdxdKYrlwOolJpYxvWu6gW/60pzT6aKN6JHhnTSBFqN wolcen@typhoon" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINTFJeOIRwEw09EhFdssRHOdb+T7o84FC+ULMQzXDewE wolcen@wolcen-ThinkPad-X220" ];
    extraGroups = [ "networkmanager" "wheel" "docker" "dialout" ];
  };

  home-manager = {
    extraSpecialArgs = { inherit inputs; };
    users = {
      "wolcen" = import ./home.nix;
    };
  };
  
  # Install firefox.
  programs.firefox.enable = true;

  # Required for DDEV to add hosts files, if your DNS will not resolve addresses to localhost.
  # Some firewall DNS resolvers will NOT allow an externally resolved domain name to resolve to a reserved IP (e.g. localhost).
  # This is a security protection method that can assist attackers with discovery of a LAN.
  # With fpSense, you can tell unbound (or dnsmasq) to resolve *.ddev.site to 127.0.0.1 and remove this mode statement
  # See https://docs.netgate.com/pfsense/en/latest/services/dns/wildcards.html
  # environment.etc.hosts.mode = "0644";

  # For xdebug...verify actual necessity
  # Have had to use this, but I think it can be disabled still - perhaps w/xdebug binding setting...don't know.
  #networking.firewall.allowedTCPPorts = [ 9003 ];

  networking.firewall = {
    allowedTCPPorts = [ 9003 ];
    allowedUDPPorts = [ 51820 ];
    # if packets are still dropped, they will show up in dmesg
    logReversePathDrops = true;
    checkReversePath = "loose";
    # wireguard trips rpfilter up
    #extraCommands = ''
    #  ip46tables -t mangle -I nixos-fw-rpfilter -p udp -m udp --sport 51820 -j RETURN
    #  ip46tables -t mangle -I nixos-fw-rpfilter -p udp -m udp --dport 51820 -j RETURN
    #'';
    #extraStopCommands = ''
    #  ip46tables -t mangle -D nixos-fw-rpfilter -p udp -m udp --sport 51820 -j RETURN || true
    #  ip46tables -t mangle -D nixos-fw-rpfilter -p udp -m udp --dport 51820 -j RETURN || true
    #'';
  };
  # Allow unfree packages
  nixpkgs.config.allowUnfree = true;

  # List packages installed in system profile. To search, run:
  # $ nix search wget
  environment.systemPackages = with pkgs; [
    binutils # gnu bin utils
    neovim # next gen vim w/lua
    wget # url fetcher/spider
    curl # url fetcher
    tmux # terminal multiplexer
    whois # net ip/dns lookup
    meld # file diff'r
    wl-clipboard-rs # rust implementation of wayland clipboard cli
    dogdns # a better dig cmd
    bat # a better cat command
    nix-search-cli # search the nix repo
    lsof # show open file handles
    eza # a better ls
    lm_sensors # hardware monitoring (e.g. temps)
    btop # cli sys monitor
    amdgpu_top # top-like monitor for AMD GPUs
    direnv # autoload .envrc files
    zoxide # directory navigator (z)
    nextcloud-client # next cloud UI
    file # show file types
    tldr # cli command summary
    stress # system workload generator
    dmidecode # system settings provider (e.g. bios)
    jq # json query
    niv # dependency cli for nix-shell
    openrgb-with-all-plugins # colors hardware control
    just # command runner like make
    #ansible # configuration management system/automation tool
    kdePackages.kcachegrind # analyze xdebug output
    kdePackages.filelight # disk space visualizer
    libreoffice-qt # libreoffice - qt is best for KDE
    hunspell # spell checking
    hunspellDicts.en_US # spell check dictionary
    #corectl # this doesn't exist????
    magic-wormhole # transfer files with ease
    screen # terminal multiplexer...from GNU
    gnumake # build automation tool
    git-open # open the url of the project in web
    diffr # another diff hilighting tool
    brave # privacy oriented browser
    zig # the zig language
    powerline # prompt utility
    distrobox # instant alternate OS availability
    pigz # muti-treaded replacement for gzip
    unzip # old standard zip handler
    rpi-imager # rasbperry pi os burner util
    screenkey # broadcast key presses 
    superfile # cli file manager
    mpv # movie player
    #obs-studio # open broadcast studio
    protonup-qt # proton version installer
    heroic # game launcher (GOG/Epic/Prime)
    lutris # game launcher (EA/Humble/Ubi++)
    cruft # python-based template processor
    nmap # network mapping/scanning tool
    basalt-monado # tracking for VR
    opencomposite # compatibility layer for VR
    # why did these two disappear???
    usbutils # provide lsusb, etc.
    pciutils # provide lspci, etc.
    #rustdesk # the rustdesk remote desktop client
    vorta # borg backup UI
    ncdu # nncurses tool for examining disk usage
    psmisc # process tools like killall
    corectrl # provide hardware clock controls for AMDGPU
    gimp # GIMP image manipulation proggy
  ];
  programs.zsh.enable = true;
  programs.git = {
    enable = true;
    lfs.enable = true;
  };
  # Orchestrator for FOSS VR stack
  programs.envision = {
    enable = true;
    openFirewall = true; # This is set true by default
  };
  #nixpkgs.config.permittedInsecurePackages = [
  #  "electron-27.3.11"
  #];
  fonts.packages = with pkgs; [
    anonymousPro
    corefonts
    dejavu_fonts
    dina-font
    fira-code
    fira-code-symbols
    gohufont
    inconsolata
    liberation_ttf
    #nerd-fonts
    nerd-fonts._0xproto
    nerd-fonts._3270
    nerd-fonts.anonymice
    nerd-fonts.daddy-time-mono
    nerd-fonts.hack
    nerd-fonts.jetbrains-mono
    nerd-fonts.monofur
    nerd-fonts.monoid
    nerd-fonts.roboto-mono
    nerd-fonts.sauce-code-pro
    nerd-fonts.shure-tech-mono
    nerd-fonts.space-mono
    nerd-fonts.ubuntu
    nerd-fonts.ubuntu-mono
    nerd-fonts.zed-mono
    noto-fonts
    noto-fonts-color-emoji
    noto-fonts-monochrome-emoji
    mplus-outline-fonts.githubRelease
    mononoki
    powerline-fonts
    proggyfonts
  ];

  # 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;
  # };

  # List services that you want to enable:

  # Enable the OpenSSH daemon.
  services.openssh.enable = true;
  services.openssh.ports = [ 2112 ]; # must be a list...for some reason.
  services.openssh.settings.PasswordAuthentication = false;
  services.openssh.settings.LogLevel = "VERBOSE"; # required for fail2ban to work properly
  services.fail2ban.enable = true; # by default, the SSH jail enabled
  # Enable mobile shell (for roaming, intermittent connectivity, etc)
  programs.mosh.enable = true;
  # Enable remote desktop access via rustdesk
  #services.rustdesk-server.enable = false;
  #services.rustdesk-server.openFirewall = false;
  # RX 6700 XT setup
  hardware.graphics.extraPackages = [
    pkgs.amdvlk
    pkgs.libcap
    pkgs.libva
    pkgs.mesa
    pkgs.rocmPackages.clr.icd
    #pkgs.pcre2
    #pkgs.libselinux
    #pkgs.rocmPackages.rocblas
    #pkgs.rocmPackages.rocm-smi
    #pkgs.rocmPackages.rocminfo
    #pkgs.rocmPackages.hipblas
    #pkgs.rocmPackages.rocm-device-libs
    #pkgs.rocmPackages.rpp
  ];

  # To enable Vulkan support for 32-bit applications, also add:
  hardware.graphics.extraPackages32 = [
    pkgs.driversi686Linux.amdvlk
  ];

  hardware.amdgpu.opencl.enable = true;

  services.ollama = {
    enable = true;
    acceleration = "rocm";
    #environmentVariables = {
    #  HCC_AMDGPU_TARGET = "gfx1031"; # used to be necessary, but doesn't seem to anymore
    #};
    rocmOverrideGfx = "10.3.0";
  };
  system.activationScripts = {
    script.text = ''
      install -d -m 755 /home/wolcen/.open-webui -o root -g root
    '';
   };
  virtualisation = {
    # Add docker!
    docker.enable = true;
    podman.enable = false;
    docker.storageDriver = "btrfs"; # Only when using BTRFS! (wolcen approved!)
    oci-containers = {
      backend = "docker";
      containers = {
        open-webui = {
            image = "ghcr.io/open-webui/open-webui:main";

            environment = {
              "TZ" = "America/New York";
              "OLLAMA_API_BASE_URL" = "http://127.0.0.1:11434/api";
              "OLLAMA_BASE_URL" = "http://127.0.0.1:11434";
              "WEBUI_URL" = "http://127.0.0.1:8080/";
            };

            volumes = [
              "/home/wolcen/.openweb-ui:/app/backend/data"
            ];

            ports = [
              "127.0.0.1:3000:8080" # Ensures we listen only on localhost
            ];

            extraOptions = [
              "--pull=always" # Pull if the image on the registry is newer
              "--name=open-webui"
              "--hostname=open-webui"
              "--network=host"
              "--add-host=host.containers.internal:host-gateway"
            ];
          };
      };
    };
  };
  # Force radv
  environment.variables.AMD_VULKAN_ICD = "RADV";
  # Or
  #environment.variables.VK_ICD_FILENAMES =
  #	"/run/opengl-driver/share/vulkan/icd.d/radeon_icd.x86_64.json";

  # Steam
  programs.steam = {
    enable = true;
    remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play
    dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server
    localNetworkGameTransfers.openFirewall = true; # Open ports in the firewall for Steam Local Network Game Transfers
  };
  # VR
  #Commmand: `renice -20 -p $(pgrep monado)` may help w/issues
  #services.monado = {
  #  enable = true;
  #  defaultRuntime = true; # Register as default OpenXR runtime
  #};
  #systemd.user.services.monado.environment = {
  #  WMR_HANDTRACKING = "0"; # Enable for hand tracking
  #  XRT_PRINT_OPTIONS = "1"; # Enable printing env vars set/available
  #  VIT_SYSTEM_LIBRARY_PATH = "${pkgs.basalt-monado}/lib/libbasalt.so";
  #  #U_PACING_COMP_MIN_TIME_MS = "5"; # This is a tweak for something...I forgot
  #};
  # allow clock adjustments/priority change, etc (gamemoderun ./game)
  # https://wiki.nixos.org/wiki/GameMode
  programs.gamemode.enable = true; # for performance mode
  #programs.java.enable = true;
  #programs.steam.package = pkgs.steam.override { withJava = true; };

  programs.steam.gamescopeSession.enable = true;

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

  # 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 = "24.05"; # Did you read the comment?

}