define(["require", "exports", "./gateway_handler", "@process-engine/process_engine_contracts", "../next_flow_node_info"], function (require, exports, gateway_handler_1, process_engine_contracts_1, next_flow_node_info_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    class ParallelGatewayHandler extends gateway_handler_1.GatewayHandler {
        constructor(flowNodeHandlerFactory, datastoreService) {
            super();
            this.flowNodeHandlerFactory = flowNodeHandlerFactory;
            this.datastoreService = datastoreService;
        }
        async executeIntern(flowNode, processToken, context) {
            const processDefinition = await flowNode.getProcessDef(context);
            const incomingSequenceFlows = this.getIncomingSequenceFlowsFor(flowNode.id, processDefinition);
            const outgoingSequenceFlows = this.getOutgoingSequenceFlowsFor(flowNode.id, processDefinition);
            if (incomingSequenceFlows.length < outgoingSequenceFlows.length) {
                const joinGateway = await this.findJoinGateway(flowNode, processDefinition, context);
                const promises = [];
                for (const outgoingSequenceFlow of outgoingSequenceFlows) {
                    const processTokenForBranch = await this.createProcessToken(context);
                    const nextFlowNodeInBranch = this.getFlowNodeById(outgoingSequenceFlow.target.id, processDefinition);
                    promises.push(this.executeBranchToJoinGateway(nextFlowNodeInBranch, processTokenForBranch, context, joinGateway));
                }
                const nextFlowNodeInfos = await Promise.all(promises);
                for (const nextFlowNodeInfo of nextFlowNodeInfos) {
                    this.mergeTokenHistory(processToken, nextFlowNodeInfo.processToken);
                }
                return new next_flow_node_info_1.NextFlowNodeInfo(await this.getNextFlowNodeFor(joinGateway, context), processToken);
            }
            else {
                return null;
            }
        }
        async findJoinGateway(flowNode, processDefinition, context) {
            const incomingSequenceFlows = this.getIncomingSequenceFlowsFor(flowNode.id, processDefinition);
            const outgoingSequenceFlows = this.getOutgoingSequenceFlowsFor(flowNode.id, processDefinition);
            if (flowNode.type == process_engine_contracts_1.BpmnType.parallelGateway && incomingSequenceFlows.length > outgoingSequenceFlows.length) {
                return flowNode;
            }
            else {
                return this.findJoinGateway(await this.getNextFlowNodeFor(flowNode, context), processDefinition, context);
            }
        }
        async executeBranchToJoinGateway(flowNode, processToken, context, joinGateway) {
            const flowNodeHandler = this.flowNodeHandlerFactory.create(flowNode.type);
            const nextFlowNodeInfo = await flowNodeHandler.execute(flowNode, processToken, context);
            if (nextFlowNodeInfo.flowNode !== null && nextFlowNodeInfo.flowNode.id !== joinGateway.id) {
                return this.executeBranchToJoinGateway(nextFlowNodeInfo.flowNode, nextFlowNodeInfo.processToken, context, joinGateway);
            }
            return new next_flow_node_info_1.NextFlowNodeInfo(joinGateway, processToken);
        }
        async createProcessToken(context) {
            const processTokenType = await this.datastoreService.getEntityType('ProcessToken');
            return processTokenType.createEntity(context);
        }
        mergeTokenHistory(processToken, tokenWithHistoryToMerge) {
            const gatewayToken = processToken;
            if (gatewayToken.data === undefined) {
                gatewayToken.data = {};
            }
            if (gatewayToken.data.history === undefined) {
                gatewayToken.data.history = {};
            }
            gatewayToken.data.history = Object.assign({}, gatewayToken.data.history, tokenWithHistoryToMerge.data.history);
        }
    }
    exports.ParallelGatewayHandler = ParallelGatewayHandler;
});

//# sourceMappingURL=parallel_gateway_handler.js.map
