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_DidCommOutOfBandState = require('./domain/DidCommOutOfBandState.js');
const require_DidCommDocumentService = require('../../services/DidCommDocumentService.js');
require('../../services/index.js');
const require_helpers = require('../connections/services/helpers.js');
const require_DidCommOutOfBandEvents = require('./domain/DidCommOutOfBandEvents.js');
const require_DidCommOutOfBandRole = require('./domain/DidCommOutOfBandRole.js');
const require_DidCommOutOfBandInvitation = require('./messages/DidCommOutOfBandInvitation.js');
const require_DidCommHandshakeReuseAcceptedMessage = require('./messages/DidCommHandshakeReuseAcceptedMessage.js');
const require_DidCommHandshakeReuseMessage = require('./messages/DidCommHandshakeReuseMessage.js');
require('./messages/index.js');
const require_DidCommOutOfBandRecord = require('./repository/DidCommOutOfBandRecord.js');
const require_DidCommOutOfBandRepository = require('./repository/DidCommOutOfBandRepository.js');
require('./repository/index.js');
let __credo_ts_core = require("@credo-ts/core");
__credo_ts_core = require_rolldown_runtime.__toESM(__credo_ts_core);

//#region ../didcomm/src/modules/oob/DidCommOutOfBandService.ts
var _ref, _ref2, _ref3;
let DidCommOutOfBandService = class DidCommOutOfBandService$1 {
	constructor(outOfBandRepository, eventEmitter, didCommDocumentService) {
		this.outOfBandRepository = outOfBandRepository;
		this.eventEmitter = eventEmitter;
		this.didCommDocumentService = didCommDocumentService;
	}
	/**
	* Creates an Out of Band record from a Connection/DIDExchange request started by using
	* a publicly resolvable DID this agent can control
	*/
	async createFromImplicitInvitation(agentContext, config) {
		const { did, threadId, handshakeProtocols, autoAcceptConnection, recipientKey } = config;
		const publicDid = (0, __credo_ts_core.parseDid)(did);
		const [createdDid] = await agentContext.dependencyManager.resolve(__credo_ts_core.DidsApi).getCreatedDids({ did: publicDid.did });
		if (!createdDid) throw new __credo_ts_core.CredoError(`Referenced public did ${did} not found.`);
		const outOfBandInvitation = new require_DidCommOutOfBandInvitation.DidCommOutOfBandInvitation({
			id: did,
			services: [did],
			handshakeProtocols
		});
		outOfBandInvitation.setThread({ threadId });
		const outOfBandRecord = new require_DidCommOutOfBandRecord.DidCommOutOfBandRecord({
			role: require_DidCommOutOfBandRole.DidCommOutOfBandRole.Sender,
			state: require_DidCommOutOfBandState.DidCommOutOfBandState.AwaitResponse,
			reusable: true,
			autoAcceptConnection: autoAcceptConnection ?? false,
			outOfBandInvitation,
			tags: { recipientKeyFingerprints: [recipientKey.fingerprint] }
		});
		await this.save(agentContext, outOfBandRecord);
		this.emitStateChangedEvent(agentContext, outOfBandRecord, null);
		return outOfBandRecord;
	}
	async processHandshakeReuse(messageContext) {
		const reuseMessage = messageContext.message;
		const parentThreadId = reuseMessage.thread?.parentThreadId;
		if (!parentThreadId) throw new __credo_ts_core.CredoError("handshake-reuse message must have a parent thread id");
		const outOfBandRecord = await this.findByCreatedInvitationId(messageContext.agentContext, parentThreadId);
		if (!outOfBandRecord) throw new __credo_ts_core.CredoError("No out of band record found for handshake-reuse message");
		outOfBandRecord.assertRole(require_DidCommOutOfBandRole.DidCommOutOfBandRole.Sender);
		outOfBandRecord.assertState(require_DidCommOutOfBandState.DidCommOutOfBandState.AwaitResponse);
		if ((outOfBandRecord.outOfBandInvitation.getRequests()?.length ?? 0) > 0) throw new __credo_ts_core.CredoError("Handshake reuse should only be used when no requests are present");
		const reusedConnection = messageContext.assertReadyConnection();
		this.eventEmitter.emit(messageContext.agentContext, {
			type: require_DidCommOutOfBandEvents.DidCommOutOfBandEventTypes.HandshakeReused,
			payload: {
				reuseThreadId: reuseMessage.threadId,
				connectionRecord: reusedConnection,
				outOfBandRecord
			}
		});
		if (!outOfBandRecord.reusable) await this.updateState(messageContext.agentContext, outOfBandRecord, require_DidCommOutOfBandState.DidCommOutOfBandState.Done);
		return new require_DidCommHandshakeReuseAcceptedMessage.DidCommHandshakeReuseAcceptedMessage({
			threadId: reuseMessage.threadId,
			parentThreadId
		});
	}
	async processHandshakeReuseAccepted(messageContext) {
		const reuseAcceptedMessage = messageContext.message;
		const parentThreadId = reuseAcceptedMessage.thread?.parentThreadId;
		if (!parentThreadId) throw new __credo_ts_core.CredoError("handshake-reuse-accepted message must have a parent thread id");
		const outOfBandRecord = await this.findByReceivedInvitationId(messageContext.agentContext, parentThreadId);
		if (!outOfBandRecord) throw new __credo_ts_core.CredoError("No out of band record found for handshake-reuse-accepted message");
		outOfBandRecord.assertRole(require_DidCommOutOfBandRole.DidCommOutOfBandRole.Receiver);
		outOfBandRecord.assertState(require_DidCommOutOfBandState.DidCommOutOfBandState.PrepareResponse);
		const reusedConnection = messageContext.assertReadyConnection();
		if (outOfBandRecord.reuseConnectionId !== reusedConnection.id) throw new __credo_ts_core.CredoError("handshake-reuse-accepted is not in response to a handshake-reuse message.");
		this.eventEmitter.emit(messageContext.agentContext, {
			type: require_DidCommOutOfBandEvents.DidCommOutOfBandEventTypes.HandshakeReused,
			payload: {
				reuseThreadId: reuseAcceptedMessage.threadId,
				connectionRecord: reusedConnection,
				outOfBandRecord
			}
		});
		await this.updateState(messageContext.agentContext, outOfBandRecord, require_DidCommOutOfBandState.DidCommOutOfBandState.Done);
	}
	async createHandShakeReuse(agentContext, outOfBandRecord, connectionRecord) {
		const reuseMessage = new require_DidCommHandshakeReuseMessage.DidCommHandshakeReuseMessage({ parentThreadId: outOfBandRecord.outOfBandInvitation.id });
		outOfBandRecord.reuseConnectionId = connectionRecord.id;
		await this.outOfBandRepository.update(agentContext, outOfBandRecord);
		return reuseMessage;
	}
	async save(agentContext, outOfBandRecord) {
		return this.outOfBandRepository.save(agentContext, outOfBandRecord);
	}
	async updateState(agentContext, outOfBandRecord, newState) {
		const previousState = outOfBandRecord.state;
		outOfBandRecord.state = newState;
		await this.outOfBandRepository.update(agentContext, outOfBandRecord);
		this.emitStateChangedEvent(agentContext, outOfBandRecord, previousState);
	}
	emitStateChangedEvent(agentContext, outOfBandRecord, previousState) {
		this.eventEmitter.emit(agentContext, {
			type: require_DidCommOutOfBandEvents.DidCommOutOfBandEventTypes.OutOfBandStateChanged,
			payload: {
				outOfBandRecord: outOfBandRecord.clone(),
				previousState
			}
		});
	}
	async findById(agentContext, outOfBandRecordId) {
		return this.outOfBandRepository.findById(agentContext, outOfBandRecordId);
	}
	async getById(agentContext, outOfBandRecordId) {
		return this.outOfBandRepository.getById(agentContext, outOfBandRecordId);
	}
	async findByReceivedInvitationId(agentContext, receivedInvitationId) {
		return this.outOfBandRepository.findSingleByQuery(agentContext, {
			invitationId: receivedInvitationId,
			role: require_DidCommOutOfBandRole.DidCommOutOfBandRole.Receiver
		});
	}
	async findByCreatedInvitationId(agentContext, createdInvitationId, threadId) {
		return this.outOfBandRepository.findSingleByQuery(agentContext, {
			invitationId: createdInvitationId,
			role: require_DidCommOutOfBandRole.DidCommOutOfBandRole.Sender,
			threadId
		});
	}
	async findCreatedByRecipientKey(agentContext, recipientKey) {
		return this.outOfBandRepository.findSingleByQuery(agentContext, {
			recipientKeyFingerprints: [recipientKey.fingerprint],
			role: require_DidCommOutOfBandRole.DidCommOutOfBandRole.Sender
		});
	}
	async getAll(agentContext) {
		return this.outOfBandRepository.getAll(agentContext);
	}
	async findAllByQuery(agentContext, query, queryOptions) {
		return this.outOfBandRepository.findByQuery(agentContext, query, queryOptions);
	}
	async deleteById(agentContext, outOfBandId) {
		const outOfBandRecord = await this.getById(agentContext, outOfBandId);
		return this.outOfBandRepository.delete(agentContext, outOfBandRecord);
	}
	/**
	* Extract a resolved didcomm service from an out of band invitation.
	*
	* Currently the first service that can be resolved is returned.
	*/
	async getResolvedServiceForOutOfBandServices(agentContext, services, inlineServiceKeys) {
		for (const service of services) if (typeof service === "string") {
			const [didService] = await this.didCommDocumentService.resolveServicesFromDid(agentContext, service);
			if (didService) return didService;
		} else return require_helpers.getResolvedDidcommServiceWithSigningKeyId(service, inlineServiceKeys);
		throw new __credo_ts_core.CredoError("Could not extract a service from the out of band invitation.");
	}
};
DidCommOutOfBandService = require_decorate.__decorate([(0, __credo_ts_core.injectable)(), require_decorateMetadata.__decorateMetadata("design:paramtypes", [
	typeof (_ref = typeof require_DidCommOutOfBandRepository.DidCommOutOfBandRepository !== "undefined" && require_DidCommOutOfBandRepository.DidCommOutOfBandRepository) === "function" ? _ref : Object,
	typeof (_ref2 = typeof __credo_ts_core.EventEmitter !== "undefined" && __credo_ts_core.EventEmitter) === "function" ? _ref2 : Object,
	typeof (_ref3 = typeof require_DidCommDocumentService.DidCommDocumentService !== "undefined" && require_DidCommDocumentService.DidCommDocumentService) === "function" ? _ref3 : Object
])], DidCommOutOfBandService);

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