package ua.be.wee.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Component;

import ua.be.wee.model.nodes.Node;
import ua.be.wee.model.pt.PT;


@Component
public class ExecutionFlowManager {
	    private final Map<String, List<Token>> activeTokensMap = new HashMap<>();

	    // Initialize execution flow
	    public Token createExecutionFlow(PT processTrace, Node startNode, String branchId, String invokingActivityName) {
	        Token token = new Token(startNode, processTrace, branchId, invokingActivityName);
	        activeTokensMap.computeIfAbsent(processTrace.getIri(), k -> new ArrayList<>()).add(token);
	        return token;
	    }


	    // Get active tokens for a trace
	    public List<Token> getActiveTokens(String traceIri) {
	        return activeTokensMap.getOrDefault(traceIri, new ArrayList<>());
	    }

	    // Remove token (when process ends or token finishes)
	    public void removeToken(String traceIri, String tokenId) {
	        List<Token> tokens = activeTokensMap.get(traceIri);
	        if (tokens != null) {
	            tokens.removeIf(token -> token.getId().equals(tokenId));
	            if (tokens.isEmpty()) {
	                activeTokensMap.remove(traceIri);
	            }
	        }
	    }
	    
	    public void addToken(String traceIri, Token token) {
	        activeTokensMap.computeIfAbsent(traceIri, k -> new ArrayList<>()).add(token);
	    }


	    // Fork: creates new tokens from a parent token
	    public Token forkToken(String traceIri, Token parentToken, Node nextNode) {
	        Token newToken = new Token(
	            nextNode,
	            parentToken.getProcessTrace(),
	            parentToken.getBranchId(),
	            parentToken.getInvokingActivityName()
	        );
	        getActiveTokens(traceIri).add(newToken);
	        return newToken;
	    }


	    // Update current node of a token
	    public void updateTokenCurrentNode(Token token, Node nextNode) {
	        token.setCurrentNode(nextNode);
	    }

	    public void clearTokensForTrace(String traceIri) {
	        activeTokensMap.remove(traceIri);
	    }
	    
	    public void terminateAllFlowsForTrace(String traceIri) {
	        List<Token> tokens = activeTokensMap.get(traceIri);
	        if (tokens != null) {
	            for (Token token : tokens) {
	                token.terminate();
	            }
	            activeTokensMap.remove(traceIri);
	        }
	    }
}
