const require_rolldown_runtime = require('../../../../../../_virtual/rolldown_runtime.js');
const require_decorateMetadata = require('../../../../../../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorateMetadata.js');
const require_decorate = require('../../../../../../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorate.js');
const require_DidCommAckMessage = require('../../../messages/common/DidCommAckMessage.js');
require('../../../messages/index.js');
const require_DidCommOutboundMessageContext = require('../../../models/DidCommOutboundMessageContext.js');
require('../../../models/index.js');
const require_DidCommDidRotateProblemReportMessage = require('../messages/DidCommDidRotateProblemReportMessage.js');
const require_DidCommDidRotateMessage = require('../messages/DidCommDidRotateMessage.js');
const require_DidCommDidRotateAckMessage = require('../messages/DidCommDidRotateAckMessage.js');
const require_DidCommHangupMessage = require('../messages/DidCommHangupMessage.js');
require('../messages/index.js');
const require_decorateParam = require('../../../../../../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorateParam.js');
const require_helpers = require('./helpers.js');
const require_DidCommConnectionEvents = require('../DidCommConnectionEvents.js');
const require_DidCommConnectionService = require('./DidCommConnectionService.js');
const require_DidCommConnectionMetadataTypes = require('../repository/DidCommConnectionMetadataTypes.js');
const require_helpers$1 = require('../../routing/services/helpers.js');
const require_DidCommConnectionsModuleConfig = require('../DidCommConnectionsModuleConfig.js');
let __credo_ts_core = require("@credo-ts/core");
__credo_ts_core = require_rolldown_runtime.__toESM(__credo_ts_core);

//#region ../didcomm/src/modules/connections/services/DidCommDidRotateService.ts
var _ref, _ref2;
let DidCommDidRotateService = class DidCommDidRotateService$1 {
	constructor(didResolverService, logger, eventEmitter) {
		this.didResolverService = didResolverService;
		this.logger = logger;
		this.eventEmitter = eventEmitter;
	}
	async createRotate(agentContext, options) {
		const { connection, toDid, routing } = options;
		const config = agentContext.resolve(require_DidCommConnectionsModuleConfig.DidCommConnectionsModuleConfig);
		const dids = agentContext.resolve(__credo_ts_core.DidsApi);
		if (connection.metadata.get(require_DidCommConnectionMetadataTypes.DidCommConnectionMetadataKeys.DidRotate)) throw new __credo_ts_core.CredoError(`There is already an existing opened did rotation flow for connection id ${connection.id}`);
		let resolvedDid;
		let mediatorId;
		if (toDid) {
			resolvedDid = await dids.resolveCreatedDidDocumentWithKeys(toDid);
			mediatorId = (await require_helpers$1.getMediationRecordForDidDocument(agentContext, resolvedDid.didDocument))?.id;
		} else {
			if (!routing) throw new __credo_ts_core.CredoError("Routing configuration must be defined when rotating to a new peer did");
			resolvedDid = await require_helpers.createPeerDidFromServices(agentContext, require_helpers.routingToServices(routing), config.peerNumAlgoForDidRotation);
			mediatorId = routing.mediatorId;
		}
		const message = new require_DidCommDidRotateMessage.DidCommDidRotateMessage({ toDid: resolvedDid.didDocument.id });
		connection.metadata.set(require_DidCommConnectionMetadataTypes.DidCommConnectionMetadataKeys.DidRotate, {
			threadId: message.threadId,
			did: resolvedDid.didDocument.id,
			mediatorId
		});
		await agentContext.resolve(require_DidCommConnectionService.DidCommConnectionService).update(agentContext, connection);
		return message;
	}
	async createHangup(agentContext, options) {
		const { connection } = options;
		const message = new require_DidCommHangupMessage.DidCommHangupMessage({});
		if (connection.did) connection.previousDids = [...connection.previousDids, connection.did];
		connection.did = void 0;
		await agentContext.dependencyManager.resolve(require_DidCommConnectionService.DidCommConnectionService).update(agentContext, connection);
		return message;
	}
	/**
	* Process a Hangup message and mark connection's theirDid as undefined so it is effectively terminated.
	* Connection Record itself is not deleted (TODO: config parameter to automatically do so)
	*
	* Its previous did will be stored in record in order to be able to recognize any message received
	* afterwards.
	*
	* @param messageContext
	*/
	async processHangup(messageContext) {
		const connection = messageContext.assertReadyConnection();
		const { agentContext } = messageContext;
		if (connection.theirDid) connection.previousTheirDids = [...connection.previousTheirDids, connection.theirDid];
		const previousTheirDid = connection.theirDid;
		connection.theirDid = void 0;
		await agentContext.dependencyManager.resolve(require_DidCommConnectionService.DidCommConnectionService).update(agentContext, connection);
		this.emitDidRotatedEvent(agentContext, connection, { previousTheirDid });
	}
	/**
	* Process an incoming DID Rotate message and update connection if success. Any acknowledge
	* or problem report will be sent to the prior DID, so the created context will take former
	* connection record data
	*
	* @param paramInboundDidCommMessageContext
	* @param connection
	* @returns
	*/
	async processRotate(messageContext) {
		const connection = messageContext.assertReadyConnection();
		const { message, agentContext } = messageContext;
		const newDid = message.toDid;
		if ((0, __credo_ts_core.isValidPeerDid)(newDid) && (0, __credo_ts_core.getNumAlgoFromPeerDid)(newDid) === __credo_ts_core.PeerDidNumAlgo.GenesisDoc) {
			this.logger.error(`Unable to resolve DID Document for '${newDid}`);
			return new require_DidCommOutboundMessageContext.DidCommOutboundMessageContext(new require_DidCommDidRotateProblemReportMessage.DidCommDidRotateProblemReportMessage({ description: {
				en: "DID Method Unsupported",
				code: "e.did.method_unsupported"
			} }), {
				agentContext,
				connection
			});
		}
		const didDocument = (await this.didResolverService.resolve(agentContext, newDid)).didDocument;
		if (!didDocument) {
			this.logger.error(`Unable to resolve DID Document for '${newDid}`);
			return new require_DidCommOutboundMessageContext.DidCommOutboundMessageContext(new require_DidCommDidRotateProblemReportMessage.DidCommDidRotateProblemReportMessage({ description: {
				en: "DID Unresolvable",
				code: "e.did.unresolvable"
			} }), {
				agentContext,
				connection
			});
		}
		if (!didDocument.didCommServices) return new require_DidCommOutboundMessageContext.DidCommOutboundMessageContext(new require_DidCommDidRotateProblemReportMessage.DidCommDidRotateProblemReportMessage({ description: {
			en: "DID Document Unsupported",
			code: "e.did.doc_unsupported"
		} }), {
			agentContext,
			connection
		});
		const outboundMessageContext = new require_DidCommOutboundMessageContext.DidCommOutboundMessageContext(new require_DidCommDidRotateAckMessage.DidCommDidRotateAckMessage({
			threadId: message.threadId,
			status: require_DidCommAckMessage.AckStatus.OK
		}), {
			agentContext,
			connection: connection.clone()
		});
		await agentContext.dependencyManager.resolve(__credo_ts_core.DidRepository).storeReceivedDid(agentContext, {
			did: didDocument.id,
			didDocument,
			tags: { alternativeDids: (0, __credo_ts_core.isValidPeerDid)(didDocument.id) ? (0, __credo_ts_core.getAlternativeDidsForPeerDid)(didDocument.id) : void 0 }
		});
		if (connection.theirDid) connection.previousTheirDids = [...connection.previousTheirDids, connection.theirDid];
		const previousTheirDid = connection.theirDid;
		connection.theirDid = newDid;
		await agentContext.dependencyManager.resolve(require_DidCommConnectionService.DidCommConnectionService).update(agentContext, connection);
		this.emitDidRotatedEvent(agentContext, connection, { previousTheirDid });
		return outboundMessageContext;
	}
	async processRotateAck(inboundMessage) {
		const { agentContext, message } = inboundMessage;
		const connection = inboundMessage.assertReadyConnection();
		const didRotateMetadata = connection.metadata.get(require_DidCommConnectionMetadataTypes.DidCommConnectionMetadataKeys.DidRotate);
		if (!didRotateMetadata) throw new __credo_ts_core.CredoError(`No did rotation data found for connection with id '${connection.id}'`);
		if (didRotateMetadata.threadId !== message.threadId) throw new __credo_ts_core.CredoError(`Existing did rotation flow thread id '${didRotateMetadata.threadId} does not match incoming message'`);
		if (connection.did) connection.previousDids = [...connection.previousDids, connection.did];
		const previousOurDid = connection.did;
		connection.did = didRotateMetadata.did;
		connection.mediatorId = didRotateMetadata.mediatorId;
		connection.metadata.delete(require_DidCommConnectionMetadataTypes.DidCommConnectionMetadataKeys.DidRotate);
		await agentContext.dependencyManager.resolve(require_DidCommConnectionService.DidCommConnectionService).update(agentContext, connection);
		this.emitDidRotatedEvent(agentContext, connection, { previousOurDid });
	}
	/**
	* Process a problem report related to did rotate protocol, by simply deleting any temporary metadata.
	*
	* No specific event is thrown other than generic message processing
	*DidCommInboundMessageContext
	* @param messageContext
	*/
	async processProblemReport(messageContext) {
		const { message, agentContext } = messageContext;
		const connection = messageContext.assertReadyConnection();
		this.logger.debug(`Processing problem report with id ${message.id}`);
		if (!connection.metadata.get(require_DidCommConnectionMetadataTypes.DidCommConnectionMetadataKeys.DidRotate)) throw new __credo_ts_core.CredoError(`No did rotation data found for connection with id '${connection.id}'`);
		connection.metadata.delete(require_DidCommConnectionMetadataTypes.DidCommConnectionMetadataKeys.DidRotate);
		await agentContext.dependencyManager.resolve(require_DidCommConnectionService.DidCommConnectionService).update(agentContext, connection);
	}
	async clearDidRotationData(agentContext, connection) {
		if (!connection.metadata.get(require_DidCommConnectionMetadataTypes.DidCommConnectionMetadataKeys.DidRotate)) throw new __credo_ts_core.CredoError(`No did rotation data found for connection with id '${connection.id}'`);
		connection.metadata.delete(require_DidCommConnectionMetadataTypes.DidCommConnectionMetadataKeys.DidRotate);
		await agentContext.dependencyManager.resolve(require_DidCommConnectionService.DidCommConnectionService).update(agentContext, connection);
	}
	emitDidRotatedEvent(agentContext, connectionRecord, { previousOurDid, previousTheirDid }) {
		this.eventEmitter.emit(agentContext, {
			type: require_DidCommConnectionEvents.DidCommConnectionEventTypes.DidCommConnectionDidRotated,
			payload: {
				connectionRecord: connectionRecord.clone(),
				ourDid: previousOurDid && connectionRecord.did ? {
					from: previousOurDid,
					to: connectionRecord.did
				} : void 0,
				theirDid: previousTheirDid && connectionRecord.theirDid ? {
					from: previousTheirDid,
					to: connectionRecord.theirDid
				} : void 0
			}
		});
	}
};
DidCommDidRotateService = require_decorate.__decorate([
	(0, __credo_ts_core.injectable)(),
	require_decorateParam.__decorateParam(1, (0, __credo_ts_core.inject)(__credo_ts_core.InjectionSymbols.Logger)),
	require_decorateMetadata.__decorateMetadata("design:paramtypes", [
		typeof (_ref = typeof __credo_ts_core.DidResolverService !== "undefined" && __credo_ts_core.DidResolverService) === "function" ? _ref : Object,
		Object,
		typeof (_ref2 = typeof __credo_ts_core.EventEmitter !== "undefined" && __credo_ts_core.EventEmitter) === "function" ? _ref2 : Object
	])
], DidCommDidRotateService);

//#endregion
Object.defineProperty(exports, 'DidCommDidRotateService', {
  enumerable: true,
  get: function () {
    return DidCommDidRotateService;
  }
});