# 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’).

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

{
  nix.settings.experimental-features = [ "nix-command" "flakes" ];

  # For USBIP Server configuration, to share USBKeys etc with my server (Which is the client)
  boot.extraModulePackages = with config.boot.kernelPackages; [ usbip ];
  boot.kernelModules = [ "usbip_host" ];

  services.flatpak.enable = true;

  environment.systemPackages = let 
  	# You can specify here if you want to add any packages from the stable branch onto your system
	stablePackages = with inputs.nixpkgs-stable.legacyPackages.x86_64-linux; [
	  gtk-pipe-viewer
    mpdcron
	];

  # Enable OpenGL/Vulkan hardware acceleration etc
  hardware = {
    ## radv: an open-source Vulkan driver from freedesktop
    graphics = {
      enable = true;
      enable32Bit = true;
      extraPackages = with pkgs; [
        gfxreconstruct
        glslang
        spirv-cross
        spirv-headers
        spirv-tools
        vulkan-extension-layer
        vulkan-headers
        vulkan-loader
        vulkan-tools
        vulkan-tools-lunarg
        vulkan-utility-libraries
        vulkan-validation-layers
        vkdisplayinfo
        vkd3d
        vkd3d-proton
        vk-bootstrap
      ];
    };

    ## amdvlk: an open-source Vulkan driver from AMD
    amdgpu.amdvlk = {
        enable = true;
        support32Bit.enable = true;
        extraPackages = with pkgs; [
          gfxreconstruct
          glslang
          spirv-cross
          spirv-headers
          spirv-tools
          vulkan-extension-layer
          vulkan-headers
          vulkan-loader
          vulkan-tools
          vulkan-tools-lunarg
          vulkan-utility-libraries
          vulkan-validation-layers
          vkdisplayinfo
          vkd3d
          vkd3d-proton
          vk-bootstrap
        ];
    };
  };

  # Enable proper support for USB wifi/Wwan adapters.
  hardware.usbWwan.enable = true;

  # You can specify here what python packages you waint available to python
  # Custom Python package with all the (Python) imports I need
  my-python-packages = python-packages: with python-packages; [ # ...
    setuptools
    watchdog
    epc
    six
    rapidfuzz
    paramiko
    packaging
  ];
  python-with-my-packages = pkgs.python3.withPackages my-python-packages;
  in
  	# Normal (unstable) packages
  	with pkgs; [
      inputs.blue-build.packages.${pkgs.system}.bluebuild
      python-with-my-packages

      nix-prefetch-scripts
  	  nix-index
  	  git
	    wget
      efibootmgr
	    ntfs3g

  	  # Programming Stuff, language servers etc
  	  gcc
      cmake
      libtool
  	  swift
  	  swiftPackages.Foundation
  	  swiftpm
  	  sourcekit-lsp	
  	  gradle
  	  nodejs
  	  typescript
  	  deno
	  go
	  gopls
  	  # Purely for the tooling
  	  postgresql

  	  sqlite # For development and also telescope-all-recent

  	  # Debugging/LSP related tooling
  	  gdb
  	  lldb_18 # For lldb-dap
  	  clang-tools # clangd
  	  jdt-language-server # Java language server
  	  gnumake
  	  cargo
  	  lua-language-server
  	  yaml-language-server
  	  ansible-language-server
  	  #ansible-lint
  	  nginx-language-server
  	  emmet-language-server
  	  vscode-langservers-extracted
  	  docker-compose-language-service
  	  # nodePackages.prettier
  	  nodePackages.typescript-language-server
  	  nodePackages.bash-language-server
  	  python312Packages.jedi-language-server
  	  nixd

  	  #(neovim.overrideAttrs (oldAttrs: {
	  #      buildInputs = oldAttrs.buildInputs ++ [ pkgs.xorg.libX11 ];
	  #})) # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
	  neovim
	  xorg.libX11
  	  zoxide # A fast cd command that learns your habits
  	  tealdeer # A very fast implementation of tldr in Rust
  	  sc-im

  	  emacs-gtk
      	  #((inputs.emacs-overlay.packages.x86_64-linux.emacs-unstable-pgtk.overrideAttrs (oldAttrs: { 
	    #	buildInputs = oldAttrs.buildInputs ++ [ pkgs.webkitgtk ];
	    #})).override {
      #      withXwidgets = true;
	    #})
	    #(emacs30-pgtk.overrideAttrs (oldAttrs: {
	    #	nativeBuildInputs = oldAttrs.nativeBuildInputs ++ [ pkgs.webkitgtk_4_0 ];
	    #	buildInputs = oldAttrs.buildInputs ++ [ pkgs.webkitgtk_4_0 ];
	    #}))
	    #emacs30-gtk3 # Emacs 30 currently bugged with lsp-bridge, see https://github.com/manateelazycat/lsp-bridge/issues/1123

  	  fastfetch
  	  appimage-run
  	  imagemagick
  	  yt-dlp
  	  cifs-utils
  	  exfatprogs
  	  usbutils
  	  inetutils
  	  pciutils
  	  xdg-user-dirs
  	  linuxPackages.usbip
  	  unixtools.xxd
  	  dotnet-sdk

      # Tools for Vulkan
      gfxreconstruct
      glslang
      spirv-cross
      spirv-headers
      spirv-tools
      vulkan-extension-layer
      vulkan-headers
      vulkan-loader
      vulkan-tools
      vulkan-tools-lunarg
      vulkan-utility-libraries
      vulkan-validation-layers
      vkdisplayinfo
      vkd3d
      vkd3d-proton
      vk-bootstrap


      #wineWowPackages.full
      winetricks
      # native wayland support (unstable)
      wineWowPackages.waylandFull

      firefox
      librewolf
      ungoogled-chromium
      # nyxt
      qutebrowser
      telegram-desktop
      #(discord.override {
      #   # remove any overrides that you don't want
      #   withOpenASAR = true;
      #   withVencord = true;
      #})
      (vesktop.override { withSystemVencord = false; }) # Discord Client Alternative
      discordo # Discord terminal client
      element-desktop
      # cinny-desktop
      freetube
      
      (pidgin.override { 
        plugins = [ 

          # purple-discord updated to 2024-11-23 from 2021-10-17
	        (purple-discord.overrideAttrs (oldAttrs: {
            src = fetchFromGitHub {
              owner = "EionRobb";
              repo = "purple-discord";
              rev = "c5dfbe0e1fd7de1f2adbf672f653f67e39686044";
              sha256 = "BJuw2F+7twEK8ukEwxsMhDcyVkSS6tK8iJ8uM5kygB8=";
            };
	          buildInputs = oldAttrs.buildInputs ++ [ nss qrencode ];
	        })) 

          # Switch to updated fork by BenWiederhake
	        (tdlib-purple.overrideAttrs (oldAttrs: {
            patches = [];
            src = fetchFromGitHub {
              owner = "BenWiederhake";
              repo = "tdlib-purple";
              rev = "43e6cc2f14ccd08171b1515f6216f4bbf84eed80";
              sha256 = "Uq8yfz6UM+U296nFnZtRuUGHdcNoTCHev6GcWTy+Ys0=";
            };
            meta = with lib; {
              homepage = "https://github.com/BenWiederhake/tdlib-purple";
              description = "libpurple Telegram plugin using tdlib";
              license = licenses.gpl2Plus;
              maintainers = with maintainers; [ sikmir ];
              platforms = platforms.unix;

              broken = false;
            };
	        })) 

        ];
      })
      # pidginPackages.tdlib-purple

      lutris
      protonup-qt
      qpwgraph

      #ardour
      #rnnoise-plugin
      #lsp-plugins
      (yabridge.override { wine = wineWowPackages.waylandFull; })
      (yabridgectl.override { wine = wineWowPackages.waylandFull; })
      #(yabridge.override { wine = wineWowPackages.full; })
      #(yabridgectl.override { wine = wineWowPackages.full; })
      audacity
      lmms

      furnace
      vgm2x

      MIDIVisualizer
      kdePackages.kdenlive
      vlc
      # unityhub
      veracrypt
      boxbuddy
      distrobox
      qdirstat
      kid3
      # brasero
      # kdePackages.k3b
      # xfce.xfburn
      ffmpeg
      ventoy-full
      qbittorrent
      krita

      gimp
      gimpPlugins.gmic

      darktable

      obs-studio
      prismlauncher
      
      pass-wayland
      thunderbird
      protonmail-desktop

      texliveFull
      ripgrep
      fd
      fzf

      yazi
      ueberzugpp # To display images in yazi via alacritty

      ncdu
      
      # Just for utils
      pulseaudio
      alsa-utils
      
      # For curl scripts
      jq
      libnotify

  	] ++ stablePackages;

  # Enable ADB Tools for android development
  programs.adb.enable = true;

  systemd.services.usbipd = {
    description = "Custom service that runs usbipd";
    wantedBy = [ "multi-user.target" ];
    path = with pkgs; [ linuxPackages.usbip ];
    enable = true;
    serviceConfig = {
      User = "root";
      Group = "root";
    };
    script = "
           usbipd
    ";
  };

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

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

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

  # Configure keymap in X11
  services.xserver.xkb = {
    layout = "gb";
    variant = "";
  };

  # Console (TTY) Configuration
  console = {
    # Configure console keymap
    keyMap = "uk";
    # Configure console colors (Gruvbox Light) - More colourschemes at https://github.com/kolunmi/ttyscheme/blob/main/ttyscheme
    colors = [
      "fbf1c7"
      "cc241d"
      "98971a"
      "d79921"
      "458588"
      "b16286"
      "689d6a"
      "7c6f64"
      "928374"
      "9d0006"
      "79740e"
      "b57614"
      "076678"
      "8f3f71"
      "427b58"
      "3c3836"
    ];
  };

  # TODO: Fix
  fonts.packages = with pkgs; [
    #nerdfonts
    #inputs.apple-fonts.packages.${pkgs.system}.sf-pro-nerd
    inputs.apple-fonts.packages.${pkgs.system}.sf-compact-nerd
    inputs.apple-fonts.packages.${pkgs.system}.sf-mono-nerd
    inputs.apple-fonts.packages.${pkgs.system}.sf-arabic-nerd
  ];

  users.groups.plugdev = {};
  # Define a user account. Don't forget to set a password with ‘passwd’.
  users.users.cspark = {
    isNormalUser = true;
    description = "Curt Spark";
    extraGroups = [ "plugdev" "networkmanager" "wheel" "libvirtd" "libvirt" "kvm" "input" "docker" "cdrom" "adbusers" ];
  };

  # Allow unfree packages
  nixpkgs.config.allowUnfree = true;
  # Accept android license
  nixpkgs.config.android_sdk.accept_license = true;

  # Due to NixOS not using FHS paths, many DAWs will not know where to look for VSTs and other plugins. You can solve this by setting 
  environment.variables = let
    makePluginPath = format:
      (lib.strings.makeSearchPath format [
        "$HOME/.nix-profile/lib"
        "/run/current-system/sw/lib"
        "/etc/profiles/per-user/$USER/lib"
      ])
      + ":$HOME/.${format}";
  in {
    DSSI_PATH   = makePluginPath "dssi";
    LADSPA_PATH = makePluginPath "ladspa";
    LV2_PATH    = makePluginPath "lv2";
    LXVST_PATH  = makePluginPath "lxvst";
    VST_PATH    = makePluginPath "vst";
    VST3_PATH   = makePluginPath "vst3";

    # Dotnet libicu not found fix
    DOTNET_SYSTEM_GLOBALIZATION_INVARIANT = "1";

    # Dotnet path not found fix
    DOTNET_ROOT = "${pkgs.dotnet-sdk}";

    # Set neovim to be used instead of less for viewing manpages
    # MANPAGER = "nvim +Man!";
    MANPAGER = "emacsclient -c";

    # Nicer terminal prompt
    PS1="\[\e[0;36m\]\u\[\e[0m\]@\[\e[0;33m\]\h\[\e[0m\]:\[\e[0;35m\]\w\[\e[0m\] \$ ";

    PATH = "/run/current-system/sw/bin" + builtins.getEnv "PATH";
  };

  # NixOS Dynamic Libraries Fix
  programs.nix-ld.enable = true;
  programs.nix-ld.libraries = with pkgs; [
    # Add any missing dynamic libraries for unpackaged programs
    # here, NOT in environment.systemPackages
    icu
    vulkan-extension-layer
    vulkan-headers
    vulkan-loader
    vulkan-tools
    vulkan-tools-lunarg
    vulkan-utility-libraries
    vulkan-validation-layers
    vkdisplayinfo
    vkd3d
    vkd3d-proton
    vk-bootstrap
  ];

  # Systemwide Java support
  programs.java = {
    enable = true;
    #package = pkgs.jdk17;
    package = pkgs.jdk23;
  };

  # Emacs Config Init Service - For root user also
  systemd.services.emacs-config-initialiser = {
    description = "Initialises default emacs configuration if not available";
    wantedBy = [ "multi-user.target" ];
    path = with pkgs; [ coreutils git ];
    enable = true;
    serviceConfig = {
      User = "root";
      Group = "root";
    };
    script = "
      if [[ ! -d $HOME/.emacs.d ]]; then
        mkdir -p $HOME/.emacs.d
        git clone https://git.cspark.dev/cspark/Emacs-Configuration $HOME/.emacs.d
      else
        exit 0
      fi
    ";
  };

  # Neovim Config Init Service - For root user also
  systemd.services.neovim-config-initialiser = {
    description = "Initialises default neovim configuration if not available";
    wantedBy = [ "multi-user.target" ];
    path = with pkgs; [ coreutils git ];
    enable = true;
    serviceConfig = {
      User = "root";
      Group = "root";
    };
    script = "
      if [[ ! -d $HOME/.config/nvim ]]; then
        mkdir -p $HOME/.config/nvim
        git clone https://git.cspark.dev/cspark/Neovim-Configuration $HOME/.config/nvim
      else
        exit 0
      fi
    ";
  };

  # Emacs install and enable daemon/server mode.
  #services.emacs = {
  #  enable = true;
  #  package = pkgs.emacs-gtk;
  #};
  #systemd.services.emacs = {
  #  description = "Emacs server daemon for root";
  #  wantedBy = [ "multi-user.target" ];
  #  path = with pkgs; [ emacs-gtk ];
  #  enable = true;
  #  serviceConfig = {
  #    User = "root";
  #    Group = "root";
  #  };
  #  script = "
  #    emacs --daemon
  #  ";
  #};

  # Virt Manager Installation
  virtualisation.libvirtd.enable = true;
  programs.virt-manager.enable = true;
  virtualisation.spiceUSBRedirection.enable = true;


  # 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;
  programs.ssh.startAgent = true;

  # Open ports in the firewall.
  # 3240 - USBIP Port
  # 1714 to 1764 - KDEConnect
  networking.firewall = {
  	allowedTCPPorts = [ 3240 25565 ];
   	allowedTCPPortRanges = [ 
  		{ from = 1714; to = 1764; } 
  	];
  	allowedUDPPorts = [ 25565 ];
   	allowedUDPPortRanges = [ 
  		{ from = 1714; to = 1764; } 
  	];
  	# Or disable the firewall altogether.
  	enable = true;
  };

  # Disable powersave feature on network cards.
  networking.networkmanager.wifi.powersave = false;

  # Use the preserved MAC address of the network card.
  networking.networkmanager.wifi.macAddress = "preserve";
  networking.networkmanager.wifi.scanRandMacAddress = false;

  services.udev.extraRules = ''
  ## Rules file for NetMD devices and HiMD devices in NetMD mode
  ## source: https://usb-ids.gowdy.us/read/UD/054c
  ## last changed: 2011-06-29
  
  ## HiMD
  
  # Sony MZ-NH1
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="017e", MODE="0664", GROUP="plugdev"
  
  # Sony MZ-NH3D
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0180", MODE="0664", GROUP="plugdev"
  
  # Sony MZ-NH900
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0182", MODE="0664", GROUP="plugdev"
  
  # Sony MZ-NH700/800
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0184", MODE="0664", GROUP="plugdev"
  
  # Sony MZ-NH600/600D
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0186", MODE="0664", GROUP="plugdev"
  
  # Sony MZ-DH10P
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="01e9", MODE="0664", GROUP="plugdev"
  
  # Sony MZ-RH10
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0219", MODE="0664", GROUP="plugdev"
  
  # Sony MZ-RH910
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="021b", MODE="0664", GROUP="plugdev"
  
  # Sony CMT-AH10
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="022c", MODE="0664", GROUP="plugdev"
  
  # Sony DS-HMD1
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="023c", MODE="0664", GROUP="plugdev"
  
  # Sony MZ-RH1
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0286", MODE="0664", GROUP="plugdev"
  
  
  ## NetMD
  
  # Aiwa AM-NX1
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0113", MODE="0664", GROUP="plugdev"
  
  # Aiwa AM-NX9
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="014c", MODE="0664", GROUP="plugdev"
  
  # Sharp IM-MT880H/MT899H
  ATTRS{idVendor}=="04dd", ATTRS{idProduct}=="7202", MODE="0664", GROUP="plugdev"
  
  # Sharp IM-DR400/DR410
  ATTRS{idVendor}=="04dd", ATTRS{idProduct}=="9013", MODE="0664", GROUP="plugdev"
  
  # Sharp IM-DR420/DR80/DR580 - Kenwood DMC-S9NET
  ATTRS{idVendor}=="04dd", ATTRS{idProduct}=="9014", MODE="0664", GROUP="plugdev"
  
  # Sony NetMD (unknown model)
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0036", MODE="0664", GROUP="plugdev"
  
  # Sony NetMD MZ-N1
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0075", MODE="0664", GROUP="plugdev"
  
  # Sony NetMD (unknown model)
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="007c", MODE="0664", GROUP="plugdev"
  
  # Sony NetMD LAM-1
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0080", MODE="0664", GROUP="plugdev"
  
  # Sony NetMD MDS-JE780/JB980
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0081", MODE="0664", GROUP="plugdev"
  
  # Sony MZ-N505
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0084", MODE="0664", GROUP="plugdev"
  
  # Sony NetMD MZ-S1
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0085", MODE="0664", GROUP="plugdev"
  
  # Sony NetMD MZ-N707
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0086", MODE="0664", GROUP="plugdev"
  
  # Sony MZ-N10
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="00c6", MODE="0664", GROUP="plugdev"
  
  # Sony NetMD MZ-N910
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="00c7", MODE="0664", GROUP="plugdev"
  
  # Sony NetMD MZ-N710/NF810/NE810
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="00c8", MODE="0664", GROUP="plugdev"
  
  # Sony NetMD MZ-N510/NF610
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="00c9", MODE="0664", GROUP="plugdev"
  
  # Sony MZ-N410/NF520D
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="00ca", MODE="0664", GROUP="plugdev"
  
  # Sony NetMD MZ-NE810/NE910/DN430
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="00eb", MODE="0664", GROUP="plugdev"
  
  # Sony NetMD LAM-10
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0101", MODE="0664", GROUP="plugdev"
  
  # Sony MZ-N920
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0188", MODE="0664", GROUP="plugdev"
  
  # Sony NetMD LAM-3
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="018a", MODE="0664", GROUP="plugdev"
  
  # Sony NetMD CMT-AH10
  ATTRS{idVendor}=="054c", ATTRS{idProduct}=="021d", MODE="0664", GROUP="plugdev"
  '';

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

}
