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

import { UserVerificationContext } from './UserVerificationContext';
import type { PasswordUserVerificationError } from '../../error/userVerification/PasswordUserVerificationError';
import { PasswordUserVerificationErrorConverter } from '../../error/userVerification/PasswordUserVerificationErrorConverter';
import { Authenticator } from '../../localData/Authenticator';
import { PasswordAuthenticatorProtectionStatus } from '../password/PasswordAuthenticatorProtectionStatus';

/**
 * The object providing information about the password user verification
 * (i.e. the user credential validation) operation to be done.
 *
 * This object contains the information required to ask the user to authenticate:
 * the authenticator to be used, whether there were previous errors authenticating, etc.
 *
 * @see {@link PasswordUserVerifier.verifyPassword}
 */
export abstract class PasswordUserVerificationContext extends UserVerificationContext {
	/**
	 * The authenticator protection status.
	 */
	abstract authenticatorProtectionStatus: PasswordAuthenticatorProtectionStatus;

	/**
	 * When a recoverable error occurred during the last credential verification, it returns the
	 * object describing the last error.
	 *
	 * If present, this means that an invalid password was provided in the previous invocation to
	 * {@link PasswordUserVerificationHandler.verifyPassword} and thus the protection status is
	 * {@link PasswordProtectionStatusLastAttemptFailed}.
	 */
	abstract lastRecoverableError?: PasswordUserVerificationError;

	/**
	 * Alternate constructor that creates a {@link UserVerificationContext} from a json.
	 *
	 * @param json contains the source for instance creation.
	 * @returns the created {@link PasswordUserVerificationContext} instance.
	 */
	static fromJson(json: any): PasswordUserVerificationContext {
		return PasswordUserVerificationContextImpl.fromJson(json);
	}
}

export class PasswordUserVerificationContextImpl extends PasswordUserVerificationContext {
	authenticator: Authenticator;
	authenticatorProtectionStatus: PasswordAuthenticatorProtectionStatus;
	lastRecoverableError?: PasswordUserVerificationError;

	constructor(
		authenticator: Authenticator,
		authenticatorProtectionStatus: PasswordAuthenticatorProtectionStatus,
		lastRecoverableError?: PasswordUserVerificationError
	) {
		super();
		this.authenticator = authenticator;
		this.authenticatorProtectionStatus = authenticatorProtectionStatus;
		this.lastRecoverableError = lastRecoverableError;
	}

	static fromJson(json: any): PasswordUserVerificationContextImpl {
		const authenticator = Authenticator.fromJson(json.authenticator);
		const status = PasswordAuthenticatorProtectionStatus.fromJson(
			json.authenticatorProtectionStatus
		);
		const lastRecoverableError =
			json.lastRecoverableError &&
			new PasswordUserVerificationErrorConverter(json.lastRecoverableError).convert();
		return new PasswordUserVerificationContextImpl(authenticator, status, lastRecoverableError);
	}
}
