using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;
using System.Collections;

namespace FormulaEditor
{
    /// <summary>
    /// Symbol of unary series
    /// </summary>
    [Serializable()]
    public class SeriesSymbol : SimpleSymbol
    {
        /// <summary>
        /// Operation
        /// </summary>
        private IOperationAcceptor acceptor;

        public SeriesSymbol(int index)
            : base('f', (int)FormulaConstants.Series, true, "f")
        {
            Index = index;
        }

        public SeriesSymbol(SeriesSymbol s)
            : this(s.index)
        {
        }

        protected SeriesSymbol(SerializationInfo info, StreamingContext context)
            : base('f', (int)FormulaConstants.Series, true, "f")
        {
            Index = (int)info.GetValue("Index", typeof(int));
        }

        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Index", index, typeof(int));
        }

        /// <summary>
        /// Sets this object to formula
        /// </summary>
        /// <param name="formula">the formula to set</param>
        public override void SetToFormula(MathFormula formula)
        {
            base.SetToFormula(formula);
            if (this is BracketsSymbol | this is BinarySymbol | this is BinaryFunctionSymbol)
            {
                return;
            }
            children.Clear();
            if (level < (sizes.Length - 1))
            {
                MathFormula child = new MathFormula((byte)(level + 1), sizes);
                children.Add(child);
                return;
            }
            children = null;
        }


        /// <summary>
        /// Operation
        /// </summary>
        public IOperationAcceptor Acceptor
        {
            get
            {
                return acceptor;
            }
        }


        /// <summary>
        /// ICloneable interface implementation
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new SeriesSymbol(Index);
        }

        /// <summary>
        /// Sets operations to formula
        /// </summary>
        /// <param name="formula">The formula</param>
        /// <param name="table">Table of operations</param>
        public static void SetOperations(MathFormula formula, Hashtable table)
        {
            for (int i = 0; i < formula.Count; i++)
            {
                MathSymbol s = formula[i];
                for (int j = 0; j < s.Count; j++)
                {
                    SetOperations(s[j], table);
                }
                if (!(s is SeriesSymbol))
                {
                    continue;
                }
                SeriesSymbol ss = s as SeriesSymbol;
                int ind = ss.index;
                ss.acceptor = null;
                if (!table.ContainsKey(ind))
                {
                    throw new Exception("Operation with index " + ind + " does not exist");
                }
                IOperationAcceptor acc = table[ind] as IOperationAcceptor;
                ss.acceptor = acc;
            }
        }

        public static void SetOperations(MathFormula[] formulas, Hashtable table)
        {
            foreach (MathFormula f in formulas)
            {
                SetOperations(f, table);
            }
        }

        public static ArrayList GetOperationIndexes(MathFormula[] formulas)
        {
            ArrayList list = new ArrayList();
            foreach (MathFormula f in formulas)
            {
                getOperationIndexes(f, list);
            }
            return list;
        }

        private static void getOperationIndexes(MathFormula formula, ArrayList list)
        {
            for (int i = 0; i < formula.Count; i++)
            {
                MathSymbol s = formula[i];
                for (int j = 0; j < s.Count; j++)
                {
                    getOperationIndexes(s[j], list);
                }
                if (!(s is SeriesSymbol))
                {
                    continue;
                }
                SeriesSymbol ss = s as SeriesSymbol;
                int ind = ss.index;
                if (!list.Contains(ind))
                {
                    list.Add(ind);
                }
            }
        }
    }
}
