/*
 * Copyright (C) 1999-2006 <a href="mailto:paschke@in.tum.de">Adrian Paschke</a>
 * 
 * The ECA Interpreter is part of the Rule Based Service Level Agreement (RBSLA)
 * framework, available at 
 * <a href=" http://ibis.in.tum.de/staff/paschke/rbsla/index.htm">RBSLA</a>
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package rbsla.eca;

import java.util.HashMap;
import java.util.Map;

import org.mandarax.kernel.ResultSet;



/**
 * Test Event, Condition and trigger Action, with parameters, if necessary.
 * 
 * @author <A HREF="mailto:paschke@in.tum.de">Adrian Paschke</A>
 * @version 0.1 <1 Sept 2005>
 * @since 0.1
 */
public class EventConditionActionExecutor implements Runnable
{
    private ActiveRule rule;
    private ActiveKnowledgeBase akb;
	private ResultSet rst;

    public EventConditionActionExecutor(ActiveKnowledgeBase _akb, ActiveRule _rule, ResultSet rs)
    {
        akb = _akb;
        rule = _rule;		
		rst = rs;
    }
	

		
	private void addVariables(ResultSet rs, Map vars) throws Exception {
		if (rs!=null) {			
			Map new_vars = rs.getResults();						
			vars.putAll(new_vars); // add new variables to vars			
		}
	}
    
	public void run()
    {
    	
    	// parse rule
    	Event ev = rule.getEvent();
    	Condition cond = rule.getCondition();
    	Action act = rule.getAction();
    	Condition postCond = rule.getPostCond();
    	Action elseAct = rule.getElseAction();
		
		Map vars = new HashMap(); // substitution variables
		boolean cut_break=false; // cut
		
		try 
		{
		
		  // test time			
		  if (testResult(rst)) {
			boolean more_times;
			String cachedEvent="";
			do {																
					
				addVariables(rst,vars); // add new variables from time part					
				Event event = (Event) ev.clone(); // clone the event
				event.replace(vars); //	substitute variables in event	
				
				// test event					
				ResultSet rse;
				if (cachedEvent.equals(event.toString())) {
					rse=null; // use cached value
				} else { 
					if (event.toString()!=null) cachedEvent=event.toString();						
					rse=event.evaluate(akb.getKnowledgeBaseWrapper()); // new evaluation					
				}					
				
				if (testResult(rse)) { // event succeeded ?
					boolean more_events;
					String cachedCondition="";
					do {									
						
						addVariables(rse,vars); // add variables from event part														
						Condition condition = (Condition) cond.clone();
						condition.replace(vars); // substitute variables in condition
						
						// test condition							
						ResultSet rsc;							
						if (cachedCondition.equals(condition)) { // use cached condition								
							rsc=null;
						} else {
							if (condition.toString()!=null) cachedCondition=condition.toString();								
							rsc = condition.evaluate(akb.getKnowledgeBaseWrapper());
						}							
						if (testResult(rsc)) {								
							boolean more_conditions;
							do {
								addVariables(rsc,vars);																							
								Action action = (Action) act.clone(); 								
								action.replace(vars); // substitute variables in action									
								
								// test action									
								ResultSet rsa=action.start(akb.getKnowledgeBaseWrapper());
								if (testResult(rsa)) {									
									// cut break ?
									if (postCond.toString()!=null)
									if (postCond.toString().equals("!")) { // cut break
										cut_break=true;
										break;
									}
																				
									boolean more_actions;
									do {													
										addVariables(rsa,vars);																																						
										Condition post = (Condition) postCond.clone(); 
										post.replace(vars); // substitute variables	in postcondition									
	
										// test postcondition										
										ResultSet rsp=post.evaluate(akb.getKnowledgeBaseWrapper());
										if (testResult(rsp)) {
										
											
											// active rule completely executed
											//System.out.println("rule executed");
										
										}
									
										if (cut_break) break;
										if (rsa==null) more_actions=false;
										else more_actions=rsa.next();
										
									} while (more_actions); 																	
								
								}
								
								if (cut_break) break;
								if (rsc==null) more_conditions=false;
								else more_conditions=rsc.next();									
							
							} while (more_conditions); 
						
						}
					
						if (cut_break) break;
						if (rse==null) more_events=false;
						else more_events=rse.next();							
					
					} while (more_events);
				
				} else { // event failed --> else action
					
					//TODO: ELSE Action over Time variables
					
					ResultSet rsel=elseAct.start(akb.getKnowledgeBaseWrapper());
					if (testResult(rsel)) {
						// else action executed
						//System.out.println("else action executed");
					}
				
				}					
				if (cut_break) break;
				if (rst==null) more_times=false;
				else more_times=rst.next();
				
				
				} while (more_times);
		  }
	 
		} catch (Exception e) {
			System.err.println(e);
		}
				
    }

  
	
    
	private boolean testResult(ResultSet rs)
    {		
		if (rs==null) return true;	
		try {						
			if (rs.first()) return true;	
			
		} catch (Exception ex) {			
			return false;
		}
		return false;

    } 
	
  
}