{
  pkgs,
  lib,
  config,
  ...
}:
let
  capitalizeFirstLetter =
    str:
    (lib.strings.toUpper (builtins.substring 0 1 str))
    + (builtins.substring 1 (builtins.stringLength str) str);
in
{
  options.frogeye = {
    name = lib.mkOption {
      description = "Name of the system";
      type = lib.types.str;
    };
    toplevel = lib.mkOption {
      description = "top-level flake";
      type = lib.types.attrs;
    };
    cuda = lib.mkEnableOption "Use CUDA for some libraries";
    extra = lib.mkEnableOption "Big software";
    gaming = lib.mkEnableOption "Games";
    polarity = lib.mkOption {
      default = "light";
      description = "Whether to use light theme or dark theme.";
      type = lib.types.enum [
        "light"
        "dark"
      ];
    };
    desktop = {
      xorg = lib.mkEnableOption "Enable X11 support";
      # TODO Use appropriate OS/HM option(s) instead
      numlock = lib.mkEnableOption "Auto-enable numlock";
      x11_screens = lib.mkOption {
        default = [ "UNSET1" ];
        description = "A list of xrandr screen names from left to right.";
        type = lib.types.listOf lib.types.str;
      };
      maxVideoHeight = lib.mkOption {
        type = lib.types.int;
        description = "Maximum video height in pixel the machine can reasonably watch";
        default = 1080;
      };
      phasesCommands = {
        jour = lib.mkOption {
          type = lib.types.lines;
          default = "";
          description = "Command to execute for phase: jour";
        };
        crepuscule = lib.mkOption {
          type = lib.types.lines;
          default = "";
          description = "Command to execute for phase: crepuscule";
        };
        nuit = lib.mkOption {
          type = lib.types.lines;
          default = "";
          description = "Command to execute for phase: nuit";
        };
      };
    };
    dev = {
      "3d" = lib.mkEnableOption "3D (printing) / CAD stuff";
      ansible = lib.mkEnableOption "Ansible dev stuff";
      c = lib.mkEnableOption "C/C++ dev stuff";
      docker = lib.mkEnableOption "Docker dev stuff";
      go = lib.mkEnableOption "Go dev stuff";
      node = lib.mkEnableOption "NodeJS dev stuff";
      perl = lib.mkEnableOption "Perl dev stuff";
      php = lib.mkEnableOption "PHP dev stuff";
      prose = lib.mkEnableOption "Writing stuff";
      python = lib.mkEnableOption "Python dev stuff";
      vm = lib.mkEnableOption "Virtual machines";
    };
    storageSize = lib.mkOption {
      default = "small";
      type = lib.types.enum [
        "small"
        "big"
        "phone"
      ];
      description = "Type of storage for the device. Used to determine which folder to include.";
    };
    folders = lib.mkOption {
      default = { };
      description = "Folders used by users";
      # Top-level so Syncthing can work for all users. Also there's no real home-manager syncthing module.
      type = lib.types.attrsOf (
        lib.types.submodule (
          { config, name, ... }:
          {
            options = {
              name = lib.mkOption {
                type = lib.types.str;
                default = name;
                readOnly = true;
                internal = true;
                description = "Name accessing this entry";
              };
              enable = lib.mkOption {
                type = lib.types.bool;
                default = true;
                description = "Whether to use this folder.";
              };
              path = lib.mkOption {
                type = lib.types.str;
                description = "Path relative to HOME. Prefer French names which has more varied initials, easing navigation.";
              };
              label = lib.mkOption {
                type = lib.types.str;
                description = "Friendly name";
                default = capitalizeFirstLetter config.path;
              };
              user = lib.mkOption {
                type = lib.types.str;
                default = "geoffrey";
                description = "User using this directory.";
              };
              fullPath = lib.mkOption {
                type = lib.types.str;
                default = "/home/${config.user}/${config.path}";
                # Hardcoded due to outside of any user context
                description = "Absolute path.";
              };
              xdgUserDirVariable = lib.mkOption {
                type = lib.types.nullOr lib.types.str;
                default = if config.enable then "XDG_${lib.strings.toUpper name}_DIR" else null;
                description = "Name for the XDG user dir variable. If set, will automatically create the directory.";
              };
              syncthing = lib.mkOption {
                default = { };
                description = "Syncthing configuration for the folder";
                type = lib.types.submodule (
                  { ... }:
                  {
                    freeformType = (pkgs.formats.json { }).type;
                    options = {
                      enable = lib.mkOption {
                        type = lib.types.bool;
                        default = config.enable && config.syncthing.id != null;
                        description = "Whether to sync.";
                      };
                      id = lib.mkOption {
                        type = lib.types.nullOr lib.types.str;
                        default = null;
                        description = "Syncthing folder id";
                      };
                    };
                  }
                );
              };
              versionsMaxDays = lib.mkOption {
                type = lib.types.nullOr lib.types.int;
                default = 365;
                description = "For big systems, how many days of staggered versions should be kept";
              };
            };
          }
        )
      );
    };
    hooks.lock = lib.mkOption {
      type = lib.types.lines;
      default = "";
      description = "Bash commands to execute on locking the session.";
    };
    syncthing = {
      id = lib.mkOption {
        type = lib.types.nullOr lib.types.str;
        default = null;
        description = "Full syncthing id";
      };
      name = lib.mkOption {
        type = lib.types.nullOr lib.types.str;
        default = "Geoffrey ${capitalizeFirstLetter config.frogeye.name}";
        description = "Syncthing name";
      };
    };
  };

  config = {
    frogeye = {
      dev = {
        prose = lib.mkDefault true;
        python = lib.mkDefault true;
      };
      folders.download.path = "Téléchargements";
    };
  };
}