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

namespace FormulaEditor
{
	/// <summary>
	/// Summary description for ElementaryFormulaSimplification.
	/// </summary>
	public class ElementaryFormulaSimplification : FormulaSimplification
	{
		//private IFormulaCreatorOperation creator;

		private static readonly Double a = 0;

        public static readonly ElementaryFormulaSimplification Object = new ElementaryFormulaSimplification();

		private ElementaryFormulaSimplification()///*IFormulaCreatorOperation creator)
		{
			//this.creator = creator;
		}
		
		#region IFormulaSimplification Members

		public override ObjectFormulaTree Simplify(ObjectFormulaTree tree)
		{
            ObjectFormulaTree t = tree.Clone() as ObjectFormulaTree;
            t = simplify(t);
            t = PolyMult.MultMult(t);
            t = simplify(t);
			return PolyMult.MultMultReverse(t);
		}




		#endregion


        private ObjectFormulaTree simplify(ObjectFormulaTree tree)
        {
            ObjectFormulaTree t = tree;
            while (true)
            {
                bool b;
                t = PolyMult.simplify(t, out b);
                t = PolySum.Simplify(t, ref b);
                if (b)
                {
                   break;
                }
            }
            return t;
        }

		public static bool IsConst(ObjectFormulaTree tree)
		{
			for (int i = 0; i < tree.Count; i++)
			{
				if (!IsConst(tree[i]))
				{
					return false;
				}
			}
			IObjectOperation op = tree.Operation;
			if (op is ElementaryRealConstant)
			{
				return true;
			}
			return false;
		}

		public static object GetValue(ObjectFormulaTree tree)
		{
			if (!IsConst(tree))
			{
				return null;
			}
			return tree.Result;
		}

		public static ObjectFormulaTree SimplifyContstants(ObjectFormulaTree tree, out bool completed)
		{
			bool comp = true;
			completed = true;
			if (IsConst(tree))
			{
				if (tree.Operation is ElementaryRealConstant)
				{
					completed = true;
					return tree;
				}
				if (tree.ReturnType.Equals(a))
				{
					ElementaryRealConstant x = new ElementaryRealConstant((double) tree.Result);
					completed = false;
					return new ObjectFormulaTree(x, new List<ObjectFormulaTree>());
				}
			}
			List<ObjectFormulaTree> l = new List<ObjectFormulaTree>();
			for (int i = 0; i < tree.Count; i++)
			{
				ObjectFormulaTree t = SimplifyContstants(tree[i], out comp);
				if (!comp)
				{
					completed = false;
				}
				l.Add(t);
			}
			return new ObjectFormulaTree(tree.Operation, l);
		}
	}

}
