import java.util.Vector;
import com.sun.java.swing.JProgressBar;
import com.symantec.itools.swing.models.StringTableModel;

public class ExpressionList
{
    private ComparableVector expressions;
    private ComparableVector values;
    private JProgressBar pbar;
    
    public void assignValues(ComparableVector vals, JProgressBar p) {
        values = vals;
        pbar = p;
    }
    
	private void incBar() {
	    pbar.setValue(pbar.getValue()+1);
	}
	
	public void findAllExpressions() {
	    try {
	        expressions = (ComparableVector)this.findAllExpressions(this.values);
	    } catch (BadOperatorException b) {
	    } catch (ExpressionException b) {}
	}
	
	private void addElementWithBar(ComparableVector v, Expression e) {
	    v.addElement(e);
	    this.incBar();
	}
	
	private void removeTwoElementsFromHead(Vector v) {
	    v.removeElementAt(0);
	    v.removeElementAt(0);
	}
 
    private ComparableVector findAllExpressions(Vector values) 
                    throws ExpressionException, BadOperatorException {
        ComparableVector answer = new ComparableVector();
        if (values.size() == 1) {
            Rational r = (Rational)values.elementAt(0);
            Expression e = new Expression(r);
            answer.addElement(e);
        } else {
            Vector possibleSplits = splitVector(values);
            removeTwoElementsFromHead(possibleSplits);
            while (possibleSplits.size() > 0) {
                Vector left = (Vector)possibleSplits.elementAt(0);
                Vector right = (Vector)possibleSplits.elementAt(1);
                removeTwoElementsFromHead(possibleSplits);
                ComparableVector subExpressions1 = this.findAllExpressions(left);
                ComparableVector subExpressions2;
                boolean symmetric = identical(left,right);
                
                if (symmetric)
                    subExpressions2 = (ComparableVector)subExpressions1.clone();
                else
                    subExpressions2 = findAllExpressions(right);
                    
                for (int lcv=0;lcv<subExpressions1.size();lcv++) for (int lcv2=0;lcv2<subExpressions2.size();lcv2++) {
                    Expression s1 = (Expression)subExpressions1.elementAt(lcv);
                    Expression s2 = (Expression)subExpressions2.elementAt(lcv2);
                    addElementWithBar(answer,new Expression(s1,ArithOperator.ADD,s2));
                    addElementWithBar(answer,new Expression(s1,ArithOperator.SUB,s2));
                    if (!symmetric) 
                        addElementWithBar(answer,new Expression(s2,ArithOperator.SUB,s1));
                    addElementWithBar(answer,new Expression(s1,ArithOperator.MUL,s2));
                    addElementWithBar(answer,new Expression(s1,ArithOperator.DIV,s2));
                    if (!symmetric) 
                        addElementWithBar(answer,new Expression(s2,ArithOperator.DIV,s1));
                }
            }
        }
        return(answer);        
    }

    private Vector splitVector(Vector values) 
    {
        Vector answer = new Vector();
        if (values.size() == 0) {
            answer.addElement(new Vector(5));
            answer.addElement(new Vector(5));
        } else {
            Vector subVector = (Vector)values.clone();
            subVector.removeElementAt(0);
            Vector subSplit = splitVector(subVector);
            
            while (subSplit.size() > 0) {
                Vector term1 = (Vector)subSplit.elementAt(0);
                Vector term2 = (Vector)subSplit.elementAt(1);
                this.removeTwoElementsFromHead(subSplit);

                term1.insertElementAt(values.elementAt(0), 0);
                answer.addElement(term1.clone());
                term1.removeElementAt(0);
                answer.addElement(term2.clone());
                if (!identical(term1,term2)) {
                    term2.insertElementAt(values.elementAt(0), 0);
                    answer.addElement(term1);
                    answer.addElement(term2);
                }
            }
        }
        return(answer);
    }
/* 
    public void simplifyAllExpressions() {
	    for (int lcv=0;lcv<expressions.size();lcv++) {
	        Expression a = (Expression)expressions.elementAt(lcv);
	        a.simplify();
	        incBar();
	    }
    }
*/    
	private boolean identical(Vector a, Vector b) {
	    if (a.size() != b.size())
	        return(false);
	    else {
	        int lcv;
	        boolean answer = true;
	        for (lcv=0;answer && (lcv < a.size());lcv++)
	            if (!a.elementAt(lcv).equals(b.elementAt(lcv)))
	                answer = false;
            return answer;
	    }
	}
 
    public void sortAllExpressions() {
        ComparableVector.dojb = true;
        expressions.sort();
        ComparableVector.dojb = false;
    }
 
    public void pruneAllExpressions(Rational goal) {
        ComparableVector.dojb = true;
        expressions.prune(goal);
        ComparableVector.dojb = false;
    }
    
    public void fillTableModel(StringTableModel stm) {
        pbar.setMinimum(0);
        pbar.setMaximum(expressions.size());
    	for (int lcv=0;lcv<expressions.size();lcv++) {
	        Expression a = (Expression)expressions.elementAt(lcv);
	        stm.addRow(a.toString()+","+a.getValue().toString());
	        pbar.setValue(lcv);
        }
	    stm.setColumnHeaders("Expressions,Values");
    }
}