/**
 * <copyright>
 * Copyright (c) 2010-2014 Henshin developers. All rights reserved. 
 * This program and the accompanying materials are made available 
 * under the terms of the Eclipse Public License v1.0 which 
 * accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * </copyright>
 */
package org.eclipse.emf.henshin.interpreter.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Stack;

import javax.script.ScriptEngine;

import org.eclipse.emf.henshin.interpreter.ApplicationMonitor;
import org.eclipse.emf.henshin.interpreter.Assignment;
import org.eclipse.emf.henshin.interpreter.EGraph;
import org.eclipse.emf.henshin.interpreter.Engine;
import org.eclipse.emf.henshin.interpreter.InterpreterFactory;
import org.eclipse.emf.henshin.interpreter.RuleApplication;
import org.eclipse.emf.henshin.interpreter.UnitApplication;
import org.eclipse.emf.henshin.model.ConditionalUnit;
import org.eclipse.emf.henshin.model.HenshinPackage;
import org.eclipse.emf.henshin.model.IndependentUnit;
import org.eclipse.emf.henshin.model.IteratedUnit;
import org.eclipse.emf.henshin.model.LoopUnit;
import org.eclipse.emf.henshin.model.Parameter;
import org.eclipse.emf.henshin.model.ParameterKind;
import org.eclipse.emf.henshin.model.ParameterMapping;
import org.eclipse.emf.henshin.model.PriorityUnit;
import org.eclipse.emf.henshin.model.Rule;
import org.eclipse.emf.henshin.model.SequentialUnit;
import org.eclipse.emf.henshin.model.Unit;

/**
 * Default {@link UnitApplication} implementation.
 * 
 * @author Enrico Biermann, Gregor Bonifer, Christian Krause
 */
public class UnitApplicationImpl extends AbstractApplicationImpl {
	
	// Parameter assignments:
	protected Assignment assignment, resultAssignment;
	
	// Applied and undone rules:
	protected final Stack<RuleApplication> appliedRules, undoneRules;
	
	/**
	 * Default constructor.
	 * @param engine Engine to be used.
	 */
	public UnitApplicationImpl(Engine engine) {
		super(engine);
		appliedRules = new Stack<RuleApplication>();
		undoneRules = new Stack<RuleApplication>();
	}

	/**
	 * Convenience constructor.
	 * @param engine Engine to be used.
	 * @param graph Target graph.
	 * @param unit Unit to be used.
	 * @param assignment Assignment.
	 */
	public UnitApplicationImpl(Engine engine, EGraph graph, Unit unit, Assignment assignment) {
		this(engine);
		setEGraph(graph);
		setUnit(unit);
		setAssignment(assignment);
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.eclipse.emf.henshin.interpreter.UnitApplication#execute(org.eclipse.emf.henshin.interpreter.ApplicationMonitor)
	 */
	@Override
	public boolean execute(ApplicationMonitor monitor) {
		if (monitor==null) {
			monitor = InterpreterFactory.INSTANCE.createApplicationMonitor();
		}
		appliedRules.clear();
		undoneRules.clear();
		resultAssignment = (assignment!=null) ? 
				new AssignmentImpl(assignment, true) : 
				new AssignmentImpl(unit, true);
		return doExecute(monitor);
	}

	/*
	 * Do execute a unit. Assumes that the monitor and the result assignment is set.
	 */
	protected boolean doExecute(ApplicationMonitor monitor) {
		if (unit.isActivated()) {
			switch (unit.eClass().getClassifierID()) {
				case HenshinPackage.RULE:
					return executeRule(monitor);
				case HenshinPackage.INDEPENDENT_UNIT:
					return executeIndependentUnit(monitor);
				case HenshinPackage.SEQUENTIAL_UNIT:
					return executeSequentialUnit(monitor);
				case HenshinPackage.CONDITIONAL_UNIT:
					return executeConditionalUnit(monitor);
				case HenshinPackage.PRIORITY_UNIT:
					return executePriorityUnit(monitor);
				case HenshinPackage.ITERATED_UNIT:
					return executeIteratedUnit(monitor);
				case HenshinPackage.LOOP_UNIT:
					return executeLoopUnit(monitor);
				default:
					return false;
			}
		}
		return true;
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.emf.henshin.interpreter.UnitApplication#undo(org.eclipse.emf.henshin.interpreter.ApplicationMonitor)
	 */
	@Override
	public boolean undo(ApplicationMonitor monitor) {
		if (appliedRules.isEmpty()) {
			return true;
		}
		if (monitor==null) {
			monitor = InterpreterFactory.INSTANCE.createApplicationMonitor();
		}
		boolean success = true;
		while (!appliedRules.isEmpty()) {
			RuleApplication ruleApplication = appliedRules.pop();
			if (!ruleApplication.undo(monitor)) {
				success = false;
				break;
			}
			undoneRules.push(ruleApplication);
		}
		monitor.notifyUndo(this, success);
		return success;
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.eclipse.emf.henshin.interpreter.UnitApplication#redo(org.eclipse.emf.henshin.interpreter.ApplicationMonitor)
	 */
	@Override
	public boolean redo(ApplicationMonitor monitor) {
		if (undoneRules.isEmpty()) {
			return true;
		}
		if (monitor==null) {
			monitor = InterpreterFactory.INSTANCE.createApplicationMonitor();
		}
		boolean success = true;
		while (!undoneRules.isEmpty()) {
			RuleApplication ruleApplication = undoneRules.pop();
			if (!ruleApplication.redo(monitor)) {
				success = false;
				break;
			}
			appliedRules.push(ruleApplication);
		}
		monitor.notifyRedo(this, success);
		return success;
	}
	
	/*
	 * Execute a Rule.
	 */
	protected boolean executeRule(ApplicationMonitor monitor) {
		Rule rule = (Rule) unit;
		RuleApplication ruleApp = new RuleApplicationImpl(engine, graph, rule, resultAssignment);
		if (ruleApp.execute(monitor)) {
			resultAssignment = new AssignmentImpl(ruleApp.getResultMatch(), true);
			appliedRules.push(ruleApp);
			return true;  // notification is done in the rule application
		} else {
			return false;
		}
	}

	/*
	 * Execute an IndependentUnit.
	 */
	protected boolean executeIndependentUnit(ApplicationMonitor monitor) {
		IndependentUnit indepUnit = (IndependentUnit) unit;
		List<Unit> subUnits = new ArrayList<Unit>(indepUnit.getSubUnits());
		boolean success = false;
		while (!subUnits.isEmpty()) {
			if (monitor.isCanceled()) {
				if (monitor.isUndo()) undo(monitor);
				break;
			}
			int index = new Random().nextInt(subUnits.size());
			UnitApplicationImpl unitApp = createApplicationFor(subUnits.remove(index));
			if (unitApp.execute(monitor)) {
				updateParameterValues(unitApp);
				appliedRules.addAll(unitApp.appliedRules);
				success = true;
				break;
			}
		}
		monitor.notifyExecute(this, success);
		return success;
	}
	
	/*
	 * Execute a SequentialUnit.
	 */
	protected boolean executeSequentialUnit(ApplicationMonitor monitor) {
		SequentialUnit seqUnit = (SequentialUnit) unit;
		boolean success = false;
		for (Unit subUnit : seqUnit.getSubUnits()) {
			if (monitor.isCanceled()) {
				if (monitor.isUndo()) undo(monitor);
				success = false;
				break;
			}
			UnitApplicationImpl unitApp = createApplicationFor(subUnit);
			if (unitApp.execute(monitor)) {
				success = true;
				updateParameterValues(unitApp);
				appliedRules.addAll(unitApp.appliedRules);
			} else {
				if (seqUnit.isStrict()) {
					success = false;
					if (seqUnit.isRollback()) {
						undo(monitor);
					}
				}
				break;
			}
		}
		if (seqUnit.getSubUnits().isEmpty())
			success = true;
		monitor.notifyExecute(this, success);
		return success;
	}
	
	/*
	 * Execute a ConditionalUnit.
	 */
	protected boolean executeConditionalUnit(ApplicationMonitor monitor) {
		boolean success = false;
		ConditionalUnit condUnit = (ConditionalUnit) unit;
		UnitApplicationImpl ifUnitApp = createApplicationFor(condUnit.getIf());
		if (ifUnitApp.execute(monitor)) {
			updateParameterValues(ifUnitApp);
			appliedRules.addAll(ifUnitApp.appliedRules);
			UnitApplicationImpl thenUnitApp = createApplicationFor(condUnit.getThen());
			success = thenUnitApp.execute(monitor);
			if (success) {
				updateParameterValues(thenUnitApp);
			}
			appliedRules.addAll(thenUnitApp.appliedRules);
		} else {
			if (condUnit.getElse() != null) {
				UnitApplicationImpl elseUnitApp = createApplicationFor(condUnit.getElse());
				success = elseUnitApp.execute(monitor);
				if (success) {
					updateParameterValues(elseUnitApp);
				}
				appliedRules.addAll(elseUnitApp.appliedRules);
			} else {
				success = true;
			}
		}
		if (monitor.isCanceled()) {
			if (monitor.isUndo()) undo(monitor);
			monitor.notifyExecute(this, false);
			return false;
		}
		if (!success) {
			undo(monitor);
		}
		monitor.notifyExecute(this, success);
		return success;
	}
	
	/*
	 * Execute a PriorityUnit.
	 */
	protected boolean executePriorityUnit(ApplicationMonitor monitor) {
		PriorityUnit priUnit = (PriorityUnit) unit;
		boolean success = false;
		for (Unit subUnit : priUnit.getSubUnits()) {
			if (monitor.isCanceled()) {
				if (monitor.isUndo()) undo(monitor);				
				break;
			}
			UnitApplicationImpl unitApp = createApplicationFor(subUnit);
			if (unitApp.execute(monitor)) {
				updateParameterValues(unitApp);
				appliedRules.addAll(unitApp.appliedRules);
				success = true;
				break;
			}
		}
		monitor.notifyExecute(this, success);
		return success;
	}
	
	/*
	 * Execute an IteratedUnit.
	 */
	protected boolean executeIteratedUnit(ApplicationMonitor monitor) {
		IteratedUnit iteratedUnit = (IteratedUnit) unit;
		
		// Determine the number of iterations:
		String itersString = iteratedUnit.getIterations();
		if (itersString==null) {
			return false;
		}
		itersString = itersString.trim();
		int iterations = 0;
		boolean ok = false;
		
		// Constant?
		try {
			iterations = Integer.parseInt(itersString);
			ok = true;
		} catch (NumberFormatException e) {}
		
		// Parameter?
		if (!ok) {
			for (Parameter param : unit.getParameters()) {
				if (itersString.equals(param.getName())) {
					Object v = resultAssignment.getParameterValue(param);
					if (v instanceof Number) {
						iterations = ((Number) v).intValue();
						ok = true;
						break;						
					} else {
						return false;
					}
				}
			}
		}
		
		// We need the script engine...
		if (!ok) {
			try {
				ScriptEngine scriptEngine = engine.getScriptEngine();
				for (Parameter param : unit.getParameters()) {
					scriptEngine.put(param.getName(), resultAssignment.getParameterValue(param));
				}
				Object value = scriptEngine.eval(itersString);
				if (value==null) {
					throw new RuntimeException("Error determining number of iterations for unit '" + iteratedUnit.getName() + "'");
				}
				String valueString = value.toString();
				int index = valueString.indexOf('.');
				if (index==0) {
					valueString = "0";
				} else if (index>0) {
					valueString = valueString.substring(0, index);
				}
				iterations = Integer.parseInt(valueString);
			} catch (Exception e) {
				throw new RuntimeException(e.getMessage());
			}
		}
		
		// Now apply the subunit n times:
		boolean success = false;
		for (int i=0; i<iterations; i++) {
			if (monitor.isCanceled()) {
				if (monitor.isUndo()) undo(monitor);
				success = false;
				break;
			}
			UnitApplicationImpl unitApp = createApplicationFor(iteratedUnit.getSubUnit());
			if (unitApp.execute(monitor)) {
				success = true;
				updateParameterValues(unitApp);
				appliedRules.addAll(unitApp.appliedRules);
			} else {
				if (iteratedUnit.isStrict()) {
					success = false;
					if (iteratedUnit.isRollback()) {
						undo(monitor);
					}
				}
				break;
			}
		}
		monitor.notifyExecute(this, success);
		return success;
	}

	/*
	 * Execute a LoopUnit.
	 */
	protected boolean executeLoopUnit(ApplicationMonitor monitor) {
		LoopUnit loopUnit = (LoopUnit) unit;
		boolean success = true;
		while (true) {
			if (monitor.isCanceled()) {
				if (monitor.isUndo()) undo(monitor);
				success = false;
				break;
			}
			UnitApplicationImpl unitApp = createApplicationFor(loopUnit.getSubUnit());
			if (unitApp.execute(monitor)) {
				updateParameterValues(unitApp);
				appliedRules.addAll(unitApp.appliedRules);
			} else {
				break;
			}
		}
		monitor.notifyExecute(this, success);
		return success;
	}

	/*
	 * Create an ApplicationUnit for a given Unit.
	 */
	protected UnitApplicationImpl createApplicationFor(Unit subUnit) {
		if (resultAssignment==null) {
			resultAssignment = new AssignmentImpl(unit);
		}
		Assignment assign = new AssignmentImpl(subUnit);
		for (ParameterMapping mapping : unit.getParameterMappings()) {
			Parameter source = mapping.getSource();
			Parameter target = mapping.getTarget();
			if (target.getUnit()==subUnit) {
				assign.setParameterValue(target, resultAssignment.getParameterValue(source));
			}
		}
		return new UnitApplicationImpl(engine, graph, subUnit, assign);
	}
	
	/*
	 * Update the parameter values.
	 */
	protected void updateParameterValues(UnitApplicationImpl subUnitApp) {
		if (resultAssignment==null) {
			resultAssignment = new AssignmentImpl(unit);
		}
		for (ParameterMapping mapping : unit.getParameterMappings()) {
			Parameter source = mapping.getSource();
			Parameter target = mapping.getTarget();
			if (source.getUnit()==subUnitApp.getUnit()) {
				Parameter param = subUnitApp.getUnit().getParameter(source.getName());
				if (param!=null) {
					Object value = subUnitApp.getResultAssignment().getParameterValue(param);
					if (value!=null) {
						resultAssignment.setParameterValue(target, value);
					}
				}
			}
		}
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.eclipse.emf.henshin.interpreter.UnitApplication#getAssignment()
	 */
	@Override
	public Assignment getAssignment() {
		return assignment;
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.emf.henshin.interpreter.UnitApplication#setAssignment(org.eclipse.emf.henshin.interpreter.Assignment)
	 */
	@Override
	public void setAssignment(Assignment assignment) {
		this.assignment = assignment;
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.emf.henshin.interpreter.UnitApplication#getResultAssignment()
	 */
	@Override
	public Assignment getResultAssignment() {
		return resultAssignment;
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.emf.henshin.interpreter.UnitApplication#getParameterValue(java.lang.String)
	 */
	@Override
	public Object getResultParameterValue(String paramName) {
		if (unit==null) {
			throw new RuntimeException("Transformation unit not set");
		}
		Parameter param = unit.getParameter(paramName);
		if (param==null) {
			throw new RuntimeException("No parameter \"" + paramName + "\" in transformation unit \"" + unit.getName() + "\" found" );
		}
		if (resultAssignment!=null) {
			return resultAssignment.getParameterValue(param);
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.emf.henshin.interpreter.UnitApplication#setParameterValue(java.lang.String, java.lang.Object)
	 */
	@Override
	public void setParameterValue(String paramName, Object value) {
		if (unit==null) {
			throw new RuntimeException("Unit not set");
		}
		Parameter param = unit.getParameter(paramName);
		if (param==null) {
			throw new RuntimeException("No parameter \"" + paramName + "\" in unit \"" + unit.getName() + "\" found" );
		}
		ParameterKind paramKind = param.getKind();
		if (paramKind == ParameterKind.OUT || paramKind == ParameterKind.VAR) {
			throw new RuntimeException(paramKind.getAlias() + " parameter \"" + paramName + "\" may not be set before the execution of u \"" + unit.getName() + "\"");
		}
		if (assignment==null) {
			assignment = new AssignmentImpl(unit);
		}
		assignment.setParameterValue(param, value);
	}
	
	/**
	 * Get the applied rules of this unit application.
	 * @return List of applied rules.
	 */
	public List<RuleApplication> getAppliedRules() {
		return new ArrayList<RuleApplication>(appliedRules);
	}

	/**
	 * Get the undone rules of this unit application.
	 * @return List of undone rules.
	 */
	public List<RuleApplication> getUndoneRules() {
		return new ArrayList<RuleApplication>(undoneRules);
	}
	
}
