# MANUAL: rustup target add x86_64-unknown-linux-musl
# MANUAL: rustup target add wasm32-unknown-unknown
# MANUAL: rustup component add rustc-codegen-cranelift
{
  config,
  lib,
  pkgs,
  ...
}:

let
  cargo_wrapped =
    package: prog:
    pkgs.writeShellScriptBin "${prog}" ''
      export PATH="$PATH:${
        lib.makeBinPath [
          pkgs.clang
          pkgs.pkg-config # Needed for openssl-sys
        ]
      }"
      # Needed for openssl-sys
      export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:${pkgs.openssl.dev}/lib/pkgconfig"
      exec ${package}/bin/${prog} "''${@}"
    '';
in
{
  imports = [ ];

  options.me = {
    rust.enable = lib.mkOption {
      type = lib.types.bool;
      default = false;
      example = true;
      description = "Whether we want to install rust.";
    };
  };

  config = lib.mkIf config.me.rust.enable (
    lib.mkMerge [
      {
        environment.systemPackages = with pkgs; [
          rustup
          lldb # for lldb-vscode
          musl # for building static binaries
          cargo-semver-checks
          # ? cargo-bloat
          # ? cargo-outdated
          # ? cargo-public-api
        ];

        home-manager.users.talexander =
          { pkgs, ... }:
          {
            home.file = {
              ".cargo/config.toml" = {
                source = ./files/cargo_config.toml;
              };
              ".rustup/settings.toml" = {
                source = ./files/rustup_settings.toml;
              };
            };
          };

        environment.persistence."/state" = lib.mkIf (!config.me.buildingIso) {
          hideMounts = true;
          users.talexander = {
            directories = [
              {
                directory = ".rustup";
                user = "talexander";
                group = "talexander";
                mode = "0755";
              }
              {
                directory = ".cargo/registry";
                user = "talexander";
                group = "talexander";
                mode = "0755";
              }
            ];
          };
        };

        systemd.services.link-rust-creds = {
          # Contains credentials so it cannot be added to the nix store
          enable = true;
          description = "link-rust-creds";
          wantedBy = [ "multi-user.target" ];
          wants = [ "multi-user.target" ];
          after = [ "multi-user.target" ];
          # path = with pkgs; [
          #   zfs
          # ];
          unitConfig.DefaultDependencies = "no";
          serviceConfig = {
            Type = "oneshot";
            RemainAfterExit = "yes";
          };
          script = ''
            if [ -e /persist/manual/rust/cargo_credentials.toml ]; then
              install --directory --owner talexander --group talexander --mode 0755 /home/talexander/.cargo
              ln -s /persist/manual/rust/cargo_credentials.toml /home/talexander/.cargo/credentials.toml
            fi
          '';
          preStop = ''
            rm -f /home/talexander/.cargo/credentials.toml
          '';
        };

        nixpkgs.overlays = [
          (final: prev: {
            rustup = pkgs.symlinkJoin {
              name = "rustup";
              paths =
                (builtins.map (cargo_wrapped prev.rustup) [
                  "cargo"
                  "cargo-clippy"
                  "cargo-fmt"
                  "cargo-miri"
                  "clippy-driver"
                  "rls"
                  "rust-analyzer"
                  "rust-gdb"
                  "rust-gdbgui"
                  "rust-lldb"
                  "rustc"
                  "rustdoc"
                  "rustfmt"
                  "rustup"
                ])
                ++ [
                  prev.rustup
                ];
              buildInputs = [ pkgs.makeWrapper ];
            };
          })
        ];
      }
    ]
  );
}

# TODO: Install clippy, cranelift, rust-src