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.varModel.DecisionVariableDeclaration;
import de.uni_hildesheim.sse.model.varModel.datatypes.Enum;
import de.uni_hildesheim.sse.model.varModel.datatypes.OclKeyWords;
import de.uni_hildesheim.sse.trans.in.AbstractReader;
import de.uni_hildesheim.sse.trans.in.ParserException;

/**
 * Represents a condition read from a "ItemSelects" line in a .rsf file. <br />
 * The format looks like this: <br />
 * <code>
 * ItemSelects <i>variable</i> <i>selectedVaraible</i> <i>condition</i>
 * </code> <br />
 * <i>selectedVaraible</i> has to be set to true, if <i>variable</i> and <i>condition</i> are true. <br />
 * {@link RSFItemSelectsCondition#getPureBooleanConstraintSyntaxTree(AbstractReader, String, String)} will convert it
 * to: <br />
 * <code>
 * NOT <i>variable</i> OR NOT <i>condition</i> OR <i>selectedVaraible</i>
 * </code> <br />
 * or, if condition is "y", to: <br />
 * <code>
 * NOT <i>variable</i> OR <i>selectedVaraible</i>
 * </code> <br />
 * @author Adam Krafczyk
 */
class RSFItemSelectsCondition extends RSFCondition {

    private String variable;
    private String selectedVariable;
    private String condition;
    
    /**
     * Creates a condition with the given variable and condition as read from a "ItemSelects" line in a .rsf file.
     * @param variable The name of the variable
     * @param selectedVaraible The name of the variable that is selected
     * @param condition The condition as read from the .rsf file
     */
    RSFItemSelectsCondition(String variable, String selectedVaraible, String condition) {
        this.variable = variable;
        this.selectedVariable = selectedVaraible;
        // TODO error handling if only one is true?
        if (this.selectedVariable.startsWith("\"") && this.selectedVariable.endsWith("\"")) {
            this.selectedVariable = this.selectedVariable.substring(1, this.selectedVariable.length() - 1);
        }
        this.condition = condition;
        // TODO error handling if only one is true?
        if (this.condition.startsWith("\"") && this.condition.endsWith("\"")) {
            this.condition = this.condition.substring(1, this.condition.length() - 1);
        }
    }
    
    @Override
    List<ConstraintSyntaxTree> toPureBooleanConstraintSyntaxTree(RSFReader reader) throws ParserException {
        DecisionVariableDeclaration varDecl = reader.getVariable(variable);
        Variable var = varPool.obtainVariable(varDecl);
        OCLFeatureCall notVar = new OCLFeatureCall(var, OclKeyWords.NOT);
        
        DecisionVariableDeclaration selectedVarDecl = reader.getVariable(selectedVariable);
        Variable selectedVar = varPool.obtainVariable(selectedVarDecl);
        
        ConstraintSyntaxTree condition = getPureBooleanConstraintSyntaxTree(reader, this.condition, variable);
        
        ConstraintSyntaxTree result = null;
        
        if (condition != null) {
            ConstraintSyntaxTree notCondition = new OCLFeatureCall(condition, OclKeyWords.NOT);
            result = new OCLFeatureCall(notCondition, OclKeyWords.OR, selectedVar);
            result = new OCLFeatureCall(notVar, OclKeyWords.OR, result);
        } else {
            result = new OCLFeatureCall(notVar, OclKeyWords.OR, selectedVar);
        }
        
        List<ConstraintSyntaxTree> list  = new ArrayList<ConstraintSyntaxTree>();
        list.add(result);
        return list;
    }
    
    @Override
    ConstraintSyntaxTree toNotBooleanConstraintSyntaxTree(AbstractReader reader, Enum tristate) throws ParserException {
        // TODO implement
        return null;
    }
    
}
