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

using CategoryTheory;
using DiagramUI;

namespace DataPerformer
{
    [Serializable()]
    public class SeriesIterator : Series, IDataConsumer, IPostSetArrow, IIteratorConsumer
    {
        #region Fields

        protected IMeasure[] coordinates = new IMeasure[2];

        protected List<IIterator> iterators = new List<IIterator>();

        List<IMeasurements> measurementsData = new List<IMeasurements>();

        #endregion

        #region Ctors

        public SeriesIterator()
        {
        }


        protected SeriesIterator(SerializationInfo info, StreamingContext context)
        {
            x = info.GetValue("X", typeof(string)) as string;
            y = info.GetValue("Y", typeof(string)) as string;
        }

        #endregion

        #region Overriden Members
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("X", x, typeof(string));
            info.AddValue("Y", y, typeof(string));
        }

        #endregion

        #region IDataConsumer Members

        void IDataConsumer.Add(IMeasurements measurements)
        {
            measurementsData.Add(measurements);
        }

        void IDataConsumer.Remove(IMeasurements measurements)
        {
            measurementsData.Remove(measurements);
        }

        void IDataConsumer.UpdateChildrenData()
        {
            foreach (IMeasurements m in measurementsData)
            {
                m.UpdateMeasurements();
            }
        }

        int IDataConsumer.Count
        {
            get { return measurementsData.Count; }
        }

        IMeasurements IDataConsumer.this[int n]
        {
            get { return measurementsData[n]; }
        }

        void IDataConsumer.Reset()
        {
            DataConsumer.Reset(this);
        }

        #endregion

        #region IPostSetArrow Members

        void IPostSetArrow.PostSetArrow()
        {
            Set();
            Post();
        }

        #endregion

        #region IIteratorConsumer Members

        void IIteratorConsumer.Add(IIterator iterator)
        {
            iterators.Add(iterator);
        }

        void IIteratorConsumer.Remove(IIterator iterator)
        {
            iterators.Remove(iterator);
        }

        #endregion


        #region Specific Members


        public void Set(string x, string y)
        {
            this.x = x;
            this.y = y;
            Set();
        }

        protected void Set()
        {
            points = new List<double[]>();
            List<IIterator> iter = iterators;
            if (iter.Count == 0)
            {
                iter = new List<IIterator>();
                IteratorGLM.GetIterators(this, iter);
            }
            IDataConsumer consumer = this;
            for (int i = 0; i < consumer.Count; i++)
            {
                IMeasurements m = consumer[i];
                IAssociatedObject ao = m as IAssociatedObject;
                string on = PureDesktop.GetRelativeName(this, ao) + ".";
                for (int j = 0; j < m.Count; j++)
                {
                    IMeasure mea = m[j];
                    string s = on + mea.Name;
                    if (s.Equals(x))
                    {
                        coordinates[0] = mea;
                        continue;
                    }
                    if (s.Equals(y))
                    {
                        coordinates[1] = mea;
                    }
                }
            }
            foreach (IMeasure m in coordinates)
            {
                if (m == null)
                {
                    return;
                }
            }

            foreach (IIterator it in iter)
            {
                it.Reset();
            }
            while (true)
            {
                consumer.Reset();
                consumer.UpdateChildrenData();
                object ox = coordinates[0].Parameter();
                if (ox is DBNull | ox == null)
                {
                    goto iterate;
                }
                object oy = coordinates[1].Parameter();
                if (oy is DBNull | oy == null)
                {
                    goto iterate;
                }
                double xx = (double)ox;
                double yy = (double)oy;
                points.Add(new double[] { xx, yy });
            iterate:
                foreach (IIterator it in iter)
                {
                    if (!it.Next())
                    {
                        goto fin;
                    }
                }
            }
        fin:
            return;
        }

        public List<string> AllMeasurements
        {
            get
            {
                Double a = 0;
                IDataConsumer c = this;
                List<string> list = new List<string>();
                for (int i = 0; i < c.Count; i++)
                {
                    IMeasurements m = c[i];
                    IAssociatedObject ao = m as IAssociatedObject;
                    string on = PureDesktop.GetRelativeName(this, ao) + ".";
                    for (int j = 0; j < m.Count; j++)
                    {
                        IMeasure mea = m[j];
                        if (mea.Type.Equals(a))
                        {
                            string s = on + mea.Name;
                            list.Add(s);
                        }
                    }
                }
                return list;
            }
        }



        #endregion

    }
}
