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

import { PasswordAuthenticatorProtectionStatus } from './PasswordAuthenticatorProtectionStatus';
import type { PasswordChangeRecoverableError } from '../../error/password/change/PasswordChangeRecoverableError';
import { PasswordChangeRecoverableErrorConverter } from '../../error/password/change/PasswordChangeRecoverableErrorConverter';

/**
 * The object providing some contextual information during password change.
 *
 * @see {@link PasswordChanger.changePassword}
 */
export abstract class PasswordChangeContext {
	/**
	 * The username whose password must be changed.
	 */
	abstract username: string;

	/**
	 * The object describing the password protection status (whether is locked, in
	 * cool-down mode, etc.).
	 */
	abstract authenticatorProtectionStatus: PasswordAuthenticatorProtectionStatus;

	/**
	 * The object describing the latest recoverable error (if any).
	 */
	abstract lastRecoverableError?: PasswordChangeRecoverableError;

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

export class PasswordChangeContextImpl extends PasswordChangeContext {
	authenticatorProtectionStatus: PasswordAuthenticatorProtectionStatus;
	lastRecoverableError?: PasswordChangeRecoverableError;
	username: string;

	private constructor(
		username: string,
		authenticatorProtectionStatus: PasswordAuthenticatorProtectionStatus,
		lastRecoverableError?: PasswordChangeRecoverableError
	) {
		super();
		this.username = username;
		this.authenticatorProtectionStatus = authenticatorProtectionStatus;
		this.lastRecoverableError = lastRecoverableError;
	}

	static fromJson(json: any): PasswordChangeContextImpl {
		const username = json.username;
		const status = PasswordAuthenticatorProtectionStatus.fromJson(
			json.authenticatorProtectionStatus
		);
		const lastRecoverableError =
			json.lastRecoverableError &&
			new PasswordChangeRecoverableErrorConverter(json.lastRecoverableError).convert();
		return new PasswordChangeContextImpl(username, status, lastRecoverableError);
	}
}
