/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ruleengine;

import CommonFunctions.debugPrinter;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import mdot.Main;
import structures.ActionTag;
import structures.ConditionTag;
import structures.Constants;
import structures.HashContext;
import structures.RuleSet;
import structures.Rule;
import userdefined.ActionInterface;
import userdefined.ConditionInterface;

/*class RuleChecker
 * Checks the conditions from the ConditionInterface and if they are satisfied
 * runs the appropriate action.
 */
public class RuleChecker {

    private Hashtable conditions = Main.conditionHash;
    private Hashtable actions = Main.actionHash;
    public RuleSet rules = null;

    public RuleChecker(RuleSet rule) {
        rules = rule;
    }

    public void CheckRules() {
        try {

            Vector ruleVector = rules.getRuleSetVector();
            Vector resultVector = null;
            Vector tmpVector = null;
            Vector transVector = null;
            String previousLogicalOperator = "";


//            if (!hashUtil.checkHashChanged()) {
//                debugPrinter.printLine("No change, we shouldn't check the conditions.");
//                return;
//            }

            Enumeration en = ruleVector.elements();
            while (en.hasMoreElements()) {
                debugPrinter.printLine("checking rules !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                Rule tmpRule = (Rule) en.nextElement();
                tmpVector = new Vector();
                transVector = new Vector();
                resultVector = new Vector();
                Vector vectorCondition = tmpRule.getConditionVector();
                previousLogicalOperator = "";
                Enumeration encond = vectorCondition.elements();
                while (encond.hasMoreElements()) {
                    ConditionTag cond = (ConditionTag) encond.nextElement();
                    String functionName = cond.getFunctionName();
                    String logicalOperator = cond.getLogicalOperator();
                    String isNot = cond.getNegation();
                    tmpVector = CallConditions(functionName);
                    if (isNot.equals(Constants.HASH_VALUE_TRUE)) {
                        ClearPresentStatus();
                        transVector = new Vector();
                        Enumeration enCon = tmpVector.elements();
                        while (enCon.hasMoreElements()) {
                            HashContext tmpCon = (HashContext) enCon.nextElement();

                            HashContext tmpHashContext = (HashContext) Main.getContext().get(tmpCon.GetObjectAsString(Constants.HASH_ID));
                            if (tmpHashContext != null) {
                                tmpHashContext.setObjectAsString(Constants.HASH_PRESENT, Constants.HASH_VALUE_TRUE);
                            }
                        }
                        transVector = new Vector();
                        Enumeration enCon1 = Main.getContext().elements();
                        while (enCon1.hasMoreElements()) {
                            HashContext tmpCon1 = (HashContext) enCon1.nextElement();
                            if (!tmpCon1.ContainsKey(Constants.HASH_PRESENT)) {
                                transVector.addElement(tmpCon1);
                            }
                        }
                        tmpVector = transVector;
                        ClearPresentStatus();
                    }

                    if (previousLogicalOperator.equals("")) {
                        resultVector = tmpVector;
                    } else if (previousLogicalOperator.equals(Constants.LOGICAL_AND)) {
                        ClearPresentStatus();
                        transVector = new Vector();
                        Enumeration enCon = resultVector.elements();
                        while (enCon.hasMoreElements()) {
                            HashContext tmpCon = (HashContext) enCon.nextElement();
                            Enumeration enCon1 = tmpVector.elements();
                            Hashtable tmpHash = null;
                            while (enCon1.hasMoreElements()) {
                                HashContext tmpCon1 = (HashContext) enCon1.nextElement();
                                if ((tmpCon1.GetObjectAsString(Constants.HASH_ID)).equals(tmpCon.GetObjectAsString(Constants.HASH_ID))) {
                                    transVector.addElement(tmpCon1);
                                }
                            }
                        }
                        resultVector = transVector;
                        ClearPresentStatus();
                    } else if (previousLogicalOperator.equals(Constants.LOGICAL_OR)) {
                        ClearPresentStatus();
                        transVector = new Vector();
                        Enumeration enCon = resultVector.elements();
                        while (enCon.hasMoreElements()) {
                            HashContext tmpCon = (HashContext) enCon.nextElement();
                            Enumeration enCon1 = tmpVector.elements();
                            while (enCon1.hasMoreElements()) {
                                HashContext tmpCon1 = (HashContext) enCon1.nextElement();
                                tmpCon1.removeObject(Constants.HASH_PRESENT);
                                if ((tmpCon1.GetObjectAsString(Constants.HASH_ID)).equals(tmpCon.GetObjectAsString(Constants.HASH_ID))) {
                                    tmpCon1.setObjectAsString(Constants.HASH_PRESENT, Constants.HASH_VALUE_TRUE);
                                }
                            }

                        }
                        Enumeration enCon1 = tmpVector.elements();
                        while (enCon1.hasMoreElements()) {
                            HashContext tmpCon1 = (HashContext) enCon1.nextElement();
                            if (!tmpCon1.ContainsKey(Constants.HASH_PRESENT)) {
                                resultVector.addElement(tmpCon1);
                            }
                        }
                        ClearPresentStatus();
                    }
                    if (logicalOperator.equals("")) {
                        break;
                    } else {
                        previousLogicalOperator = logicalOperator;
                    }

                }
                Vector vectorAction = tmpRule.getActionVector();
                Enumeration enAction = vectorAction.elements();
                while (enAction.hasMoreElements()) {
                    ActionTag tmpAct = (ActionTag) enAction.nextElement();
                    String functionName = tmpAct.getFunctionName();
                    Enumeration enResult = resultVector.elements();
                    while (enResult.hasMoreElements()) {
                        HashContext tmpResult = (HashContext) enResult.nextElement();
                        CallActions(functionName, tmpResult);
                    }
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public Vector CallConditions(String functionName) {
        Vector tmpVector = null;
        ConditionInterface con = (ConditionInterface) conditions.get(functionName);
        tmpVector = con.CheckCondition(Main.getContext(), Main.getMe());
        return tmpVector;
    }

    public void CallActions(String functionName, HashContext tmp) {
        ActionInterface act = (ActionInterface) actions.get(functionName);
        act.doWork(tmp);
    }

    public void ClearPresentStatus() {
        Enumeration enCon = Main.getContext().elements();
        while (enCon.hasMoreElements()) {
            HashContext tmpCon = (HashContext) enCon.nextElement();
            tmpCon.removeObject(Constants.HASH_PRESENT);
        }
    }
}
