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

import { FidoErrorCodeConverter } from './FidoErrorCodeConverter';
import { SessionProvider } from '../authorization/SessionProvider';
import { FidoErrorCode } from '../error/FidoErrorCode';
import { Server } from '../localData/Server';

/**
 * Represents the error that can occur during communicating with the native plugins.
 *
 * @group Errors
 * @category Common
 */
export class ChannelError {
	/**
	 * The type of the error (e.g. `DeviceProtectionError` or `FidoError`).
	 */
	type: string;

	/**
	 * Provides details about the error that occurred.
	 */
	description: string;

	/**
	 * The server where the error occurred.
	 */
	server?: Server;

	/**
	 * The exception (if any) that caused this error.
	 */
	cause?: string;

	/**
	 * The {@link SessionProvider} that can be used to continue with the operation.
	 */
	sessionProvider?: SessionProvider;

	/**
	 * The FIDO UAF error that occurred.
	 *
	 * @see {@link OperationFidoError}, {@link AuthCloudApiFidoError}, and {@link AuthenticationFidoError}.
	 */
	errorCode?: FidoErrorCode;

	/**
	 * The message is provided by the operating system during fingerprint verification error.
	 */
	message?: string;

	/**
	 * The default constructor.
	 *
	 * @param type The type of the error (e.g. `DeviceProtectionError` or `FidoError`).
	 * @param description The exception (if any) that caused this error.
	 * @param cause The exception (if any) that caused this error.
	 * @param server the server where the error occurred.
	 * @param sessionProvider The {@link SessionProvider} that can be used to continue with the operation.
	 * @param errorCode The FIDO UAF error that occurred.
	 * @param message The message is provided by the operating system during fingerprint verification error.
	 */
	constructor(
		type: string,
		description: string,
		cause?: string,
		server?: Server,
		sessionProvider?: SessionProvider,
		errorCode?: FidoErrorCode,
		message?: string
	) {
		this.type = type;
		this.description = description;
		this.cause = cause;
		this.server = server;
		this.sessionProvider = sessionProvider;
		this.errorCode = errorCode;
		this.message = message;
	}

	/**
	 * Alternate constructor that creates a {@link ChannelError} from a json.
	 *
	 * @param input contains the source for instance creation.
	 * @returns the created instance.
	 */
	static fromJson(input: any): ChannelError {
		let root = input;
		if (input.userInfo?.exception) {
			root = input.userInfo.exception;
		}

		const type = root.type;
		const data = root.data;
		const server = data.server && Server.fromJson(data.server);
		const sessionProvider =
			data.sessionProvider && SessionProvider.fromJson(data.sessionProvider);
		const errorCode = data.errorCode && FidoErrorCodeConverter.fromJson(data.errorCode);

		return new ChannelError(
			type,
			data.description,
			data.cause,
			server,
			sessionProvider,
			errorCode,
			data.message
		);
	}
}
