# 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 = with pkgs; [
    nix-index
    git

    # Programming Stuff, language servers etc
    gcc
    gradle
    nodejs
    typescript
    deno
    # 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
    vscode-langservers-extracted
    lua-language-server
    yaml-language-server
    ansible-language-server
    ansible-lint
    nginx-language-server
    docker-compose-language-service
    nodePackages.prettier
    nodePackages.typescript-language-server
    nodePackages.bash-language-server
    python312Packages.jedi-language-server
    nixd

    neovim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
    emacs-gtk
    fastfetch
    appimage-run
    imagemagick
    yt-dlp
    python3
    cifs-utils
    exfatprogs
    usbutils
    inetutils
    pciutils
    xdg-user-dirs
    linuxPackages.usbip
    unixtools.xxd
    dotnet-sdk
  ];
  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"
    ];
  };
  
  fonts.packages = with pkgs; [
    nerdfonts
  ];

  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" ];
  };

  # Allow unfree packages
  nixpkgs.config.allowUnfree = 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}";
  };

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

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

  # 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 ];
   	allowedTCPPortRanges = [ 
  		{ from = 1714; to = 1764; } 
  	];
  	# allowedUDPPorts = [ ... ];
   	allowedUDPPortRanges = [ 
  		{ from = 1714; to = 1764; } 
  	];
  	# Or disable the firewall altogether.
  	enable = true;
  };

  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?

}
