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

enum PasswordAuthenticatorProtectionStatusType {
	Unlocked,
	LastAttemptFailed,
	LockedOut,
}

/**
 * The object describing the password authenticator protection status.
 *
 * It provides information regarding how many retries are available for the end user before locking
 * the authenticator.
 */
export abstract class PasswordAuthenticatorProtectionStatus {
	/**
	 * Alternate constructor that creates a {@link PasswordAuthenticatorProtectionStatus} from a json.
	 *
	 * @param json contains the source for instance creation.
	 * @returns a {@link PasswordAuthenticatorProtectionStatus} instance.
	 */
	static fromJson(json: any): PasswordAuthenticatorProtectionStatus {
		const subtype =
			PasswordAuthenticatorProtectionStatusType[
				json.type as keyof typeof PasswordAuthenticatorProtectionStatusType
			];
		switch (subtype) {
			case PasswordAuthenticatorProtectionStatusType.Unlocked:
				return PasswordProtectionStatusUnlocked.fromJson();
			case PasswordAuthenticatorProtectionStatusType.LastAttemptFailed:
				return PasswordProtectionStatusLastAttemptFailed.fromJson(json.data);
			case PasswordAuthenticatorProtectionStatusType.LockedOut:
				return PasswordProtectionStatusLockedOut.fromJson();
			default:
				throw new Error(`Unknown password authenticator protection status (${json.type}).`);
		}
	}
}

/**
 * The authenticator is unlocked and can be used.
 */
export abstract class PasswordProtectionStatusUnlocked extends PasswordAuthenticatorProtectionStatus {
	/**
	 * Alternate constructor that creates a {@link PasswordProtectionStatusUnlocked} from a json.
	 *
	 * @returns the created {@link PasswordProtectionStatusUnlocked} instance.
	 */
	static fromJson(): PasswordProtectionStatusUnlocked {
		return PasswordProtectionStatusUnlockedImpl.fromJson();
	}
}

export class PasswordProtectionStatusUnlockedImpl extends PasswordProtectionStatusUnlocked {
	static fromJson(): PasswordProtectionStatusUnlockedImpl {
		return new PasswordProtectionStatusUnlockedImpl();
	}
}

/**
 * An invalid password was provided previously.
 *
 * This may imply that an attacker is trying to use the password authenticator.
 */
export abstract class PasswordProtectionStatusLastAttemptFailed extends PasswordAuthenticatorProtectionStatus {
	/**
	 * The number of remaining retries available.
	 */
	abstract remainingRetries: number;

	/**
	 * The time that must be passed before the user can try to provide credentials again.
	 * If the value is 0, it means that no cool-down is required, and that a new password can
	 * be provided immediately.
	 */
	abstract coolDownTimeInSec: number;

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

export class PasswordProtectionStatusLastAttemptFailedImpl extends PasswordProtectionStatusLastAttemptFailed {
	remainingRetries: number;
	coolDownTimeInSec: number;

	constructor(remainingRetries: number, coolDownTimeInSec: number) {
		super();
		this.remainingRetries = remainingRetries;
		this.coolDownTimeInSec = coolDownTimeInSec;
	}

	static fromJson(json: any): PasswordProtectionStatusLastAttemptFailedImpl {
		return new PasswordProtectionStatusLastAttemptFailedImpl(
			json.remainingRetries,
			json.coolDownTimeInSec
		);
	}
}

/**
 * The authenticator is locked and cannot be used.
 */
export abstract class PasswordProtectionStatusLockedOut extends PasswordAuthenticatorProtectionStatus {
	/**
	 * Alternate constructor that creates a {@link PasswordProtectionStatusLockedOut} from a json.
	 *
	 * @returns the created {@link PasswordProtectionStatusLockedOut} instance.
	 */
	static fromJson(): PasswordProtectionStatusLockedOut {
		return PasswordProtectionStatusLockedOutImpl.fromJson();
	}
}

export class PasswordProtectionStatusLockedOutImpl extends PasswordProtectionStatusLockedOut {
	static fromJson(): PasswordProtectionStatusLockedOutImpl {
		return new PasswordProtectionStatusLockedOutImpl();
	}
}
