{ lib, ... }:
let
  inherit (lib) mkOption types;

  collection = types.either types.str (types.listOf types.str);
in
{
  options.vdirsyncer = {
    enable = lib.mkEnableOption "synchronization using vdirsyncer";

    urlCommand = mkOption {
      type = types.nullOr (types.listOf types.str);
      default = null;
      example = [ "~/get-url.sh" ];
      description = "A command that prints the URL of the storage.";
    };

    userNameCommand = mkOption {
      type = types.nullOr (types.listOf types.str);
      default = null;
      example = [ "~/get-username.sh" ];
      description = "A command that prints the user name to standard output.";
    };

    collections = mkOption {
      type = types.nullOr (types.listOf collection);
      default = null;
      description = ''
        The collections to synchronize between the storages.
      '';
    };

    conflictResolution = mkOption {
      type = types.nullOr (
        types.either (types.enum [
          "remote wins"
          "local wins"
        ]) (types.listOf types.str)
      );
      default = null;
      description = ''
        What to do in case of a conflict between the storages. Either
        `remote wins` or
        `local wins` or
        a list that contains a command to run. By default, an error
        message is printed.
      '';
    };

    partialSync = mkOption {
      type = types.nullOr (
        types.enum [
          "revert"
          "error"
          "ignore"
        ]
      );
      default = null;
      description = ''
        What should happen if synchronization in one direction
        is impossible due to one storage being read-only.
        Defaults to `revert`.

        See
        <https://vdirsyncer.pimutils.org/en/stable/config.html#pair-section>
        for more information.
      '';
    };

    metadata = mkOption {
      type = types.listOf types.str;
      default = [ ];
      example = [
        "color"
        "displayname"
      ];
      description = ''
        Metadata keys that should be synchronized when vdirsyncer
        metasync is executed.
      '';
    };

    timeRange = mkOption {
      type = types.nullOr (
        types.submodule {
          options = {
            start = mkOption {
              type = types.str;
              description = "Start of time range to show.";
            };

            end = mkOption {
              type = types.str;
              description = "End of time range to show.";
            };
          };
        }
      );
      default = null;
      description = ''
        A time range to synchronize. start and end can be any Python
        expression that returns a `datetime.datetime`
        object.
      '';
      example = {
        start = "datetime.now() - timedelta(days=365)";
        end = "datetime.now() + timedelta(days=365)";
      };
    };

    itemTypes = mkOption {
      type = types.nullOr (types.listOf types.str);
      default = null;
      description = ''
        Kinds of items to show. The default is to show everything.
        This depends on particular features of the server, the results
        are not validated.
      '';
    };

    useVcard4 = mkOption {
      type = types.bool;
      default = false;
      description = ''
        Specifies whether vdirsyncer should request vCards in version 4.0.
        If set to `false` then vdirsyncer will default to version 3.0.
      '';
    };

    verify = mkOption {
      type = types.nullOr types.path;
      default = null;
      description = "Null or path to certificate to verify SSL against";
      example = "/path/to/cert.pem";
    };

    verifyFingerprint = mkOption {
      type = types.nullOr types.str;
      default = null;
      description = ''
        Optional. SHA1 or MD5 fingerprint of the expected server certificate.

        See
        <https://vdirsyncer.pimutils.org/en/stable/ssl-tutorial.html#ssl-tutorial>
        for more information.
      '';
    };

    auth = mkOption {
      type = types.nullOr (
        types.enum [
          "basic"
          "digest"
          "guess"
        ]
      );
      default = null;
      description = ''
        Authentication settings. The default is `basic`.
      '';
    };

    authCert = mkOption {
      type = types.nullOr (types.either types.str (types.listOf types.str));
      default = null;
      description = ''
        Either a path to a certificate with a client certificate and
        the key or a list of paths to the files with them.
      '';
    };

    userAgent = mkOption {
      type = types.nullOr types.str;
      default = null;
      description = ''
        The user agent to report to the server. Defaults to
        `vdirsyncer`.
      '';
    };

    postHook = mkOption {
      type = types.nullOr types.lines;
      default = null;
      description = ''
        Command to call for each item creation and modification.
        The command will be called with the path of the new/updated
        file.
      '';
    };

    ## Options for google storages

    tokenFile = mkOption {
      type = types.nullOr types.str;
      default = null;
      description = ''
        A file path where access tokens are stored.
      '';
    };

    clientIdCommand = mkOption {
      type = types.nullOr (types.listOf types.str);
      default = null;
      example = [
        "pass"
        "client_id"
      ];
      description = ''
        A command that prints the OAuth credentials to standard
        output.

        See
        <https://vdirsyncer.pimutils.org/en/stable/config.html#google>
        for more information.
      '';
    };

    clientSecretCommand = mkOption {
      type = types.nullOr (types.listOf types.str);
      default = null;
      example = [
        "pass"
        "client_secret"
      ];
      description = ''
        A command that prints the OAuth credentials to standard
        output.

        See
        <https://vdirsyncer.pimutils.org/en/stable/config.html#google>
        for more information.
      '';
    };
  };
}
