using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace FormulaEditor
{
	/// <summary>
	/// Elementary object detector
	/// </summary>
	public class ElementaryObjectDetector : ElementaryRealDetector
	{
		/// <summary>
		/// Table of variable types
		/// </summary>
		private Hashtable table;

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="table">Table of variable types</param>
		public ElementaryObjectDetector(Hashtable table)
		{
			this.table = table;
		}

		/// <summary>
		/// Detects operation
		/// </summary>
		/// <param name="s">First symbol of the formula</param>
		/// <returns>Acceptor of operation</returns>
		public override IOperationAcceptor Detect(MathSymbol s)
		{
			Double a = 0;
			if (s.Symbol == '~')
			{
				return new BitwiseOperation();
			}
			if (s.Symbol == '¬')
			{
				return NegationOperation.Object;
			}
			if (s.Symbol == '-')
			{
				return new ElementaryFunctionOperation('-');
			}
			if (s is SeriesSymbol)
			{
				SeriesSymbol ss = s as SeriesSymbol;
				if (ss.Acceptor is IUnary)
				{
					return new ElementaryUnaryOperation(ss.Acceptor as IUnary, ss.Index);
				}
				return ss.Acceptor;
			}
			if (s is BinaryFunctionSymbol)
			{
				return ElementaryAtan2.Object;
			}
			if (s is RootSymbol)
			{
				return new ElementaryRoot();
			}
			if (s is FractionSymbol)
			{
				return ElementaryFraction.Object;
			}
			if (s is BracketsSymbol)
			{
				return new ElementaryBrackets();
			}
			if (s is SubscriptedSymbol)
			{
				SubscriptedSymbol sym = s as SubscriptedSymbol;
                if (table != null)
                {
                    if (table[sym.Pair].Equals(a))
                    {
                        return new ElementaryRealVariable(sym.Pair);
                    }
                }
				return new ElementaryObjectVariable(sym.Pair, table);
			}
			if (s.SymbolType == (byte)FormulaConstants.Variable)
			{
				if (s.Symbol == '%')
				{
					return new ElementaryRealConstant(Math.PI);
				}
				if (s.Symbol == 'e')
				{
					return new ElementaryRealConstant(Math.E);
				}
                if (table != null)
                {
                    if (!table.ContainsKey(s.Symbol))
                    {
                        return null;
                    }
                    if (table[s.Symbol].Equals(a))
                    {
                        return new ElementaryRealVariable(s.Symbol);
                    }
                    return new ElementaryObjectVariable(s.Symbol, table);
                }
                else
                {
                    return null;
                }
			}
			if (s.SymbolType == (byte)FormulaConstants.Number)
			{
				if (s.Symbol == '?')
				{
					return new ElementaryRealConstant(s.DoubleValue);
				}
				else
				{
					return new ElementaryULongConstant(s.ULongValue);
				}
			}
			if (s.SymbolType == (byte)FormulaConstants.Unary & s.Symbol != '\u2211')
			{
				string str = s.Symbol + "";
				if (str.Equals(str.ToLower()))
				{
					return new ElementaryFunctionOperation(s.Symbol);
				}
				return new ElementaryIntegerOperation(s.Symbol);
			}
			return null;
		}

		/// <summary>
		/// Gets variables of fornula
		/// </summary>
		/// <param name="formula">The formula</param>
		/// <param name="s">List of variables</param>
		static public void GetVariables(MathFormula formula, ArrayList s)
		{
			for (int i = 0; i < formula.Count; i++)
			{
				MathSymbol sym = formula[i];
				if (sym.SymbolType == (byte)FormulaConstants.Variable)
				{
					char c = sym.Symbol;
					if ((c != 'e') & (c != '%'))
					{
						if (!s.Contains(c))
						{
							s.Add(c);
						}
					}
				}
				for (int j = 0; j < sym.Count; j++)
				{
					GetVariables(sym[j], s);
				}
			}
		}
		
		/// <summary>
		/// Gets variables of formula
		/// </summary>
		/// <param name="formula">The formula</param>
		/// <returns>String of variables</returns>
		static public string GetVariables(MathFormula formula)
		{
			ArrayList s = new ArrayList();
			GetVariables(formula, s);
			string str = "";
			foreach (char c in s)
			{
				str += c;
			}
			return str;
		}

		/// <summary>
		/// Gets variables of formulas
		/// </summary>
		/// <param name="formulas">The formulas</param>
		/// <returns>String of variables</returns>
		static public string GetVariables(MathFormula[] formulas)
		{
			ArrayList s = new ArrayList();
			string str = "";
			foreach (MathFormula formula in formulas)
			{
				GetVariables(formula, s);
			}
			foreach (char c in s)
			{
				str += c;
			}
			return str;
		}

	}
}
