{ lib, ... }:

let
  inherit (lib) mkOption;
  inherit (lib.types) types;

in
{
  options.fediversityVm = {

    ##########################################################################
    ## Meta

    name = mkOption {
      description = ''
        The name of the machine. Most of the time, this will look like `vm02XXX`
        or `fediYYY`.
      '';
    };

    proxmox = mkOption {
      type = types.nullOr (
        types.enum [
          "procolix"
          "fediversity"
        ]
      );
      description = ''
        The Proxmox instance. This is used for provisioning only and should be
        set to `null` if the machine is not a VM.
      '';
    };

    vmId = mkOption {
      # REVIEW: There is `types.ints.between` but maybe not `types.ints.above`?
      type = types.nullOr (types.addCheck types.int (x: x >= 100));
      description = ''
        The id of the machine in the corresponding Proxmox. This is used for
        provisioning only and should be set to `null` if the machine is not a
        VM.
      '';
    };

    description = mkOption {
      description = ''
        A human-readable description of the machine's purpose. It should be
        constituted of a first line giving a very short description, followed
        by a blank line, then followed by more details if necessary.
      '';
      default = "";
    };

    ##########################################################################
    ## Virtualised hardware

    sockets = mkOption {
      type = types.int;
      description = "The number of sockets of the VM.";
      default = 1;
    };

    cores = mkOption {
      type = types.int;
      description = "The number of cores of the VM.";
      default = 1;
    };

    memory = mkOption {
      type = types.int;
      description = "The amount of memory of the VM in MiB.";
      default = 2048;
    };

    diskSize = mkOption {
      type = types.int;
      description = "The amount of disk of the VM in GiB.";
      default = 32;
    };

    ##########################################################################
    ## Networking

    domain = mkOption {
      description = ''
        The domain hosting the machine. Most of the time, this will be either of
        `procolix.com`, `fediversity.eu` or `abundos.eu`.
      '';
      default = "procolix.com";
    };

    ipv4 = {
      address = mkOption {
        description = ''
          The IP address of the machine, version 4. It will be injected as a
          value in `networking.interfaces.eth0`, but it will also be used to
          communicate with the machine via NixOps4.
        '';
      };

      prefixLength = mkOption {
        description = ''
          The subnet mask of the interface, specified as the number of bits in
          the prefix.
        '';
        default = 24;
      };

      gateway = mkOption {
        description = ''
          The IP address of the default gateway.
        '';
        default = "185.206.232.1"; # FIXME: compute default from `address` and `prefixLength`.
      };
    };

    ipv6 = {
      address = mkOption {
        description = ''
          The IP address of the machine, version 6. It will be injected as a
          value in `networking.interfaces.eth0`, but it will also be used to
          communicate with the machine via NixOps4.
        '';
      };

      prefixLength = mkOption {
        description = ''
          The subnet mask of the interface, specified as the number of bits in
          the prefix.
        '';
        default = 64;
      };

      gateway = mkOption {
        description = ''
          The IP address of the default gateway.
        '';
        default = "2a00:51c0:12:1201::1"; # FIXME: compute default from `address` and `prefixLength`.
      };
    };

    hostPublicKey = mkOption {
      description = ''
        The ed25519 host public key of the machine. It is used to filter Age
        secrets and only keep the relevant ones, and to feed to NixOps4.
      '';
    };

    unsafeHostPrivateKey = mkOption {
      default = null;
      description = ''
        The ed25519 host private key of the machine. It is used when
        provisioning to have a predictable public key. Warning: only ever use
        this for testing machines, as it is a security hole for so many reasons.
      '';
    };
  };
}