package gleichung;

/**
 * 
 * 
 * @author Christian Semrau
 * <a href="mailto:Christian.Semrau@student.uni-magdeburg.de">
 * Christian.Semrau@student.uni-magdeburg.de</a>
 */
public class GleichungBaum {
	static int calcs = 0;
	static int creates = 0;

	private int val;
	private int op;
	private int eval;
	private boolean calced;
	private GleichungBaum left, right;

	// diese vier Werte duerfen nicht veraendert werden
	// wegen nextComb_mWmR() in GleichungValues.calculate()
	static final int OP_ADD = 0;
	static final int OP_SUB = 1;
	static final int OP_MUL = 2;
	static final int OP_DIV = 3;

	static final int OP_NUL = 10;
/**
 * Baum constructor comment.
 */
public GleichungBaum(int v, int o, GleichungBaum l, GleichungBaum r) {
	val = v;
	op = (o<OP_ADD || o>OP_DIV) ? OP_NUL : o;
	eval = -1;
	left = l;
	right = r;
	calced = (left==null||right==null||op==OP_NUL);
	creates++;
}
/**
 * 
 * @return int
 */
public int calc() {
	if (calced||left==null||right==null||op==OP_NUL)
		return val;
	else{
		calcs++;
		val = verkn(left.calc(), right.calc());
		calced = true;
		return val;
	}
}
/**
 * 
 * @return int
 */
public int evaluate() {
	if (eval>=0) return eval;
	int v;
	switch(op){
		case OP_ADD: v = 2;
		case OP_SUB: v = 10;
		case OP_MUL: v = 4;
		case OP_DIV: v = 11;
		default: v = 0;
	}
	if (left==null||right==null)
		return eval=v;
	else
		return eval=(v+left.evaluate()+right.evaluate());
}
/**
 * 
 * @return boolean
 * @param t1 int
 * @param t2 int
 */
public boolean klammern(int t1, int t2, boolean left) {
	if (t2==OP_NUL)
		return false;

//	if (true)
//	return true;

	if (t1==OP_ADD){
		return false;
	}

	if (t1==OP_SUB){
		if (left)
			return false;
		else
			return (t2==OP_ADD || t2==OP_SUB);
	}

	if (t1==OP_MUL){
		return (t2!=OP_MUL);
	}

	return true;
}
/**
 * 
 * @return java.lang.String
 */
public static String opString(int o) {
	switch (o){
		case OP_ADD: return "+";
		case OP_SUB: return "-";
		case OP_MUL: return "*";
		case OP_DIV: return "/";
		case OP_NUL: return "";
		default: return "?";
	};
}
/**
 * 
 * @return java.lang.String
 */
public String toString() {
	String s = "";
	if (left!=null){
		if (klammern(op, left.op, true))
			s+="(";
		s+=left.toString();
		if (klammern(op, left.op, true))
			s+=")";
	}
	if (left==null&&right==null)
		s+=val;
	else
		if (op==OP_NUL)
			s+="#";
		else
			s+=opString(op);
	if (right!=null){
		if (klammern(op, right.op, false))
			s+="(";
		s+=right.toString();
		if (klammern(op, right.op, false))
			s+=")";
	}
	return s;
}
/**
 * 
 * @return int
 * @param X1 int
 * @param X2 int
 */
public int verkn(int X1, int X2) throws ArithmeticException {
	switch(op){
		case OP_ADD: return X1+X2;
		case OP_SUB: return X1-X2;
		case OP_MUL: return X1*X2;
		case OP_DIV: if (X2==0) throw new ArithmeticException("DIV by zero"); else return X1/X2;
		case OP_NUL: return X1;
		default: return 0;
	}
}
}