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

using CategoryTheory;
using DataPerformer;
using DataSetService;


namespace DataTableSelection
{


    [Serializable()]
    public class DataSetIterator : ISerializable, ICategoryObject, IIterator, IDataSetConsumer, IMeasurements
    {

        #region Fields
        protected DataSet dataSet;
        protected DataTable table;
        protected DataRow row;
        protected int current = -1;
        protected DataRow[] rowm = new DataRow[] { null };
        protected IDataSetFactory factory;
        protected List<IMeasure> mea = new List<IMeasure>();

        private object obj;

        #endregion

        #region Constructors

        public DataSetIterator()
        {
        }


        public DataSetIterator(SerializationInfo info, StreamingContext context)
        {
        }

        #endregion

        #region ISerializable Members

        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
        }

        #endregion

        #region ICategoryObject Members

        ICategory ICategoryObject.Category
        {
            get { throw new Exception("The method or operation is not implemented."); }
        }

        ICategoryArrow ICategoryObject.Id
        {
            get { throw new Exception("The method or operation is not implemented."); }
        }

        #endregion

        #region IAssociatedObject Members

        object IAssociatedObject.Object
        {
            get
            {
                return obj;
            }
            set
            {
                obj = value;
            }
        }

        #endregion

        #region IIterator Members

        void IIterator.Reset()
        {
            current = 0;
            rowm[0] = table.Rows[0];
        }

        bool IIterator.Next()
        {
            if (table == null)
            {
                return false;
            }
            ++current;
            if (current >= table.Rows.Count)
            {
                return false;
            }
            row = table.Rows[current];
            rowm[0] = row;
            return true;
        }

        #endregion

        #region IDataSetConsumer Members

        void IDataSetConsumer.Add(DataSet dataSet)
        {
            if (this.dataSet != null & dataSet != null)
            {
                throw new Exception();
            }
            this.dataSet = dataSet;
            table = dataSet.Tables[0];
            init();

        }

        void IDataSetConsumer.Remove(DataSet dataSet)
        {
            this.dataSet = null;
        }

        public IDataSetFactory Factory
        {
            get
            {
                return factory;
            }
            set
            {
                factory = value;
            }
        }


        #endregion

        #region IMeasurements Members

        int IMeasurements.Count
        {
            get { return mea.Count; }
        }

        IMeasure IMeasurements.this[int n]
        {
            get { return mea[n]; }
        }

        void IMeasurements.UpdateMeasurements()
        {
        }

        bool IMeasurements.IsUpdated
        {
            get
            {
                return true;
            }
            set
            {
            }
        }

        #endregion


        #region Specific Members

        protected void init()
        {
            if (table == null)
            {
                return;
            }
            mea.Clear();
            foreach (DataColumn c in table.Columns)
            {
                int ord = c.Ordinal;
                string name = c.ColumnName;
                object type = factory.GetObjectType(c);
                IMeasure m = new RowMeasure(name, type, rowm, ord);
                mea.Add(m);
            }
        }


        #endregion

        #region Measure
  
        class RowMeasure : IMeasure
        {
            string name;
            object type;
            DataRow[] row;
            int ordinal;

            MeasureParameter par;

            public RowMeasure(string name, object type, DataRow[] row, int ordinal)
            {
                this.name = name;
                this.type = type;
                this.row = row;
                this.ordinal = ordinal;
                par = get;
            }

            #region IMeasure Members

            MeasureParameter IMeasure.Parameter
            {
                get { return par; }
            }

            string IMeasure.Name
            {
                get { return name; }
            }

 
            object IMeasure.Type
            {
                get { return type; }
            }

            #endregion

            object get()
            {
                return row[0][ordinal];
            }
        }
        #endregion

    }
}
