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 { ReturnRouteTypes } from "../../decorators/transport/TransportDecorator.mjs";
import { DidCommOutboundMessageContext } from "../../models/DidCommOutboundMessageContext.mjs";
import "../../models/index.mjs";
import { DidCommHandshakeProtocol } from "./models/DidCommHandshakeProtocol.mjs";
import "./models/index.mjs";
import "./messages/index.mjs";
import { DidCommOutOfBandService } from "../oob/DidCommOutOfBandService.mjs";
import { DidCommConnectionService } from "./services/DidCommConnectionService.mjs";
import { DidCommMessageSender } from "../../DidCommMessageSender.mjs";
import { getMediationRecordForDidDocument } from "../routing/services/helpers.mjs";
import { DidCommConnectionsModuleConfig } from "./DidCommConnectionsModuleConfig.mjs";
import { DidCommDidRotateService } from "./services/DidCommDidRotateService.mjs";
import "./services/index.mjs";
import { DidCommRoutingService } from "../routing/services/DidCommRoutingService.mjs";
import { DidExchangeProtocol } from "./DidExchangeProtocol.mjs";
import { AgentContext, CredoError, DidResolverService, injectable } from "@credo-ts/core";

//#region ../didcomm/src/modules/connections/DidCommConnectionsApi.ts
var _ref, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9;
let DidCommConnectionsApi = class DidCommConnectionsApi$1 {
	constructor(didExchangeProtocol, connectionService, didRotateService, outOfBandService, routingService, didResolverService, messageSender, agentContext, connectionsModuleConfig) {
		this.didExchangeProtocol = didExchangeProtocol;
		this.connectionService = connectionService;
		this.didRotateService = didRotateService;
		this.outOfBandService = outOfBandService;
		this.routingService = routingService;
		this.messageSender = messageSender;
		this.didResolverService = didResolverService;
		this.agentContext = agentContext;
		this.config = connectionsModuleConfig;
	}
	async acceptOutOfBandInvitation(outOfBandRecord, config) {
		const { protocol, label, alias, imageUrl, autoAcceptConnection, ourDid } = config;
		if (ourDid && config.routing) throw new CredoError(`'routing' is disallowed when defining 'ourDid'`);
		let routing = config.routing;
		if (!routing && !ourDid) routing = await this.routingService.getRouting(this.agentContext, { mediatorId: outOfBandRecord.mediatorId });
		let result;
		if (protocol === DidCommHandshakeProtocol.DidExchange) result = await this.didExchangeProtocol.createRequest(this.agentContext, outOfBandRecord, {
			label,
			alias,
			routing,
			autoAcceptConnection,
			ourDid
		});
		else if (protocol === DidCommHandshakeProtocol.Connections) {
			if (ourDid) throw new CredoError("Using an externally defined did for connections protocol is unsupported");
			if (!routing) throw new CredoError("Routing is required for connections protocol");
			result = await this.connectionService.createRequest(this.agentContext, outOfBandRecord, {
				label,
				alias,
				imageUrl,
				routing,
				autoAcceptConnection
			});
		} else throw new CredoError(`Unsupported handshake protocol ${protocol}.`);
		const { message, connectionRecord } = result;
		const outboundMessageContext = new DidCommOutboundMessageContext(message, {
			agentContext: this.agentContext,
			connection: connectionRecord,
			outOfBand: outOfBandRecord
		});
		await this.messageSender.sendMessage(outboundMessageContext);
		return connectionRecord;
	}
	/**
	* Accept a connection request as inviter (by sending a connection response message) for the connection with the specified connection id.
	* This is not needed when auto accepting of connection is enabled.
	*
	* @param connectionId the id of the connection for which to accept the request
	* @returns connection record
	*/
	async acceptRequest(connectionId) {
		const connectionRecord = await this.connectionService.findById(this.agentContext, connectionId);
		if (!connectionRecord) throw new CredoError(`Connection record ${connectionId} not found.`);
		if (!connectionRecord.outOfBandId) throw new CredoError(`Connection record ${connectionId} does not have out-of-band record.`);
		const outOfBandRecord = await this.outOfBandService.findById(this.agentContext, connectionRecord.outOfBandId);
		if (!outOfBandRecord) throw new CredoError(`Out-of-band record ${connectionRecord.outOfBandId} not found.`);
		const routing = outOfBandRecord.reusable || outOfBandRecord.outOfBandInvitation.getInlineServices().length === 0 ? await this.routingService.getRouting(this.agentContext) : void 0;
		let outboundMessageContext;
		if (connectionRecord.protocol === DidCommHandshakeProtocol.DidExchange) outboundMessageContext = new DidCommOutboundMessageContext(await this.didExchangeProtocol.createResponse(this.agentContext, connectionRecord, outOfBandRecord, routing), {
			agentContext: this.agentContext,
			connection: connectionRecord
		});
		else {
			const routing$1 = outOfBandRecord.reusable || outOfBandRecord.outOfBandInvitation.getInlineServices().length === 0 ? await this.routingService.getRouting(this.agentContext) : void 0;
			const { message } = await this.connectionService.createResponse(this.agentContext, connectionRecord, outOfBandRecord, routing$1);
			outboundMessageContext = new DidCommOutboundMessageContext(message, {
				agentContext: this.agentContext,
				connection: connectionRecord
			});
		}
		await this.messageSender.sendMessage(outboundMessageContext);
		return connectionRecord;
	}
	/**
	* Accept a connection response as invitee (by sending a trust ping message) for the connection with the specified connection id.
	* This is not needed when auto accepting of connection is enabled.
	*
	* @param connectionId the id of the connection for which to accept the response
	* @returns connection record
	*/
	async acceptResponse(connectionId) {
		const connectionRecord = await this.connectionService.getById(this.agentContext, connectionId);
		let outboundMessageContext;
		if (connectionRecord.protocol === DidCommHandshakeProtocol.DidExchange) {
			if (!connectionRecord.outOfBandId) throw new CredoError(`Connection ${connectionRecord.id} does not have outOfBandId!`);
			const outOfBandRecord = await this.outOfBandService.findById(this.agentContext, connectionRecord.outOfBandId);
			if (!outOfBandRecord) throw new CredoError(`OutOfBand record for connection ${connectionRecord.id} with outOfBandId ${connectionRecord.outOfBandId} not found!`);
			const message = await this.didExchangeProtocol.createComplete(this.agentContext, connectionRecord, outOfBandRecord);
			message.setReturnRouting(ReturnRouteTypes.none);
			outboundMessageContext = new DidCommOutboundMessageContext(message, {
				agentContext: this.agentContext,
				connection: connectionRecord
			});
		} else {
			const { message } = await this.connectionService.createTrustPing(this.agentContext, connectionRecord, { responseRequested: false });
			message.setReturnRouting(ReturnRouteTypes.none);
			outboundMessageContext = new DidCommOutboundMessageContext(message, {
				agentContext: this.agentContext,
				connection: connectionRecord
			});
		}
		await this.messageSender.sendMessage(outboundMessageContext);
		return connectionRecord;
	}
	/**
	* Send a trust ping to an established connection
	*
	* @param connectionId the id of the connection for which to accept the response
	* @param responseRequested do we want a response to our ping
	* @param withReturnRouting do we want a response at the time of posting
	* @returns TrustPingMessage
	*/
	async sendPing(connectionId, { responseRequested = true, withReturnRouting = void 0 } = {}) {
		const connection = await this.getById(connectionId);
		const { message } = await this.connectionService.createTrustPing(this.agentContext, connection, { responseRequested });
		if (withReturnRouting === true) message.setReturnRouting(ReturnRouteTypes.all);
		if (withReturnRouting === false) message.setReturnRouting(ReturnRouteTypes.none);
		await this.messageSender.sendMessage(new DidCommOutboundMessageContext(message, {
			agentContext: this.agentContext,
			connection
		}));
		return message;
	}
	/**
	* Rotate the DID used for a given connection, notifying the other party immediately.
	*
	*  If `toDid` is not specified, a new peer did will be created. Optionally, routing
	* configuration can be set.
	*
	* Note: any did created or imported in agent wallet can be used as `toDid`, as long as
	* there are valid DIDComm services in its DID Document.
	*
	* @param options connectionId and optional target did and routing configuration
	* @returns object containing the new did
	*/
	async rotate(options) {
		const { connectionId, toDid } = options;
		const connection = await this.connectionService.getById(this.agentContext, connectionId);
		if (toDid && options.routing) throw new CredoError(`'routing' is disallowed when defining 'toDid'`);
		let routing = options.routing;
		if (!toDid && !routing) routing = await this.routingService.getRouting(this.agentContext, {});
		const message = await this.didRotateService.createRotate(this.agentContext, {
			connection,
			toDid,
			routing
		});
		const outboundMessageContext = new DidCommOutboundMessageContext(message, {
			agentContext: this.agentContext,
			connection
		});
		await this.messageSender.sendMessage(outboundMessageContext);
		return { newDid: message.toDid };
	}
	/**
	* Terminate a connection by sending a hang-up message to the other party. The connection record itself and any
	* keys used for mediation will only be deleted if `deleteAfterHangup` flag is set.
	*
	* @param options connectionId
	*/
	async hangup(options) {
		const connection = await this.connectionService.getById(this.agentContext, options.connectionId);
		const connectionBeforeHangup = connection.clone();
		const outboundMessageContext = new DidCommOutboundMessageContext(await this.didRotateService.createHangup(this.agentContext, { connection }), {
			agentContext: this.agentContext,
			connection: connectionBeforeHangup
		});
		await this.messageSender.sendMessage(outboundMessageContext);
		if (options.deleteAfterHangup) {
			await this.removeRouting(connectionBeforeHangup);
			await this.deleteById(connection.id);
		}
	}
	async returnWhenIsConnected(connectionId, options) {
		return this.connectionService.returnWhenIsConnected(this.agentContext, connectionId, options?.timeoutMs);
	}
	/**
	* Retrieve all connections records
	*
	* @returns List containing all connection records
	*/
	getAll() {
		return this.connectionService.getAll(this.agentContext);
	}
	/**
	* Retrieve all connections records by specified query params
	*
	* @returns List containing all connection records matching specified query paramaters
	*/
	findAllByQuery(query, queryOptions) {
		return this.connectionService.findAllByQuery(this.agentContext, query, queryOptions);
	}
	/**
	* Allows for the addition of connectionType to the record.
	*  Either updates or creates an array of string connection types
	* @param connectionId
	* @param type
	* @throws {RecordNotFoundError} If no record is found
	*/
	async addConnectionType(connectionId, type) {
		const record = await this.getById(connectionId);
		await this.connectionService.addConnectionType(this.agentContext, record, type);
		return record;
	}
	/**
	* Removes the given tag from the given record found by connectionId, if the tag exists otherwise does nothing
	* @param connectionId
	* @param type
	* @throws {RecordNotFoundError} If no record is found
	*/
	async removeConnectionType(connectionId, type) {
		const record = await this.getById(connectionId);
		await this.connectionService.removeConnectionType(this.agentContext, record, type);
		return record;
	}
	/**
	* Gets the known connection types for the record matching the given connectionId
	* @param connectionId
	* @returns An array of known connection types or null if none exist
	* @throws {RecordNotFoundError} If no record is found
	*/
	async getConnectionTypes(connectionId) {
		const record = await this.getById(connectionId);
		return this.connectionService.getConnectionTypes(record);
	}
	/**
	*
	* @param connectionTypes An array of connection types to query for a match for
	* @returns a promise of ab array of connection records
	*/
	async findAllByConnectionTypes(connectionTypes) {
		return this.connectionService.findAllByConnectionTypes(this.agentContext, connectionTypes);
	}
	/**
	* Retrieve a connection record by id
	*
	* @param connectionId The connection record id
	* @throws {RecordNotFoundError} If no record is found
	* @return The connection record
	*
	*/
	getById(connectionId) {
		return this.connectionService.getById(this.agentContext, connectionId);
	}
	/**
	* Find a connection record by id
	*
	* @param connectionId the connection record id
	* @returns The connection record or null if not found
	*/
	findById(connectionId) {
		return this.connectionService.findById(this.agentContext, connectionId);
	}
	/**
	* Delete a connection record by id
	*
	* @param connectionId the connection record id
	*/
	async deleteById(connectionId) {
		const connection = await this.connectionService.getById(this.agentContext, connectionId);
		await this.removeRouting(connection);
		return this.connectionService.deleteById(this.agentContext, connectionId);
	}
	async removeRouting(connection) {
		if (connection.mediatorId && connection.did) {
			const { didDocument } = await this.didResolverService.resolve(this.agentContext, connection.did);
			if (didDocument) await this.routingService.removeRouting(this.agentContext, {
				recipientKeys: didDocument.getRecipientKeysWithVerificationMethod({ mapX25519ToEd25519: true }).map(({ publicJwk }) => publicJwk),
				mediatorId: connection.mediatorId
			});
		}
	}
	/**
	* Remove relationship of a connection with any previous did (either ours or theirs), preventing it from accepting
	* messages from them. This is usually called when a DID Rotation flow has been succesful and we are sure that no
	* more messages with older keys will arrive.
	*
	* It will remove routing keys from mediator if applicable.
	*
	* Note: this will not actually delete any DID from the wallet.
	*
	* @param connectionId
	*/
	async removePreviousDids(options) {
		const connection = await this.connectionService.getById(this.agentContext, options.connectionId);
		for (const previousDid of connection.previousDids) {
			const did = await this.didResolverService.resolve(this.agentContext, previousDid);
			if (!did.didDocument) continue;
			const mediatorRecord = await getMediationRecordForDidDocument(this.agentContext, did.didDocument);
			if (mediatorRecord) await this.routingService.removeRouting(this.agentContext, {
				recipientKeys: did.didDocument.getRecipientKeysWithVerificationMethod({ mapX25519ToEd25519: true }).map(({ publicJwk }) => publicJwk),
				mediatorId: mediatorRecord.id
			});
		}
		connection.previousDids = [];
		connection.previousTheirDids = [];
		await this.connectionService.update(this.agentContext, connection);
	}
	async findAllByOutOfBandId(outOfBandId) {
		return this.connectionService.findAllByOutOfBandId(this.agentContext, outOfBandId);
	}
	/**
	* Retrieve a connection record by thread id
	*
	* @param threadId The thread id
	* @throws {RecordNotFoundError} If no record is found
	* @throws {RecordDuplicateError} If multiple records are found
	* @returns The connection record
	*/
	getByThreadId(threadId) {
		return this.connectionService.getByThreadId(this.agentContext, threadId);
	}
	async findByDid(did) {
		return this.connectionService.findByTheirDid(this.agentContext, did);
	}
	async findByInvitationDid(invitationDid) {
		return this.connectionService.findByInvitationDid(this.agentContext, invitationDid);
	}
};
DidCommConnectionsApi = __decorate([injectable(), __decorateMetadata("design:paramtypes", [
	typeof (_ref = typeof DidExchangeProtocol !== "undefined" && DidExchangeProtocol) === "function" ? _ref : Object,
	typeof (_ref2 = typeof DidCommConnectionService !== "undefined" && DidCommConnectionService) === "function" ? _ref2 : Object,
	typeof (_ref3 = typeof DidCommDidRotateService !== "undefined" && DidCommDidRotateService) === "function" ? _ref3 : Object,
	typeof (_ref4 = typeof DidCommOutOfBandService !== "undefined" && DidCommOutOfBandService) === "function" ? _ref4 : Object,
	typeof (_ref5 = typeof DidCommRoutingService !== "undefined" && DidCommRoutingService) === "function" ? _ref5 : Object,
	typeof (_ref6 = typeof DidResolverService !== "undefined" && DidResolverService) === "function" ? _ref6 : Object,
	typeof (_ref7 = typeof DidCommMessageSender !== "undefined" && DidCommMessageSender) === "function" ? _ref7 : Object,
	typeof (_ref8 = typeof AgentContext !== "undefined" && AgentContext) === "function" ? _ref8 : Object,
	typeof (_ref9 = typeof DidCommConnectionsModuleConfig !== "undefined" && DidCommConnectionsModuleConfig) === "function" ? _ref9 : Object
])], DidCommConnectionsApi);

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