{ lib, config, ... }:
let
  inherit (lib) types mkOption;
  cfg = config.valhalla.fileSystems;

  mountType = types.submodule (
    { config, name, ... }: {
      options = {
        device = mkOption {
          type = types.nullOr types.str;
          description = "The device to mount.";
          default = null;
        };

        mountPoint = mkOption {
          type = types.str;
          description = "The path to mount the device to.";
          default = name;
        };

        fsType = mkOption {
          type = types.nullOr types.str;
          description = "The file system type of the mount.";
          default = null;
        };

        options = mkOption {
          type = types.listOf types.str;
          description = "The options of the mount.";
          default = [ ];
        };
      };
    }
  );
in
{
  imports = [
    ./fileSystems/btrfs.nix
    ./fileSystems/disks.nix
  ];

  options = {
    valhalla = {
      fileSystems = {
        rootDir = mkOption {
          type = types.str;
          description = "The root of the installation directory to mount disks into.";
          default = "/mnt";
        };

        mounts = mkOption {
          type = types.attrsOf mountType;
          description = "The devices to mount.";
          default = { };
        };

        script = mkOption {
          type = types.str;
          description = "The script for preparing the system's mounts.";
        };
      };
    };
  };

  config = {
    valhalla = {
      fileSystems = {
        script =
          let
            inherit (lib.strings) normalizePath removeSuffix;
            devices = (builtins.attrValues cfg.diskSetup.devices);
            mountScript = lib.strings.concatLines (
              (builtins.concatMap
                (
                  _: [
                    "partprobe 2> /dev/null || true"
                    "udevadm trigger"
                    (builtins.concatStringsSep " " (
                      [ "sudo" "mount" "--mkdir" ] ++
                      (lib.optionals (_.fsType == "ntfs") [ "-t" "ntfs3" ]) ++
                      [
                        (builtins.concatStringsSep " " (builtins.map (_: "-o ${_}") _.options))
                        (_.device)
                        (removeSuffix "/" (normalizePath "/${cfg.rootDir}/${_.mountPoint}"))
                      ]
                    ))
                  ]
                )
                (builtins.attrValues cfg.mounts))
            );

            affected = (builtins.map (_: _.deviceVariable) devices) ++
              (builtins.concatMap
                (_: builtins.map (_: lib.escapeShellArg _) _.devices)
                (builtins.attrValues cfg.btrfs.volumes));
          in
          ''
            #!/bin/bash
            set -o errexit
            ${cfg.diskSetup.scripts.init}
            ${lib.strings.concatLines (lib.optionals ((builtins.length devices) > 0) [
              ''echo "$(tput setaf 3)=== WARNING ====$(tput sgr0)"''
              (''echo "Continuing this script will alter the partitions of ''
              + (lib.strings.concatStringsSep ", " (lib.lists.init affected))
              + (if (builtins.length affected) > 1 then " and " else "") + (lib.lists.last affected) + ''"'')
              ''
                if ! fish ${./fileSystems/confirm.fish} "Are you sure you want to continue?" "n"; then
                  exit 1
                fi
              ''
              ])}
            ${cfg.diskSetup.scripts.partition}
            ${cfg.btrfs.script}
            ${mountScript}
            ${cfg.diskSetup.scripts.swap}
          '';
      };
    };
  };
}