package de.uni_hildesheim.sse.trans.in.rsf;

import java.util.ArrayList;
import java.util.List;

import de.uni_hildesheim.sse.model.cst.ConstraintSyntaxTree;
import de.uni_hildesheim.sse.model.cst.OCLFeatureCall;
import de.uni_hildesheim.sse.model.cst.Variable;
import de.uni_hildesheim.sse.model.cst.VariablePool;
import de.uni_hildesheim.sse.model.varModel.datatypes.OclKeyWords;
import de.uni_hildesheim.sse.trans.in.AbstractReader;

/**
 * Contains a Choice and the ChoiceItems.
 * 
 * @author Adam Krafczyk
 */
class RSFChoice {

    private static VariablePool varPool = new VariablePool();
    
    private String choiceName;
    private List<String> choiceItems;
    
    /**
     * Creates a new Choice with no ChoiceItems.
     * @param choiceName The name of the Choice.
     */
    RSFChoice(String choiceName) {
        this.choiceName = choiceName;
        choiceItems = new ArrayList<String>();
    }
    
    /**
     * Adds a ChoiceItem to the Choice.
     * @param name The name of the ChoiceItem.
     */
    void addChoiceItem(String name) {
        choiceItems.add(name);
    }
    
    /**
     * Creates a {@link ConstraintSyntaxTree}s to assure that only one ChoiceItem is selected.
     * @param reader A reader to get variable declarations from.
     * @return An array of {@link ConstraintSyntaxTree}s.
     */
    List<ConstraintSyntaxTree> getBooleanConstraintSyntaxTree(AbstractReader reader) {
        //ConstraintSyntaxTree[] trees = new ConstraintSyntaxTree[choiceItems.size()];
        List<ConstraintSyntaxTree> trees = new ArrayList<ConstraintSyntaxTree>();
        Variable choiceVar = varPool.obtainVariable(reader.getVariable(choiceName));
        OCLFeatureCall notChoiceVar = new OCLFeatureCall(choiceVar, OclKeyWords.NOT);
        
        // Create one tree with all variables OR'd together
        ConstraintSyntaxTree allItemsTree = notChoiceVar;
        
        // And for each unique combination of choiceItems:
        for (int i = 0; i < choiceItems.size(); i++) {
            Variable var1 = varPool.obtainVariable(reader.getVariable(choiceItems.get(i)));
            OCLFeatureCall notVar1 = new OCLFeatureCall(var1, OclKeyWords.NOT);
            for (int j = i + 1; j < choiceItems.size(); j++) {
                // Add the 2 variables negated and OR'd together:
                Variable var2 = varPool.obtainVariable(reader.getVariable(choiceItems.get(j)));
                OCLFeatureCall notVar2 = new OCLFeatureCall(var2, OclKeyWords.NOT);
                OCLFeatureCall call = new OCLFeatureCall(notVar1, OclKeyWords.OR, notVar2);
                trees.add(new OCLFeatureCall(notChoiceVar, OclKeyWords.OR, call));
            }
            
            allItemsTree = new OCLFeatureCall(allItemsTree, OclKeyWords.OR, var1);
        }
        
        trees.add(allItemsTree);
        
        return trees;
    }
    
}
