/**
 * Copyright © 2023-2024 Nevis Security AG. All rights reserved.
 */

import { type AppAttestation } from './AppAttestation';

/**
 * The {@link MobileAuthenticationClient} configuration.
 *
 * The {@link Configuration} is used to build and initialize the {@link MobileAuthenticationClient}.
 *
 * @group Essentials
 * @see {@link MobileAuthenticationClientInitializer.configuration}
 */
export abstract class Configuration {
	/**
	 * The default base URL for the HTTP endpoints the SDK must interact with.
	 *
	 * @returns the base URL.
	 */
	abstract getBaseUrl(): string;

	/**
	 * The registration request URL path used to send the FIDO UAF registration GetUafRequest.
	 *
	 * The registration request URL is the result of combining the `baseUrl` and this path.
	 *
	 * @returns the registration request path.
	 */
	abstract getRegistrationRequestPath(): string;

	/**
	 * The registration response URL path used to send the final FIDO UAF registration response.
	 *
	 * The registration response URL is the result of combining the `baseUrl` and this path.
	 *
	 * @returns registration response path.
	 */
	abstract getRegistrationResponsePath(): string;

	/**
	 * The authentication request URL path used to send the FIDO UAF authentication GetUafRequest.
	 *
	 * The authentication request URL is the result of combining the `baseUrl` and this path.
	 *
	 * @returns the authentication request path.
	 */
	abstract getAuthenticationRequestPath(): string;

	/***
	 * The authentication response URL path used to send the final FIDO UAF authentication response.
	 *
	 * The authentication response URL is the result of combining the `baseUrl` and this path.
	 *
	 * @returns the authentication response path.
	 */
	abstract getAuthenticationResponsePath(): string;

	/**
	 * Returns the URL path used to obtain the FIDO UAF deregistration request.
	 *
	 * The deregistration request URL is the result of combining the `baseUrl` and this path.
	 *
	 * @returns the deregistration request path.
	 */
	abstract getDeregistrationRequestPath(): string;

	/**
	 * The dispatch target resource URL path.
	 *
	 * The dispatch target resource URL is the result of combining the `baseUrl` and this path.
	 *
	 * @returns the dispatch target resource path.
	 */
	abstract getDispatchTargetResourcePath(): string;

	/**
	 * The device managing resource URL path.
	 *
	 * The device managing resource URL is the result of combining the `baseUrl` and this path.
	 *
	 * @returns the device managing resource path.
	 */
	abstract getDeviceResourcePath(): string;

	/**
	 * Time interval for network calls in seconds. Any network request that takes longer than this
	 * value, will result in a timeout.
	 *
	 * @returns the time interval for network requests.
	 */
	abstract getNetworkTimeoutInSeconds(): number;

	/**
	 * The user interaction timeout in seconds. This is the maximum time that the SDK will wait to
	 * obtain a result when {@link AccountSelector.selectAccount}, {@link AuthenticatorSelector.selectAuthenticator},
	 * {@link PinUserVerifier.verifyPin}, {@link PasswordUserVerifier.verifyPassword}, {@link FingerprintUserVerifier.verifyFingerprint},
	 * or {@link BiometricUserVerifier.verifyBiometric} are invoked (i.e. the maximum time to wait
	 * before any of the methods of the provided consumer in any of those methods is invoked).
	 *
	 * If the timeout occurs, then the operation delegate failure method ({@link Registration.onError},
	 * {@link OutOfBandRegistration.onError}, {@link Authentication.onError}
	 * or {@link OutOfBandAuthentication.onError}, depending on the operation being executed) will
	 * be invoked. The provided exception will contain an {@link FidoErrorCodeType.UserNotResponsive}
	 * error code.
	 *
	 * @returns the timeout for user interaction.
	 */
	abstract getUserInteractionTimeoutInSeconds(): number;

	/**
	 * The configuration related to application attestation.
	 *
	 * If the backend (nevisFIDO) requires application attestation through its policy, you must provide
	 * this information, so that the mobile SDK can send the required application attestation information.
	 *
	 * This information is not needed if your backend does not require application attestation.
	 */
	abstract getAppAttestation(): AppAttestation | undefined;

	/**
	 * Returns a new {@link ConfigurationBuilder}.
	 *
	 * @returns a new {@link ConfigurationBuilder}.
	 */
	static builder(): ConfigurationBuilder {
		return new ConfigurationBuilderImpl();
	}

	/**
	 * Returns a new {@link ConfigurationAuthCloudBuilder}. This is a simpler version of
	 * {@link ConfigurationBuilder} that can only be used when your application interacts with
	 * the Nevis Authentication Cloud.
	 *
	 * If you are fine with the default network parameters of the builder, you just need to provide
	 * the hostname of your application to build a {@link Configuration} object:
	 *
	 * @example
	 * ```ts
	 * const configuration = Configuration.authCloudBuilder()
	 *     .hostname(hostname)
	 *     .build();
	 * ```
	 *
	 * @returns a new {@link ConfigurationAuthCloudBuilder}.
	 */
	static authCloudBuilder(): ConfigurationAuthCloudBuilder {
		return new ConfigurationAuthCloudBuilderImpl(Configuration.builder());
	}

	/**
	 * Returns a new {@link ConfigurationAdmin4PatternBuilder}. This is a simpler version of
	 * {@link ConfigurationBuilder} that can only be used when your application interacts with
	 * the Nevis Identity Suite configured with default Nevis Admin 4 pattern.
	 *
	 * If you are fine with the default network parameters of the builder, you just need to provide
	 * the hostname of your application to build a {@link Configuration} object:
	 *
	 * @example
	 * ```ts
	 * const configuration = Configuration.admin4PatternBuilder()
	 *     .hostname(hostname)
	 *     .build();
	 * ```
	 *
	 * @returns a new {@link ConfigurationAdmin4PatternBuilder}.
	 */
	static admin4PatternBuilder(): ConfigurationAdmin4PatternBuilder {
		return new ConfigurationAdmin4PatternBuilderImpl(Configuration.builder());
	}
}

export const AuthCloudConstants = {
	RegistrationRequestPath: '/uaf/1.1/request/registration/',
	RegistrationResponsePath: '/uaf/1.1/registration/',
	AuthenticationRequestPath: '/uaf/1.1/request/authentication/',
	AuthenticationResponsePath: '/uaf/1.1/authentication/',
	DeregistrationRequestPath: '/uaf/1.1/request/deregistration/',
	DispatchTargetResourcePath: '/token/dispatch/targets/',
	DeviceResourcePath: '/devices/',
};

export const Admin4PatternConstants = {
	RegistrationRequestPath: `/nevisfido${AuthCloudConstants.RegistrationRequestPath}`,
	RegistrationResponsePath: `/nevisfido${AuthCloudConstants.RegistrationResponsePath}`,
	AuthenticationRequestPath: '/auth/fidouaf',
	AuthenticationResponsePath: '/auth/fidouaf/authenticationresponse/',
	DeregistrationRequestPath: `/nevisfido${AuthCloudConstants.DeregistrationRequestPath}`,
	DispatchTargetResourcePath: `/nevisfido${AuthCloudConstants.DispatchTargetResourcePath}`,
	DeviceResourcePath: `/nevisfido${AuthCloudConstants.DeviceResourcePath}`,
};

export const ConfigurationConstants = {
	NetworkTimeoutInSeconds: 60,
	UserInteractionTimeoutInSeconds: 240,
};

class ConfigurationImpl extends Configuration {
	baseUrl: string;
	registrationRequestPath: string;
	registrationResponsePath: string;
	authenticationRequestPath: string;
	authenticationResponsePath: string;
	deregistrationRequestPath: string;
	dispatchTargetResourcePath: string;
	deviceResourcePath: string;
	networkTimeoutInSeconds: number;
	userInteractionTimeoutInSeconds: number;
	appAttestation?: AppAttestation;

	constructor(
		baseUrl: string,
		registrationRequestPath: string,
		registrationResponsePath: string,
		authenticationRequestPath: string,
		authenticationResponsePath: string,
		deregistrationRequestPath: string,
		dispatchTargetResourcePath: string,
		deviceResourcePath: string,
		networkTimeoutInSeconds: number,
		userInteractionTimeoutInSeconds: number,
		appAttestation?: AppAttestation
	) {
		super();
		this.baseUrl = baseUrl;
		this.registrationRequestPath = registrationRequestPath;
		this.registrationResponsePath = registrationResponsePath;
		this.authenticationRequestPath = authenticationRequestPath;
		this.authenticationResponsePath = authenticationResponsePath;
		this.deregistrationRequestPath = deregistrationRequestPath;
		this.dispatchTargetResourcePath = dispatchTargetResourcePath;
		this.deviceResourcePath = deviceResourcePath;
		this.networkTimeoutInSeconds = networkTimeoutInSeconds;
		this.userInteractionTimeoutInSeconds = userInteractionTimeoutInSeconds;
		this.appAttestation = appAttestation;
	}

	getBaseUrl(): string {
		return this.baseUrl;
	}

	getRegistrationRequestPath(): string {
		return this.registrationRequestPath;
	}

	getRegistrationResponsePath(): string {
		return this.registrationResponsePath;
	}

	getAuthenticationRequestPath(): string {
		return this.authenticationRequestPath;
	}

	getAuthenticationResponsePath(): string {
		return this.authenticationResponsePath;
	}

	getDeregistrationRequestPath(): string {
		return this.deregistrationRequestPath;
	}

	getDispatchTargetResourcePath(): string {
		return this.dispatchTargetResourcePath;
	}

	getDeviceResourcePath(): string {
		return this.deviceResourcePath;
	}

	getNetworkTimeoutInSeconds(): number {
		return this.networkTimeoutInSeconds;
	}

	getUserInteractionTimeoutInSeconds(): number {
		return this.userInteractionTimeoutInSeconds;
	}

	getAppAttestation(): AppAttestation | undefined {
		return this.appAttestation;
	}
}

/**
 * A builder for {@link Configuration}.
 *
 * For the default values please see the {@link https://docs.nevis.net/mobilesdk/guide/configuration#authentication-cloud-backend | native}
 * API references.
 *
 * @group Essentials
 */
export abstract class ConfigurationBuilder {
	/**
	 * Sets the base URL.
	 *
	 * > [!IMPORTANT]
	 * > Providing the base URL is required.
	 *
	 * @param baseUrl the base URL.
	 * @returns a builder.
	 */
	abstract baseUrl(baseUrl: string): ConfigurationBuilder;

	/**
	 * Sets the registration request URL path.
	 *
	 * For the default value please see the {@link https://docs.nevis.net/mobilesdk/guide/configuration#authentication-cloud-backend | native}
	 * API references.
	 *
	 * @param registrationRequestPath the registration request path URL.
	 * @returns a builder.
	 */
	abstract registrationRequestPath(registrationRequestPath: string): ConfigurationBuilder;

	/**
	 * Sets the registration response path URL.
	 *
	 * For the default value please see the {@link https://docs.nevis.net/mobilesdk/guide/configuration#authentication-cloud-backend | native}
	 * API references.
	 *
	 * @param registrationResponsePath the registration response path URL.
	 * @returns a builder.
	 */
	abstract registrationResponsePath(registrationResponsePath: string): ConfigurationBuilder;

	/**
	 * Sets the authentication request path URL.
	 *
	 * For the default value please see the {@link https://docs.nevis.net/mobilesdk/guide/configuration#authentication-cloud-backend | native}
	 * API references.
	 *
	 * @param authenticationRequestPath the authentication request path URL.
	 * @returns a builder.
	 */
	abstract authenticationRequestPath(authenticationRequestPath: string): ConfigurationBuilder;

	/**
	 * Sets the authentication response path URL.
	 *
	 * For the default value please see the {@link https://docs.nevis.net/mobilesdk/guide/configuration#authentication-cloud-backend | native}
	 * API references.
	 *
	 * @param authenticationResponsePath the authentication response path URL.
	 * @returns a builder.
	 */
	abstract authenticationResponsePath(authenticationResponsePath: string): ConfigurationBuilder;

	/**
	 * Sets the deregistration path URL.
	 *
	 * For the default value please see the {@link https://docs.nevis.net/mobilesdk/guide/configuration#authentication-cloud-backend | native}
	 * API references.
	 *
	 * @param deregistrationRequestPath the deregistration path URL.
	 * @returns a builder.
	 */
	abstract deregistrationRequestPath(deregistrationRequestPath: string): ConfigurationBuilder;

	/**
	 * Sets the dispatch target resource path URL.
	 *
	 * For the default value please see the {@link https://docs.nevis.net/mobilesdk/guide/configuration#authentication-cloud-backend | native}
	 * API references.
	 *
	 * @param dispatchTargetResourcePath the dispatch target resource path URL.
	 * @returns a builder.
	 */
	abstract dispatchTargetResourcePath(dispatchTargetResourcePath: string): ConfigurationBuilder;

	/**
	 * The device managing resource URL path.
	 *
	 * For the default value please see the {@link https://docs.nevis.net/mobilesdk/guide/configuration#authentication-cloud-backend | native}
	 * API references.
	 *
	 * @param deviceResourcePath the device managing resource path URL.
	 * @returns a builder.
	 */
	abstract deviceResourcePath(deviceResourcePath: string): ConfigurationBuilder;

	/**
	 * Sets the time interval for network timeouts in seconds.
	 *
	 * For the default value please see the {@link https://docs.nevis.net/mobilesdk/guide/configuration#authentication-cloud-backend | native}
	 * API references
	 *
	 * @param networkTimeoutInSeconds the network timeout.
	 * @returns a builder.
	 */
	abstract networkTimeoutInSeconds(networkTimeoutInSeconds: number): ConfigurationBuilder;

	/**
	 * Sets the maximum time that the SDK will wait during user interaction to receive the
	 * user input.
	 *
	 * For the default value please see the {@link https://docs.nevis.net/mobilesdk/guide/configuration#authentication-cloud-backend | native}
	 * API references.
	 *
	 * @param userInteractionTimeoutInSeconds the user interaction timeout in seconds.
	 * @returns a builder.
	 */
	abstract userInteractionTimeoutInSeconds(
		userInteractionTimeoutInSeconds: number
	): ConfigurationBuilder;

	/**
	 * Sets the application attestation configuration.
	 *
	 * @param appAttestation the application attestation configuration.
	 * @returns a builder.
	 */
	abstract appAttestation(appAttestation: AppAttestation): ConfigurationBuilder;

	/**
	 * Creates a {@link Configuration}.
	 *
	 * @returns a {@link Configuration}.
	 */
	abstract build(): Configuration;
}

class ConfigurationBuilderImpl extends ConfigurationBuilder {
	_baseUrl?: string;
	_registrationRequestPath: string;
	_registrationResponsePath: string;
	_authenticationRequestPath: string;
	_authenticationResponsePath: string;
	_deregistrationRequestPath: string;
	_dispatchTargetResourcePath: string;
	_deviceResourcePath: string;
	_networkTimeoutInSeconds: number;
	_userInteractionTimeoutInSeconds: number;
	_appAttestation?: AppAttestation;

	constructor() {
		super();
		this._registrationRequestPath = AuthCloudConstants.RegistrationRequestPath;
		this._registrationResponsePath = AuthCloudConstants.RegistrationResponsePath;
		this._authenticationRequestPath = AuthCloudConstants.AuthenticationRequestPath;
		this._authenticationResponsePath = AuthCloudConstants.AuthenticationResponsePath;
		this._deregistrationRequestPath = AuthCloudConstants.DeregistrationRequestPath;
		this._dispatchTargetResourcePath = AuthCloudConstants.DispatchTargetResourcePath;
		this._deviceResourcePath = AuthCloudConstants.DeviceResourcePath;
		this._networkTimeoutInSeconds = ConfigurationConstants.NetworkTimeoutInSeconds;
		this._userInteractionTimeoutInSeconds =
			ConfigurationConstants.UserInteractionTimeoutInSeconds;
	}

	baseUrl(baseUrl: string): ConfigurationBuilder {
		this._baseUrl = baseUrl;
		return this;
	}

	registrationRequestPath(registrationRequestPath: string): ConfigurationBuilder {
		this._registrationRequestPath = registrationRequestPath;
		return this;
	}

	registrationResponsePath(registrationResponsePath: string): ConfigurationBuilder {
		this._registrationResponsePath = registrationResponsePath;
		return this;
	}

	authenticationRequestPath(authenticationRequestPath: string): ConfigurationBuilder {
		this._authenticationRequestPath = authenticationRequestPath;
		return this;
	}

	authenticationResponsePath(authenticationResponsePath: string): ConfigurationBuilder {
		this._authenticationResponsePath = authenticationResponsePath;
		return this;
	}

	deregistrationRequestPath(deregistrationRequestPath: string): ConfigurationBuilder {
		this._deregistrationRequestPath = deregistrationRequestPath;
		return this;
	}

	dispatchTargetResourcePath(dispatchTargetResourcePath: string): ConfigurationBuilder {
		this._dispatchTargetResourcePath = dispatchTargetResourcePath;
		return this;
	}

	deviceResourcePath(deviceResourcePath: string): ConfigurationBuilder {
		this._deviceResourcePath = deviceResourcePath;
		return this;
	}

	networkTimeoutInSeconds(networkTimeoutInSeconds: number): ConfigurationBuilder {
		this._networkTimeoutInSeconds = networkTimeoutInSeconds;
		return this;
	}

	userInteractionTimeoutInSeconds(userInteractionTimeoutInSeconds: number): ConfigurationBuilder {
		this._userInteractionTimeoutInSeconds = userInteractionTimeoutInSeconds;
		return this;
	}

	appAttestation(appAttestation: AppAttestation): ConfigurationBuilder {
		this._appAttestation = appAttestation;
		return this;
	}

	build(): Configuration {
		if (this._baseUrl === undefined) {
			throw new Error(`Providing the base URL is required!`);
		}

		return new ConfigurationImpl(
			this._baseUrl,
			this._registrationRequestPath,
			this._registrationResponsePath,
			this._authenticationRequestPath,
			this._authenticationResponsePath,
			this._deregistrationRequestPath,
			this._dispatchTargetResourcePath,
			this._deviceResourcePath,
			this._networkTimeoutInSeconds,
			this._userInteractionTimeoutInSeconds,
			this._appAttestation
		);
	}
}

/**
 * A simplified builder that can be used to configure an SDK when your application works with the
 * Nevis Authentication Cloud.
 *
 * With this builder, you do not need to provide the relative paths of the endpoints for each operation.
 *
 * For the default values please see the {@link https://docs.nevis.net/mobilesdk/guide/configuration#authentication-cloud-backend | native}
 * API references.
 *
 * @group Essentials
 */
export abstract class ConfigurationAuthCloudBuilder {
	/**
	 * Sets the hostname of your Nevis Authentication Cloud.
	 *
	 * > [!IMPORTANT]
	 * > Providing the hostname is required.
	 *
	 * @param hostname the hostname of your Nevis Authentication Cloud.
	 * @returns a builder.
	 */
	abstract hostname(hostname: string): ConfigurationAuthCloudBuilder;

	/**
	 * Sets the time interval for network timeouts in seconds.
	 *
	 * For the default value please see the {@link https://docs.nevis.net/mobilesdk/guide/configuration#authentication-cloud-backend | native}
	 * API references
	 *
	 * @param networkTimeoutInSeconds the network timeout.
	 * @returns a builder.
	 */
	abstract networkTimeoutInSeconds(
		networkTimeoutInSeconds: number
	): ConfigurationAuthCloudBuilder;

	/**
	 * Sets the maximum time that the SDK will wait during user interaction to receive the user input.
	 *
	 * For the default value please see the {@link https://docs.nevis.net/mobilesdk/guide/configuration#authentication-cloud-backend | native}
	 * API references
	 *
	 * @param userInteractionTimeoutInSeconds the user interaction timeout in seconds.
	 * @returns a builder.
	 */
	abstract userInteractionTimeoutInSeconds(
		userInteractionTimeoutInSeconds: number
	): ConfigurationAuthCloudBuilder;

	/**
	 * Sets the application attestation configuration.
	 *
	 * @param appAttestation the application attestation configuration.
	 * @returns a builder.
	 */
	abstract appAttestation(appAttestation: AppAttestation): ConfigurationAuthCloudBuilder;

	/**
	 * Creates a {@link Configuration}.
	 *
	 * @returns a {@link Configuration}.
	 */
	abstract build(): Configuration;
}

class ConfigurationAuthCloudBuilderImpl implements ConfigurationAuthCloudBuilder {
	_builder: ConfigurationBuilder;
	_hostname?: string;

	constructor(builder: ConfigurationBuilder) {
		this._builder = builder;
	}

	hostname(hostname: string): ConfigurationAuthCloudBuilder {
		this._hostname = hostname;
		return this;
	}

	networkTimeoutInSeconds(networkTimeoutInSeconds: number): ConfigurationAuthCloudBuilder {
		this._builder.networkTimeoutInSeconds(networkTimeoutInSeconds);
		return this;
	}

	userInteractionTimeoutInSeconds(
		userInteractionTimeoutInSeconds: number
	): ConfigurationAuthCloudBuilder {
		this._builder.userInteractionTimeoutInSeconds(userInteractionTimeoutInSeconds);
		return this;
	}

	appAttestation(appAttestation: AppAttestation): ConfigurationAuthCloudBuilder {
		this._builder.appAttestation(appAttestation);
		return this;
	}

	build(): Configuration {
		if (this._hostname === undefined) {
			throw new Error(`Providing the hostname is required!`);
		}
		const baseUrl = `https://${this._hostname}/_app`;
		return this._builder.baseUrl(baseUrl).build();
	}
}

/**
 * A simplified builder that can be used to configure an SDK when your application works with the
 * Nevis Identity Suite configured with default Nevis Admin 4 pattern.
 *
 * The builder works with the following relative endpoint paths:
 *  - Registration request: `/nevisfido/uaf/1.1/request/registration/`
 *  - Registration response: `/nevisfido/uaf/1.1/registration/`
 *  - Authentication request: `/auth/fidouaf`
 *  - Authentication response: `/auth/fidouaf/authenticationresponse/`
 *  - Deregistration request: `/uaf/1.1/request/deregistration/`
 *  - Dispatch target resource: `/nevisfido/token/dispatch/targets/`
 *  - Device resource: `/nevisfido/devices/`
 *
 * @group Essentials
 */
export abstract class ConfigurationAdmin4PatternBuilder {
	/**
	 * Sets the hostname of your Nevis Identity Suite.
	 *
	 * > [!IMPORTANT]
	 * > Providing the hostname is required.
	 *
	 * @param hostname the of your Nevis Identity Suite.
	 * @returns a builder.
	 */
	abstract hostname(hostname: string): ConfigurationAdmin4PatternBuilder;

	/**
	 * Sets the time interval for network timeouts in seconds.
	 *
	 * For the default value please see the {@link https://docs.nevis.net/mobilesdk/guide/configuration#identity-suite-backends | native}
	 * API references
	 *
	 * @param networkTimeoutInSeconds the network timeout.
	 * @returns a builder.
	 */
	abstract networkTimeoutInSeconds(
		networkTimeoutInSeconds: number
	): ConfigurationAdmin4PatternBuilder;

	/**
	 * Sets the maximum time that the SDK will wait during user interaction to receive the user input.
	 *
	 * For the default value please see the {@link https://docs.nevis.net/mobilesdk/guide/configuration#identity-suite-backends | native}
	 * API references
	 *
	 * @param userInteractionTimeoutInSeconds the user interaction timeout in seconds.
	 * @returns a builder.
	 */
	abstract userInteractionTimeoutInSeconds(
		userInteractionTimeoutInSeconds: number
	): ConfigurationAdmin4PatternBuilder;

	/**
	 * Sets the application attestation configuration.
	 *
	 * @param appAttestation the application attestation configuration.
	 * @returns a builder.
	 */
	abstract appAttestation(appAttestation: AppAttestation): ConfigurationAdmin4PatternBuilder;

	/**
	 * Creates a {@link Configuration}.
	 *
	 * @returns a {@link Configuration}.
	 */
	abstract build(): Configuration;
}

class ConfigurationAdmin4PatternBuilderImpl implements ConfigurationAdmin4PatternBuilder {
	_builder: ConfigurationBuilder;
	_hostname?: string;

	constructor(builder: ConfigurationBuilder) {
		this._builder = builder;
	}

	hostname(hostname: string): ConfigurationAdmin4PatternBuilder {
		this._hostname = hostname;
		return this;
	}

	networkTimeoutInSeconds(networkTimeoutInSeconds: number): ConfigurationAdmin4PatternBuilder {
		this._builder.networkTimeoutInSeconds(networkTimeoutInSeconds);
		return this;
	}

	userInteractionTimeoutInSeconds(
		userInteractionTimeoutInSeconds: number
	): ConfigurationAdmin4PatternBuilder {
		this._builder.userInteractionTimeoutInSeconds(userInteractionTimeoutInSeconds);
		return this;
	}

	appAttestation(appAttestation: AppAttestation): ConfigurationAdmin4PatternBuilder {
		this._builder.appAttestation(appAttestation);
		return this;
	}

	build(): Configuration {
		if (this._hostname === undefined) {
			throw new Error(`Providing the hostname is required!`);
		}
		const baseUrl = `https://${this._hostname}`;
		return this._builder
			.baseUrl(baseUrl)
			.registrationRequestPath(Admin4PatternConstants.RegistrationRequestPath)
			.registrationResponsePath(Admin4PatternConstants.RegistrationResponsePath)
			.authenticationRequestPath(Admin4PatternConstants.AuthenticationRequestPath)
			.authenticationResponsePath(Admin4PatternConstants.AuthenticationResponsePath)
			.deregistrationRequestPath(Admin4PatternConstants.DeregistrationRequestPath)
			.dispatchTargetResourcePath(Admin4PatternConstants.DispatchTargetResourcePath)
			.deviceResourcePath(Admin4PatternConstants.DeviceResourcePath)
			.build();
	}
}
