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

using CategoryTheory;
using DiagramUI;
using FormulaEditor;
using GeneralLinearMethod;
using DataPerformer;
using DataSetService;


namespace DataTableSelection
{
    [SerializableAttribute()]
    public class DataSetSelection : ArraySelectionCollection, ISerializable, ICategoryObject, IDataSetConsumer
    {
        protected DataSet dataSet;
        protected object obj;
        static readonly Double dt = 0;
        static readonly Decimal dc = 0;
        static readonly Int32 it = 0;
        static readonly Type td = dt.GetType();
        static readonly Type id = it.GetType();
        static readonly Type dct = dc.GetType();

        protected IDataSetFactory factory;
 



        #region Constructors

        public DataSetSelection()
        {
        }

        public DataSetSelection(SerializationInfo info, StreamingContext context)
        {
            // table = info.GetValue("Table", typeof(DataTable)) as DataTable;
        }

        #endregion

        #region ISerializable Members

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            //info.AddValue("Table", table);
        }

        #endregion

        #region ICategoryObject Members

        public ICategory Category
        {
            get
            {
                return null;
            }
        }

        public ICategoryArrow Id
        {
            get
            {
                return null;
            }
        }

        #endregion

        #region IAssociatedObject Members

        public object Object
        {
            get
            {
                return obj;
            }
            set
            {
                obj = value;
            }
        }

        #endregion

        #region IDataSetConsumer Members

        public void Add(DataSet dataSet)
        {
            if (this.dataSet != null && dataSet != null)
            {
                throw new Exception("Provider already exists");
            }
            this.dataSet = dataSet;
            if (dataSet != null)
            {
                load();
            }
        }

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

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


        #endregion

        #region Specific Members

        public static bool IsDouble(DataColumn c)
        {
            Type t = c.DataType;
            return t.Equals(td) | t.Equals(dct);// | t.Equals(id);

        }


        static public DataColumn SelectColumn(string name, DataSet dataSet)
        {
            List<string> names = new List<string>();
            for (int i = 0; i < dataSet.Tables.Count; i++)
            {
                DataTable table = dataSet.Tables[i];
                string pre = table.TableName + "_";
                for (int j = 0; j < table.Columns.Count; j++)
                {
                    DataColumn col = table.Columns[j];
                    string nam = pre + col.ColumnName;
                    if (name.Equals(nam))
                    {
                        return col;
                    }
                    if (!names.Contains(nam))
                    {
                        names.Add(nam);
                    }
                    else
                    {
                        for (int k = 1; ; k++)
                        {
                            string s = name + k;
                            if (!names.Contains(s))
                            {
                                names.Add(s);
                                if (s.Equals(name))
                                {
                                    return col;
                                }
                                break;
                            }
                        }
                    }
                }
            }
            return null;
        }


        public static List<string> GetDoubleNames(DataSet dataSet)
        {
            List<string> names = new List<string>();
            for (int i = 0; i < dataSet.Tables.Count; i++)
            {
                DataTable table = dataSet.Tables[i];
                List<DataColumn> dc = new List<DataColumn>();
                string pre = table.TableName + "_";
                for (int j = 0; j < table.Columns.Count; j++)
                {
                    DataColumn col = table.Columns[j];
                    if (!IsDouble(col))
                    {
                        continue;
                    }
                    dc.Add(col);
                    string name = pre + col.ColumnName;
                    if (!names.Contains(name))
                    {
                        names.Add(name);
                    }
                    else
                    {
                        for (int k = 1; ; k++)
                        {
                            string s = name + k;
                            if (!names.Contains(s))
                            {
                                names.Add(s);
                                break;
                            }
                        }
                    }
                }
            }
            return names;
        }



        protected void load()
        {
            int n = 0;
            List<string> names = new List<string>();
            Dictionary<DataTable, List<DataColumn>> dic = new Dictionary<DataTable, List<DataColumn>>();
            for (int i = 0; i < dataSet.Tables.Count; i++)
            {
                DataTable table = dataSet.Tables[i];
                List<DataColumn> dc = new List<DataColumn>();
                dic[table] = dc;
                string pre = table.TableName + "_";
                for (int j = 0; j < table.Columns.Count; j++)
                {
                    DataColumn col = table.Columns[j];
                    if (!IsDouble(col))
                    {
                        continue;
                    }
                    dc.Add(col);
                    string name = pre + col.ColumnName;
                    if (!names.Contains(name))
                    {
                        names.Add(name);
                    }
                    else
                    {
                        for (int k = 1; ; k++)
                        {
                            string s = name + k;
                            if (!names.Contains(s))
                            {
                                names.Add(s);
                                break;
                            }
                        }
                    }
                }
            }
            string[] namesStr = new string[names.Count];
            for (int i = 0; i < namesStr.Length; i++)
            {
                namesStr[i] = names[i];
            }
            double[][] data = new double[namesStr.Length][];
            n = 0;
            for (int i = 0; i < dataSet.Tables.Count; i++)
            {
                DataTable t = dataSet.Tables[i];
                int size = t.Rows.Count;
                List<DataColumn> l = dic[t];
                for (int j = 0; j < l.Count; j++)
                {
                    data[n] = new double[size];
                    ++n;
                }
            }
            n = 0;
            for (int i = 0; i < dataSet.Tables.Count; i++)
            {
                DataTable t = dataSet.Tables[i];
                DataRowCollection rows = t.Rows;
                List<DataColumn> l = dic[t];
                for (int k = 0; k < rows.Count; k++)
                {
                    DataRow row = rows[k];
                    for (int j = 0; j < l.Count; j++)
                    {
                        DataColumn dc = l[j];
                        double a = 0;
                        object o = row[dc.ColumnName];
                        try
                        {
                            a = (double)o;
                        }
                        catch (Exception)
                        {
                            string s = o + "";
                            a = Double.Parse(s);
                        }
                        /*                     if (dc.DataType.Equals(it))
                                             {
                                                 int v = (int)o;
                                                 a = (double)v;
                                             }
                                             else
                                             {
                                                 a = (double)o;
                                             }*/
                        data[n + j][k] = a;
                    }
                }
                n += l.Count;
            }
            Set(namesStr, data);
        }
       #endregion

    }

}
