# 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 {
    environment.systemPackages = with pkgs; [
      rustup
      lldb # for lldb-vscode
      musl # for building static binaries
      cargo-semver-checks
      # ? cargo-bloat
      # ? cargo-outdated
      # ? cargo-public-api
    ];

    me.install.user.talexander.file = {
      ".cargo/config.toml" = {
        source = ./files/cargo_config.toml;
      };
      # ".rustup/settings.toml" = {
      #   source = ./files/rustup_settings.toml;
      # };
    };

    environment.persistence."/state" = lib.mkIf (config.me.mountPersistence) {
      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
            ];
          nativeBuildInputs = [ pkgs.makeWrapper ];
        };
      })
    ];
  };
}

# TODO: Install clippy, cranelift, rust-src
