/* eslint-disable */

/**
 * MIT License
 *
 * Copyright (c) 2020 GitHub user u/garronej
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/** Take theses type definition with a grain of salt.
 * Some values might be undefined on some pages.
 * (ex: url.loginAction is undefined on error.ftl)
 */
export type KcContextBase =
  | KcContextBase.Login
  | KcContextBase.Register
  | KcContextBase.RegisterUserProfile
  | KcContextBase.Error
  | KcContextBase.LoginResetPassword
  | KcContextBase.LoginVerifyEmail
  | KcContextBase.Terms
  | KcContextBase.LoginOtp
  | KcContextBase.LoginUsername
  | KcContextBase.WebauthnAuthenticate
  | KcContextBase.LoginPassword
  | KcContextBase.LoginUpdatePassword
  | KcContextBase.LoginUpdateProfile
  | KcContextBase.LoginIdpLinkConfirm
  | KcContextBase.LoginIdpLinkEmail
  | KcContextBase.LoginPageExpired
  | KcContextBase.LoginConfigTotp
  | KcContextBase.LogoutConfirm
  | KcContextBase.UpdateUserProfile
  | KcContextBase.IdpReviewUserProfile;

export type WebauthnAuthenticator = {
  credentialId: string;
  label: string;
  createdAt: string;
};

export type AuthenticationSelection = {
  authExecId: string;
  authenticationExecution: {
    alternative: boolean;
    enabled: boolean;
    authenticator:
      | "auth-otp-form"
      | "webauthn-authenticator"
      | "auth-recovery-authn-code-form";
    priority: string;
  };
};

export declare namespace KcContextBase {
  export type Common = {
    url: {
      loginAction: string;
      resourcesPath: string;
      resourcesCommonPath: string;
      loginRestartFlowUrl: string;
      loginUrl: string;
    };
    realm: {
      name: string;
      displayName?: string;
      displayNameHtml?: string;
      internationalizationEnabled: boolean;
      registrationEmailAsUsername: boolean;
    };
    locale?: {
      supported: {
        url: string;
        label: string;
        languageTag: string;
      }[];
      currentLanguageTag: string;
    };
    auth?: {
      showUsername?: boolean;
      showResetCredentials?: boolean;
      showTryAnotherWayLink?: boolean;
      attemptedUsername?: string;
    };
    scripts: string[];
    message?: {
      type: "success" | "warning" | "error" | "info";
      summary: string;
    };
    client: {
      clientId: string;
      name?: string;
      description?: string;
    };
    isAppInitiatedAction: boolean;
  };

  export type Login = Common & {
    url: {
      loginResetCredentialsUrl: string;
      registrationUrl: string;
    };
    realm: {
      loginWithEmailAllowed: boolean;
      rememberMe: boolean;
      password: boolean;
      resetPasswordAllowed: boolean;
      registrationAllowed: boolean;
    };
    auth: {
      selectedCredential?: string;
    };
    registrationDisabled: boolean;
    login: {
      username?: string;
      rememberMe?: boolean;
    };
    usernameEditDisabled: boolean;
    social: {
      displayInfo: boolean;
      providers?: {
        loginUrl: string;
        alias: string;
        providerId: string;
        displayName: string;
      }[];
    };
  };

  export type RegisterCommon = Common & {
    url: {
      registrationAction: string;
    };
    passwordRequired: boolean;
    recaptchaRequired: boolean;
    recaptchaSiteKey?: string;
    social: {
      displayInfo: boolean;
      providers?: {
        loginUrl: string;
        alias: string;
        providerId: string;
        displayName: string;
      }[];
    };
  };

  export type Register = RegisterCommon & {
    register: {
      formData: {
        firstName?: string;
        displayName?: string;
        lastName?: string;
        email?: string;
        username?: string;
      };
    };
  };

  export type RegisterUserProfile = RegisterCommon & {
    profile: {
      context: "REGISTRATION_PROFILE";
      attributes: Attribute[];
      attributesByName: Record<string, Attribute>;
    };
  };

  export type Error = Common & {
    client?: {
      baseUrl?: string;
    };
    message: NonNullable<Common["message"]>;
  };

  export type LoginResetPassword = Common & {
    realm: {
      loginWithEmailAllowed: boolean;
    };
  };

  export type LoginVerifyEmail = Common & {
    user?: {
      email: string;
    };
  };

  export type Terms = Common & {};

  export type LoginOtp = Common & {
    otpLogin: {
      userOtpCredentials: { id: string; userLabel: string }[];
    };
  };

  export type LoginUsername = Common & {
    url: {
      loginResetCredentialsUrl: string;
      registrationUrl: string;
    };
    realm: {
      loginWithEmailAllowed: boolean;
      rememberMe: boolean;
      password: boolean;
      resetPasswordAllowed: boolean;
      registrationAllowed: boolean;
    };
    registrationDisabled: boolean;
    login: {
      username?: string;
      rememberMe?: boolean;
    };
    usernameHidden?: boolean;
    social: {
      displayInfo: boolean;
      providers?: {
        loginUrl: string;
        alias: string;
        providerId: string;
        displayName: string;
      }[];
    };
  };

  export type LoginPassword = Common & {
    url: {
      loginResetCredentialsUrl: string;
      registrationUrl: string;
    };
    realm: {
      resetPasswordAllowed: boolean;
    };
    auth?: {
      showUsername?: boolean;
      showResetCredentials?: boolean;
      showTryAnotherWayLink?: boolean;
      attemptedUsername?: string;
    };
    social: {
      displayInfo: boolean;
    };
    login: {
      password?: string;
    };
  };

  export type WebauthnAuthenticate = Common & {
    authenticators: {
      authenticators: WebauthnAuthenticator[];
    };
    challenge: string;
    userVerification: UserVerificationRequirement | "not specified";
    rpId: string;
    createTimeout: string;
    isUserIdentified: "true" | "false";
    shouldDisplayAuthenticators: boolean;
    social: {
      displayInfo: boolean;
    };
    login: {};
  };

  export type LoginUpdatePassword = Common & {
    username: string;
  };

  export type LoginUpdateProfile = Common & {
    user: {
      editUsernameAllowed: boolean;
      username?: string;
      email?: string;
      firstName?: string;
      lastName?: string;
    };
  };

  export type LoginIdpLinkConfirm = Common & {
    idpAlias: string;
  };

  export type LoginIdpLinkEmail = Common & {
    brokerContext: {
      username: string;
    };
    idpAlias: string;
  };

  export type LoginPageExpired = Common & {
    pageId: "login-page-expired.ftl";
  };

  export type LoginConfigTotp = Common & {
    pageId: "login-config-totp.ftl";
    mode?: "qr" | "manual" | undefined | null;
    totp: {
      totpSecretEncoded: string;
      qrUrl: string;
      policy: {
        supportedApplications: string[];
        algorithm: "HmacSHA1" | "HmacSHA256" | "HmacSHA512";
        digits: number;
        lookAheadWindow: number;
      } & (
        | {
            type: "totp";
            period: number;
          }
        | {
            type: "hotp";
            initialCounter: number;
          }
      );
      totpSecretQrCode: string;
      manualUrl: string;
      totpSecret: string;
      otpCredentials: { id: string; userLabel: string }[];
    };
  };

  export type LogoutConfirm = Common & {
    pageId: "logout-confirm.ftl";
    url: {
      logoutConfirmAction: string;
    };
    client: {
      baseUrl?: string;
    };
    logoutConfirm: {
      code: string;
      skipLink?: boolean;
    };
  };

  export type UpdateUserProfile = Common & {
    pageId: "update-user-profile.ftl";
    profile: {
      attributes: Attribute[];
      attributesByName: Record<string, Attribute>;
    };
  };

  export type IdpReviewUserProfile = Common & {
    pageId: "idp-review-user-profile.ftl";
    profile: {
      context: "IDP_REVIEW";
      attributes: Attribute[];
      attributesByName: Record<string, Attribute>;
    };
  };

  export type SAMLPostForm = Common & {
    pageId: "saml-post-form.ftl";
    samlPost: {
      url: string;
      SAMLRequest?: string;
      SAMLResponse?: string;
      relayState?: string;
    };
  };

  export type SelectAuthenticator = Common & {
    auth: {
      authenticationSelections: Array<AuthenticationSelection>;
    };
  };
}

export type Attribute = {
  name: string;
  displayName?: string;
  required: boolean;
  value?: string;
  group?: string;
  groupDisplayHeader?: string;
  groupDisplayDescription?: string;
  readOnly: boolean;
  validators: Validators;
  annotations: Record<string, string>;
  groupAnnotations: Record<string, string>;
  autocomplete?:
    | "on"
    | "off"
    | "name"
    | "honorific-prefix"
    | "given-name"
    | "additional-name"
    | "family-name"
    | "honorific-suffix"
    | "nickname"
    | "email"
    | "username"
    | "new-password"
    | "current-password"
    | "one-time-code"
    | "organization-title"
    | "organization"
    | "street-address"
    | "address-line1"
    | "address-line2"
    | "address-line3"
    | "address-level4"
    | "address-level3"
    | "address-level2"
    | "address-level1"
    | "country"
    | "country-name"
    | "postal-code"
    | "cc-name"
    | "cc-given-name"
    | "cc-additional-name"
    | "cc-family-name"
    | "cc-number"
    | "cc-exp"
    | "cc-exp-month"
    | "cc-exp-year"
    | "cc-csc"
    | "cc-type"
    | "transaction-currency"
    | "transaction-amount"
    | "language"
    | "bday"
    | "bday-day"
    | "bday-month"
    | "bday-year"
    | "sex"
    | "tel"
    | "tel-country-code"
    | "tel-national"
    | "tel-area-code"
    | "tel-local"
    | "tel-extension"
    | "impp"
    | "url"
    | "photo";
};

export type Validators = Partial<{
  length: Validators.DoIgnoreEmpty & Validators.Range;
  double: Validators.DoIgnoreEmpty & Validators.Range;
  integer: Validators.DoIgnoreEmpty & Validators.Range;
  email: Validators.DoIgnoreEmpty;
  "up-immutable-attribute": {};
  "up-attribute-required-by-metadata-value": {};
  "up-username-has-value": {};
  "up-duplicate-username": {};
  "up-username-mutation": {};
  "up-email-exists-as-username": {};
  "up-blank-attribute-value": Validators.ErrorMessage & {
    "fail-on-null": boolean;
  };
  "up-duplicate-email": {};
  "local-date": Validators.DoIgnoreEmpty;
  pattern: Validators.DoIgnoreEmpty &
    Validators.ErrorMessage & { pattern: string };
  "person-name-prohibited-characters": Validators.DoIgnoreEmpty &
    Validators.ErrorMessage;
  uri: Validators.DoIgnoreEmpty;
  "username-prohibited-characters": Validators.DoIgnoreEmpty &
    Validators.ErrorMessage;
  options: Validators.Options;
}>;

export declare namespace Validators {
  export type DoIgnoreEmpty = {
    "ignore.empty.value"?: boolean;
  };

  export type ErrorMessage = {
    "error-message"?: string;
  };

  export type Range = {
    min?: `${number}`;
    max?: `${number}`;
  };
  export type Options = {
    options: string[];
  };
}
