package gve.calc.formula;
import java.awt.*; 

public class OperatorUnion extends InfixBinaryOp {
	public String getName() { return "union"; }
	public int getPri() { return 1500; }

	public OperatorUnion(Part l,Part r) {
		super(l,r);
	}

	public Part union(Part a,Part b) {
		if (!(a instanceof Brackets) || !(b instanceof Brackets))
			return new OperatorUnion((Part)a.clone(),(Part)b.clone());
		if (((Brackets)a).getKind()!=Brackets.CURLY || ((Brackets)b).getKind() != Brackets.CURLY)
			return new OperatorUnion((Part)a.clone(),(Part)b.clone());
		Part result = (Part)((Brackets)a).child.clone();
		// Voeg elementen van b erbij
		CommaEnumerator benum = new CommaEnumerator(((Brackets)b).child);
		while (benum.hasMoreElements()) {
			Part el = benum.nextPart();
			if (OperatorSet.in(el,result)) continue;
			// voeg toe
			el = (Part)el.clone();
			if (result == null) result = el;
			else if (result instanceof Identifier && ((Identifier)result).isEmpty())
				result = el;
			else result = new OperatorComma(result,el);
		}
		return result;
	}

	public Part evaluate(Evaluator ev) {
		Part l = Brackets.unbracket(left.evaluate(ev));
		Part r = Brackets.unbracket(right.evaluate(ev));
		if (!(l instanceof Brackets)) return null;
		if (((Brackets)l).getKind() != Brackets.CURLY) return null;
		if (!(r instanceof Brackets)) return null;
		if (((Brackets)r).getKind() != Brackets.CURLY) return null;
		Part result = ((Brackets)l).child;
		Part rset = ((Brackets)r).child;
		CommaEnumerator renum = new CommaEnumerator(rset);
		while (renum.hasMoreElements()) {
			Part element = renum.nextPart();
			if (OperatorSet.in(element,result)) continue;
			// add element to result
			// Important: add element to front of list
			// (new OoperatorComma(element,result) has the priorities bad)
			result = new OperatorComma((Part)element.clone(),result);
		}
		return new Brackets(result,Brackets.CURLY);
	}

	public static Part read(java.io.BufferedReader r) throws java.io.IOException,
			ClassNotFoundException,NoSuchMethodException,
			java.lang.reflect.InvocationTargetException,IllegalAccessException{
		Part left = Part.read(r);
		Part right = Part.read(r);
		return new OperatorUnion(left,right);
	}

	public boolean same(Object o) {
		o = Brackets.unbracket(o);
		if (!(o instanceof OperatorUnion)) return false;
		OperatorUnion obj = (OperatorUnion)o;
		return left.same(obj.left) && right.same(obj.right);
	}

	public Component createView(FormulaView view) {
		return new InfixBinaryOpView(this,view,new OperatorUnionSymbolView(getName()));
	}
}

class OperatorUnionSymbolView extends TextSymbolView {
	public OperatorUnionSymbolView(String txt) { super(txt); }

	public Dimension getSymbolSize() {
		FontMetrics metrics = getFontMetrics(getFont());
		return new Dimension(metrics.charWidth(' ')*2,metrics.getHeight());
	}

	public void paintSymbol(Graphics g) {
		int spatWidth = g.getFontMetrics().charWidth(' ');
		int mBase = g.getFontMetrics().getAscent();
		int opWidth = spatWidth*2;
		// vertical bars of U
		g.drawLine(0,0,0,mBase/2);
		g.drawLine(opWidth-1,0,opWidth-1,mBase/2);
		// half circle
		g.drawArc(0,0,spatWidth*2-1,mBase,180,180);
	}
}