{
  config,
  lib,
  ...
}:
let
  mkUserJs =
    with lib;
    prefs: extraPrefs: ''
      // Generated by Geoffrey's dotfiles.

      ${concatStrings (
        mapAttrsToList (name: value: ''
          user_pref("${name}", ${builtins.toJSON value});
        '') prefs
      )}
      ${extraPrefs}
    '';

  toThunderbirdCalendar =
    account:
    let
      id = builtins.hashString "sha256" account.name;
      thunderbird = config.frogeye.accounts.calendar.accounts.${account.name};
    in
    {
      "calendar.registry.${id}.cache.enabled" = thunderbird.offlineSupport; # TODO Check this actually corresponds
      "calendar.registry.${id}.color" = thunderbird.color;
      "calendar.registry.${id}.forceEmailScheduling" = thunderbird.clientSideEmailScheduling;
      "calendar.registry.${id}.imip.identity.key" = "id_${builtins.hashString "sha256" thunderbird.email}";
      "calendar.registry.${id}.name" = account.name;
      "calendar.registry.${id}.readOnly" = thunderbird.readOnly;
      "calendar.registry.${id}.refreshInterval" = builtins.toString thunderbird.refreshInterval;
      "calendar.registry.${id}.suppressAlarms" = !thunderbird.showReminders; # TODO Check this actually corresponds
      "calendar.registry.${id}.type" = account.remote.type; # TODO Check and validate supported types
      "calendar.registry.${id}.uri" = account.remote.url;
      "calendar.registry.${id}.username" = account.remote.userName;
      # Unimplemented
      "calendar.registry.${id}.notifications.times" = "";
      # Unknown
      # "calendar.registry.${id}.calendar-main-in-composite" = true;
    };
in
{
  config = {
    programs.aerc = {
      enable = true;
      extraConfig.general.unsafe-accounts-conf = true;
    };
    programs.thunderbird = {
      enable = config.frogeye.desktop.xorg;
      profiles.hm = {
        isDefault = true;
        withExternalGnupg = true;
        extraConfig = mkUserJs (lib.attrsets.mergeAttrsList (
          # Add calendar config
          (lib.mapAttrsToList (
            name: account: (toThunderbirdCalendar account)
          ) config.accounts.calendar.accounts)
          ++
            # Add config for every identity (kinda)
            (lib.mapAttrsToList (name: account: ({
              # UPST Make signature be used in Thunderbird
              "mail.identity.id_${builtins.hashString "sha256" account.address}.htmlSigText" =
                account.signature.text;
              "mail.identity.id_${builtins.hashString "sha256" account.address}.compose_html" = false;
            })) config.accounts.email.accounts)
          ++
            # General settings
            [
              {
                "mail.pane_config.dynamic" = 0;
                "intl.date_time.pattern_override.date_short" = "yyyy-MM-dd";
              }
            ]

        )) "";
      };
    };
  };
  # UPST Thunderbird-specific options (should be named so), to be included in HM Thunderbird module
  options = {
    frogeye.accounts.calendar.accounts = lib.mkOption {
      default = { };
      type = lib.types.attrsOf (
        lib.types.submodule (
          { config, name, ... }:
          {
            # TODO Set defaults as Thunderbird sets it
            options = {
              color = lib.mkOption {
                type = lib.types.str;
                default = "#5277c3";
              };
              refreshInterval = lib.mkOption {
                type = lib.types.int;
                default = 0; # 0 = Manual
              };
              readOnly = lib.mkOption {
                type = lib.types.bool;
                default = false;
              };
              showReminders = lib.mkOption {
                type = lib.types.bool;
                default = true;
              };
              offlineSupport = lib.mkOption {
                type = lib.types.bool;
                default = true;
              };
              email = lib.mkOption {
                type = lib.types.str;
                # TODO Nullable
                # TODO Ensure it actually matches an email identity
              };
              clientSideEmailScheduling = lib.mkOption {
                type = lib.types.bool;
                default = false;
              };
            };
          }
        )
      );
    };
  };
}