/*
 * EquationsManager.java
 *
 * Created on Ketvirtadienis, 2007, Sausio 25, 17.22
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package Main.parser;

import java.util.*;
import Main.*;
import Main.panels.*;
import java.io.*;
import Main.parser.jccparser.*;


public class EquationsManager
{
	public final static String U_EQUATION= "U_EQUATION";
	public final static String V_EQUATION= "V_EQUATION";
	
	private List mEquationU;
	private List mEquationV;
	
	private EquationParser mParser= new EquationParser(new StringReader(""));
	
	private static EquationsManager mManager;
	
	
	private EquationsManager()
	{
	}
	
	public static EquationsManager getInstance()
	{
		if(mManager == null)
		{
			mManager= new EquationsManager();
		}
		return mManager;
	}
	
	public void parseText(String test, String id)
	{
		List tempList= new ArrayList();
		StringTokenizer line= new StringTokenizer(test,"\n",false);
		
		for(;line.hasMoreTokens();)
		{
			String tmp= line.nextToken();
			mParser.ReInit(new StringReader(tmp));
			try{
				AbstractEquationElement element= mParser.Start();
				tempList.add(element);
				System.err.println( "Equation: "+id+" "+element.toString() );
				//MainWindow.getInstance().getOutputStreamPanel().logn(element.toString());
			}
			catch(Exception e)
			{
				MainWindow.getInstance().getOutputStreamPanel().logn("Error occured on parsing "+id+": "+e.getMessage());
				e.printStackTrace();
				return;
			}
		}
		
		if(id.equals(U_EQUATION))
		{
			mEquationU= tempList;
		}
		else
		{
			mEquationV= tempList;
		}
		
	}
	
	public void replaceValues(String name, double value, String id)
	{
		if(id.equals(U_EQUATION))
		{
			replaceValues(name, value, mEquationU);
		}
		else if(id.equals(V_EQUATION))
		{
			replaceValues(name, value, mEquationV);
		}
	}
	
	private void replaceValues(String name, double value, List list)
	{
		for(Iterator it= list.iterator(); it.hasNext();)
		{
			AbstractEquationElement el= (AbstractEquationElement)it.next();
			changeValue(el, name, value);
			if(el.getConstraint() != null)
			{
				if(el.getConstraint() instanceof InequalitySystem)
				{
					for(Iterator it2= ((InequalitySystem)el.getConstraint()).getSystem().iterator(); it2.hasNext();)
					{
						changeValue((AbstractEquationElement)it2.next(), name, value);
					}
				}
				else
				{
					changeValue(el.getConstraint(), name, value);
				}
			}
			
		}
	}
	
	private void changeValue(AbstractEquationElement element, String name, double value)
	{
		if(element instanceof EquationElement)
		{
			if(((EquationElement)element).mName.equals(name))
			{
				((EquationElement)element).mValue= value;
			}
		}
		else if(element instanceof EquationAction)
		{
			changeValue(((EquationAction)element).getFirst(), name, value);
			changeValue(((EquationAction)element).getSecond(), name, value);
		}
	}
	
	public double calculate(String id)
	{
		AbstractEquationElement element= null;
		
		if(id.equals(U_EQUATION))
		{
			element= getEquationByConstraint(mEquationU);
		    if(element == null)
				throw new ArithmeticException("Equation system U is incorrect");
		}
		else if(id.equals(V_EQUATION))
		{
			element= getEquationByConstraint(mEquationV);
		    if(element == null)
				throw new ArithmeticException("Equation system V is incorrect");
		}
		
		
		return element.calculate();
	}
	
	private AbstractEquationElement getEquationByConstraint(List equations)
	{
		for(Iterator it= equations.iterator(); it.hasNext();)
		{
			AbstractEquationElement element= (AbstractEquationElement)it.next();

		    if(element.getConstraint() == null || element.getConstraint().isSatisfied())
			{
				return element;
			}
		}
		return null;
	}
	
}

