import { __decorateMetadata } from "../../../../../../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorateMetadata.mjs";
import { __decorate } from "../../../../../../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorate.mjs";
import { DidCommModuleConfig } from "../../../DidCommModuleConfig.mjs";
import { __decorateParam } from "../../../../../../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorateParam.mjs";
import { DidCommConnectionService } from "../../connections/services/DidCommConnectionService.mjs";
import { DidCommMediatorRoutingRecord } from "../repository/DidCommMediatorRoutingRecord.mjs";
import { DidCommMediatorRoutingRepository } from "../repository/DidCommMediatorRoutingRepository.mjs";
import { DidCommMessageSender } from "../../../DidCommMessageSender.mjs";
import { DidCommConnectionMetadataKeys } from "../../connections/repository/DidCommConnectionMetadataTypes.mjs";
import { DidCommRoutingEventTypes } from "../DidCommRoutingEvents.mjs";
import { DidCommKeylistUpdateAction, DidCommKeylistUpdateMessage } from "../messages/DidCommKeylistUpdateMessage.mjs";
import { DidCommKeylistUpdateResponseMessage, DidCommKeylistUpdateResult, DidCommKeylistUpdated } from "../messages/DidCommKeylistUpdateResponseMessage.mjs";
import { DidCommMediationGrantMessage } from "../messages/DidCommMediationGrantMessage.mjs";
import "../messages/index.mjs";
import { DidCommMediationRole } from "../models/DidCommMediationRole.mjs";
import { DidCommMediationState } from "../models/DidCommMediationState.mjs";
import { DidCommMediationRecord } from "../repository/DidCommMediationRecord.mjs";
import { DidCommMediationRepository } from "../repository/DidCommMediationRepository.mjs";
import "../../connections/services/index.mjs";
import { DidCommMessagePickupApi } from "../../message-pickup/DidCommMessagePickupApi.mjs";
import { DidCommMessagePickupSessionRole } from "../../message-pickup/DidCommMessagePickupSession.mjs";
import "../../message-pickup/index.mjs";
import { DidCommMessageForwardingStrategy } from "../DidCommMessageForwardingStrategy.mjs";
import { DidCommMediatorModuleConfig } from "../DidCommMediatorModuleConfig.mjs";
import "../repository/index.mjs";
import { CredoError, DidKey, EventEmitter, InjectionSymbols, Kms, RecordDuplicateError, TypedArrayEncoder, didKeyToVerkey, inject, injectable, isDidKey, verkeyToDidKey } from "@credo-ts/core";

//#region ../didcomm/src/modules/routing/services/DidCommMediatorService.ts
var _ref, _ref2, _ref3, _ref4;
let DidCommMediatorService = class DidCommMediatorService$1 {
	constructor(mediationRepository, mediatorRoutingRepository, eventEmitter, logger, connectionService) {
		this.mediationRepository = mediationRepository;
		this.mediatorRoutingRepository = mediatorRoutingRepository;
		this.eventEmitter = eventEmitter;
		this.logger = logger;
		this.connectionService = connectionService;
	}
	async getRoutingKeys(agentContext) {
		const mediatorRoutingRecord = await this.findMediatorRoutingRecord(agentContext);
		if (mediatorRoutingRecord) {
			this.logger.debug(`Returning mediator routing keys ${mediatorRoutingRecord.routingKeys}`);
			return mediatorRoutingRecord.routingKeysWithKeyId;
		}
		throw new CredoError("Mediator has not been initialized yet.");
	}
	async processForwardMessage(messageContext) {
		const { message, agentContext } = messageContext;
		const messagePickupApi = agentContext.resolve(DidCommMessagePickupApi);
		if (!message.to) throw new CredoError("Invalid Message: Missing required attribute \"to\"");
		const mediationRecord = await this.mediationRepository.getSingleByRecipientKey(agentContext, message.to);
		mediationRecord.assertReady();
		mediationRecord.assertRole(DidCommMediationRole.Mediator);
		const connection = await this.connectionService.getById(agentContext, mediationRecord.connectionId);
		connection.assertReady();
		const messageForwardingStrategy = agentContext.dependencyManager.resolve(DidCommMediatorModuleConfig).messageForwardingStrategy;
		const messageSender = agentContext.dependencyManager.resolve(DidCommMessageSender);
		switch (messageForwardingStrategy) {
			case DidCommMessageForwardingStrategy.QueueOnly:
				await messagePickupApi.queueMessage({
					connectionId: mediationRecord.connectionId,
					recipientDids: [verkeyToDidKey(message.to)],
					message: message.message
				});
				break;
			case DidCommMessageForwardingStrategy.QueueAndLiveModeDelivery: {
				await messagePickupApi.queueMessage({
					connectionId: mediationRecord.connectionId,
					recipientDids: [verkeyToDidKey(message.to)],
					message: message.message
				});
				const session = await messagePickupApi.getLiveModeSession({
					connectionId: mediationRecord.connectionId,
					role: DidCommMessagePickupSessionRole.MessageHolder
				});
				if (session) await messagePickupApi.deliverMessagesFromQueue({
					pickupSessionId: session.id,
					recipientDid: verkeyToDidKey(message.to)
				});
				break;
			}
			case DidCommMessageForwardingStrategy.DirectDelivery: await messageSender.sendPackage(agentContext, {
				connection,
				recipientKey: verkeyToDidKey(message.to),
				encryptedMessage: message.message
			});
		}
	}
	async processKeylistUpdateRequest(messageContext) {
		const connection = messageContext.assertReadyConnection();
		const { message } = messageContext;
		const keylist = [];
		const mediationRecord = await this.mediationRepository.getByConnectionId(messageContext.agentContext, connection.id);
		mediationRecord.assertReady();
		mediationRecord.assertRole(DidCommMediationRole.Mediator);
		const connectionUsesDidKey = message.updates.some((update) => isDidKey(update.recipientKey));
		await this.updateUseDidKeysFlag(messageContext.agentContext, connection, DidCommKeylistUpdateMessage.type.protocolUri, connectionUsesDidKey);
		for (const update of message.updates) {
			const updated = new DidCommKeylistUpdated({
				action: update.action,
				recipientKey: update.recipientKey,
				result: DidCommKeylistUpdateResult.NoChange
			});
			const publicKeyBase58 = didKeyToVerkey(update.recipientKey);
			if (update.action === DidCommKeylistUpdateAction.add) {
				mediationRecord.addRecipientKey(publicKeyBase58);
				updated.result = DidCommKeylistUpdateResult.Success;
				keylist.push(updated);
			} else if (update.action === DidCommKeylistUpdateAction.remove) {
				updated.result = mediationRecord.removeRecipientKey(publicKeyBase58) ? DidCommKeylistUpdateResult.Success : DidCommKeylistUpdateResult.NoChange;
				keylist.push(updated);
			}
		}
		await this.mediationRepository.update(messageContext.agentContext, mediationRecord);
		return new DidCommKeylistUpdateResponseMessage({
			keylist,
			threadId: message.threadId
		});
	}
	async createGrantMediationMessage(agentContext, mediationRecord) {
		mediationRecord.assertState(DidCommMediationState.Requested);
		mediationRecord.assertRole(DidCommMediationRole.Mediator);
		await this.updateState(agentContext, mediationRecord, DidCommMediationState.Granted);
		const didcommConfig = agentContext.dependencyManager.resolve(DidCommModuleConfig);
		const useDidKey = didcommConfig.useDidKeyInProtocols;
		const routingKeys = (await this.getRoutingKeys(agentContext)).map((routingKey) => useDidKey ? new DidKey(routingKey).did : TypedArrayEncoder.toBase58(routingKey.publicKey.publicKey));
		return {
			mediationRecord,
			message: new DidCommMediationGrantMessage({
				endpoint: didcommConfig.endpoints[0],
				routingKeys,
				threadId: mediationRecord.threadId
			})
		};
	}
	async processMediationRequest(messageContext) {
		const mediationRecord = new DidCommMediationRecord({
			connectionId: messageContext.assertReadyConnection().id,
			role: DidCommMediationRole.Mediator,
			state: DidCommMediationState.Requested,
			threadId: messageContext.message.threadId
		});
		await this.mediationRepository.save(messageContext.agentContext, mediationRecord);
		this.emitStateChangedEvent(messageContext.agentContext, mediationRecord, null);
		return mediationRecord;
	}
	async findById(agentContext, mediatorRecordId) {
		return this.mediationRepository.findById(agentContext, mediatorRecordId);
	}
	async getById(agentContext, mediatorRecordId) {
		return this.mediationRepository.getById(agentContext, mediatorRecordId);
	}
	async getAll(agentContext) {
		return await this.mediationRepository.getAll(agentContext);
	}
	async findMediatorRoutingRecord(agentContext) {
		return await this.mediatorRoutingRepository.findById(agentContext, this.mediatorRoutingRepository.MEDIATOR_ROUTING_RECORD_ID);
	}
	async createMediatorRoutingRecord(agentContext) {
		const kms = agentContext.resolve(Kms.KeyManagementApi);
		const didcommConfig = agentContext.resolve(DidCommModuleConfig);
		const routingKey = await kms.createKey({ type: {
			kty: "OKP",
			crv: "Ed25519"
		} });
		const publicJwk = Kms.PublicJwk.fromPublicJwk(routingKey.publicJwk);
		const routingRecord = new DidCommMediatorRoutingRecord({
			id: this.mediatorRoutingRepository.MEDIATOR_ROUTING_RECORD_ID,
			routingKeys: [{
				routingKeyFingerprint: publicJwk.fingerprint,
				kmsKeyId: routingKey.keyId
			}]
		});
		try {
			await this.mediatorRoutingRepository.save(agentContext, routingRecord);
			this.eventEmitter.emit(agentContext, {
				type: DidCommRoutingEventTypes.RoutingCreatedEvent,
				payload: { routing: {
					endpoints: didcommConfig.endpoints,
					routingKeys: [],
					recipientKey: routingKey
				} }
			});
		} catch (error) {
			if (error instanceof RecordDuplicateError) return this.mediatorRoutingRepository.getById(agentContext, this.mediatorRoutingRepository.MEDIATOR_ROUTING_RECORD_ID);
			throw error;
		}
		return routingRecord;
	}
	async findAllByQuery(agentContext, query, queryOptions) {
		return await this.mediationRepository.findByQuery(agentContext, query, queryOptions);
	}
	async updateState(agentContext, mediationRecord, newState) {
		const previousState = mediationRecord.state;
		mediationRecord.state = newState;
		await this.mediationRepository.update(agentContext, mediationRecord);
		this.emitStateChangedEvent(agentContext, mediationRecord, previousState);
	}
	emitStateChangedEvent(agentContext, mediationRecord, previousState) {
		this.eventEmitter.emit(agentContext, {
			type: DidCommRoutingEventTypes.MediationStateChanged,
			payload: {
				mediationRecord: mediationRecord.clone(),
				previousState
			}
		});
	}
	async updateUseDidKeysFlag(agentContext, connection, protocolUri, connectionUsesDidKey) {
		const useDidKeysForProtocol = connection.metadata.get(DidCommConnectionMetadataKeys.UseDidKeysForProtocol) ?? {};
		useDidKeysForProtocol[protocolUri] = connectionUsesDidKey;
		connection.metadata.set(DidCommConnectionMetadataKeys.UseDidKeysForProtocol, useDidKeysForProtocol);
		await this.connectionService.update(agentContext, connection);
	}
};
DidCommMediatorService = __decorate([
	injectable(),
	__decorateParam(3, inject(InjectionSymbols.Logger)),
	__decorateMetadata("design:paramtypes", [
		typeof (_ref = typeof DidCommMediationRepository !== "undefined" && DidCommMediationRepository) === "function" ? _ref : Object,
		typeof (_ref2 = typeof DidCommMediatorRoutingRepository !== "undefined" && DidCommMediatorRoutingRepository) === "function" ? _ref2 : Object,
		typeof (_ref3 = typeof EventEmitter !== "undefined" && EventEmitter) === "function" ? _ref3 : Object,
		Object,
		typeof (_ref4 = typeof DidCommConnectionService !== "undefined" && DidCommConnectionService) === "function" ? _ref4 : Object
	])
], DidCommMediatorService);

//#endregion
export { DidCommMediatorService };
//# sourceMappingURL=DidCommMediatorService.mjs.map