/*******************************************************************************
 * Copyright (c) 2011 University of Illinois 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 
 * 	
 * Contributors: 
 * 	Albert L. Rossi - design and implementation
 ******************************************************************************/
package org.eclipse.ptp.rm.jaxb.core.data.impl;

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

import org.eclipse.ptp.rm.jaxb.core.IAssign;
import org.eclipse.ptp.rm.jaxb.core.IJAXBNonNLSConstants;
import org.eclipse.ptp.rm.jaxb.core.data.TestType;
import org.eclipse.ptp.rm.jaxb.core.data.TestType.Else;
import org.eclipse.ptp.rm.jaxb.core.messages.Messages;
import org.eclipse.ptp.rm.jaxb.core.utils.CoreExceptionUtils;

/**
 * Wrapper implementation. A test consists of an if/else condition to be checked
 * in relation to the passed in values, plus a set of assignment actions to take
 * in the case of success. The values can be constants, references to be
 * resolved, or the current value of the target field (indicated by
 * "#fieldName").<br>
 * <br>
 * There are 8 allowable operators, indicated by the following strings: <br>
 * <br>
 * COMPARISON:<br>
 * EQ (=)<br>
 * LT (<)<br>
 * LE (<=)<br>
 * GT (>)<br>
 * GE (>=)<br>
 * <br>
 * LOGICAL:<br>
 * AND<br>
 * OR<br>
 * NOT<br>
 * <br>
 * In the case of a logical operator, the Test will delegate to its embedded
 * Test children, and then apply the operator to the results.<br>
 * <br>
 * To indicate an alternative action in the case the test fails, "<else>" is
 * used.
 * 
 * @author arossi
 * 
 */
public class TestImpl implements IJAXBNonNLSConstants {

	private static final short sEQ = 0;
	private static final short sLT = 1;
	private static final short sGT = 2;
	private static final short sLE = 3;
	private static final short sGE = 4;
	private static final short sAND = 5;
	private static final short sOR = 6;
	private static final short sNOT = 7;

	private final String uuid;
	private final short op;
	private final List<String> values;
	private List<TestImpl> children;
	private List<IAssign> ifcond;
	private List<IAssign> elsecond;

	private Object target;

	/**
	 * @param uuid
	 *            unique id associated with this resource manager operation (can
	 *            be <code>null</code>).
	 * @param test
	 *            JAXB data element
	 */
	public TestImpl(String uuid, TestType test) {
		this.uuid = uuid;
		op = getOp(test.getOp());
		values = test.getValue();
		List<TestType> tests = test.getTest();
		if (!tests.isEmpty()) {
			children = new ArrayList<TestImpl>();
			for (TestType t : tests) {
				children.add(new TestImpl(uuid, t));
			}
		}

		List<Object> listif = test.getAddOrAppendOrPut();
		if (!listif.isEmpty()) {
			ifcond = new ArrayList<IAssign>();
			for (Object o : listif) {
				AbstractAssign.add(uuid, o, ifcond);
			}
		}

		Else listelse = test.getElse();
		if (listelse != null) {
			elsecond = new ArrayList<IAssign>();
			for (Object o : listelse.getAddOrAppendOrPut()) {
				AbstractAssign.add(uuid, o, elsecond);
			}
		}
	}

	/**
	 * Applies the test.
	 * 
	 * @return whether the test succeeded or not.
	 * @throws Throwable
	 */
	public boolean doTest() throws Throwable {
		boolean result = false;
		validate(op);
		switch (op) {
		case sEQ:
			result = evaluateEquals(values.get(0), values.get(1));
			break;
		case sLT:
			result = evaluateLessThan(values.get(0), values.get(1));
			break;
		case sGT:
			result = evaluateLessThan(values.get(1), values.get(0));
			break;
		case sLE:
			result = evaluateLessThanOrEquals(values.get(0), values.get(1));
			break;
		case sGE:
			result = evaluateLessThanOrEquals(values.get(1), values.get(0));
			break;
		case sNOT:
			return !children.get(0).doTest();
		case sAND:
			result = true;
			for (TestImpl t : children) {
				result = result && t.doTest();
				if (!result) {
					break;
				}
			}
			break;
		case sOR:
			result = false;
			for (TestImpl t : children) {
				result = result || t.doTest();
				if (result) {
					break;
				}
			}
			break;
		}

		if (target != null) {
			if (result) {
				doAssign(ifcond);
			} else {
				doAssign(elsecond);
			}
		}
		return result;
	}

	/**
	 * The parent target to which to apply the actions associated with the test
	 * in case of success.
	 * 
	 * @param target
	 */
	public void setTarget(Object target) {
		this.target = target;
		if (children != null) {
			for (TestImpl t : children) {
				t.setTarget(target);
			}
		}
	}

	/**
	 * Applies the assignments to the target.
	 * 
	 * @param assign
	 *            list of assignment actions.
	 * @throws Throwable
	 */
	private void doAssign(List<IAssign> assign) throws Throwable {
		if (assign != null) {
			for (IAssign a : assign) {
				a.setTarget(target);
				/*
				 * These will be using only preassigned values, so the tokens[]
				 * param is null
				 */
				a.assign(null);
			}
		}
	}

	/**
	 * Auxiliary. Applies <code>compareTo</code> to <code>Comparable</code>
	 * objects. Strings are first converted to boolean or integers if
	 * appropriate.
	 * 
	 * @param string1
	 *            to be compared
	 * @param string2
	 *            to be compared
	 * @return -1,0 or 1
	 * @throws Throwable
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private int evaluateComparable(String string1, String string2) throws Throwable {
		Object value1 = AbstractAssign.normalizedValue(target, uuid, string1, true);
		Object value2 = AbstractAssign.normalizedValue(target, uuid, string2, true);
		if (value1 == null || value2 == null) {
			return 1;
		}
		if (!(value1 instanceof Comparable) || !(value2 instanceof Comparable)) {
			return 1;
		}
		Comparable c1 = (Comparable) value1;
		Comparable c2 = (Comparable) value2;
		return c1.compareTo(c2);
	}

	/**
	 * Applies <code>equals</code> to objects. Strings are first converted to
	 * boolean or integers if appropriate.
	 * 
	 * @param string1
	 *            to be compared
	 * @param string2
	 *            to be compared
	 * @return whether the two values are equal
	 * @throws Throwable
	 */
	private boolean evaluateEquals(String string1, String string2) throws Throwable {
		Object value1 = AbstractAssign.normalizedValue(target, uuid, string1, true);
		Object value2 = AbstractAssign.normalizedValue(target, uuid, string2, true);
		if (value1 == null) {
			return value2 == null;
		}
		return value1.equals(value2);
	}

	/**
	 * Delegates to {@link #evaluateComparable(String, String)}
	 * 
	 * @param string1
	 *            to be compared
	 * @param string2
	 *            to be compared
	 * @return true if {@link #evaluateComparable(String, String)} returns -1.
	 * @throws Throwable
	 */
	private boolean evaluateLessThan(String string1, String string2) throws Throwable {
		return evaluateComparable(string1, string2) < 0;
	}

	/**
	 * Delegates to {@link #evaluateComparable(String, String)}
	 * 
	 * @param string1
	 *            to be compared
	 * @param string2
	 *            to be compared
	 * @return true if {@link #evaluateComparable(String, String)} returns -1 or
	 *         0.
	 * @throws Throwable
	 */
	private boolean evaluateLessThanOrEquals(String string1, String string2) throws Throwable {
		return evaluateComparable(string1, string2) <= 0;
	}

	/**
	 * Translates operator to string equivalent.
	 * 
	 * @param op
	 * @return string equivalent
	 */
	private String getOp(short op) {
		if (sEQ == op) {
			return xEQ;
		}
		if (sLT == op) {
			return xLT;
		}
		if (sGT == op) {
			return xGT;
		}
		if (sLE == op) {
			return xLE;
		}
		if (sGE == op) {
			return xGE;
		}
		if (sAND == op) {
			return AND;
		}
		if (sOR == op) {
			return OR;
		}
		if (sNOT == op) {
			return NOT;
		}
		return EQ;
	}

	/**
	 * Translates string representation of operator to numerical value.
	 * 
	 * @param op
	 *            string representation
	 * @return short value
	 */
	private short getOp(String op) {
		if (xEQ.equalsIgnoreCase(op)) {
			return sEQ;
		}
		if (xLT.equalsIgnoreCase(op)) {
			return sLT;
		}
		if (xGT.equalsIgnoreCase(op)) {
			return sGT;
		}
		if (xLE.equalsIgnoreCase(op)) {
			return sLE;
		}
		if (xGE.equalsIgnoreCase(op)) {
			return sGE;
		}
		if (AND.equalsIgnoreCase(op)) {
			return sAND;
		}
		if (OR.equalsIgnoreCase(op)) {
			return sOR;
		}
		if (NOT.equalsIgnoreCase(op)) {
			return sNOT;
		}
		return sEQ;
	}

	/**
	 * Checks that the number of values matches the operator.
	 * 
	 * @param op
	 * @throws Throwable
	 *             if number of values is incorrect
	 */
	private void validate(short op) throws Throwable {
		switch (op) {
		case sEQ:
		case sLT:
		case sGT:
		case sLE:
		case sGE:
			if (values == null || values.size() != 2) {
				throw CoreExceptionUtils.newException(Messages.MalformedExpressionError + getOp(op), null);
			}
			break;
		case sNOT:
			if (children == null || children.size() != 1) {
				throw CoreExceptionUtils.newException(Messages.MalformedExpressionError + getOp(op), null);
			}
			break;
		case sAND:
		case sOR:
			if (children == null || children.size() <= 1) {
				throw CoreExceptionUtils.newException(Messages.MalformedExpressionError + getOp(op), null);
			}
			break;
		}
	}
}
