using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Runtime.Serialization;

namespace WebAPIBase.NetCore.BusinessCore
{
    [Serializable]
    public class EntityData : DataSet
    {
        private string m_EntityTypeName = "";
        private string m_ClassName = "";
        private string m_MainTableName = "";
        private int m_CurrentTableIndex = 0;
        private int m_CurrentRowIndex = 0;

        public EntityData()
        {
        }

        public EntityData(SerializationInfo info, StreamingContext context)
          : base(info, context)
        {
        }

        public EntityData(string className)
        {
            try
            {
                this.m_ClassName = className;
                this.m_EntityTypeName = "";
                EntityDataManager.CloneEntityStruct(this, className);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public string ClassName
        {
            get => this.m_ClassName;
            set => this.m_ClassName = value;
        }

        public new string MainTableName
        {
            get => this.m_MainTableName;
            set => this.m_MainTableName = value;
        }

        public int CurrentTableIndex => this.m_CurrentTableIndex;

        public int CurrentRowIndex => this.m_CurrentRowIndex;

        public string EntityTypeName
        {
            get => this.m_EntityTypeName;
            set => this.m_EntityTypeName = value;
        }

        public void AddNewRecord(DataRow row) => this.Tables[this.m_CurrentTableIndex].Rows.Add(row);

        public void AddNewRecord(DataRow row, string tableName)
        {
            if (!this.Tables.Contains(tableName))
                throw new ApplicationException("不存在该表");
            try
            {
                this.Tables[tableName].Rows.Add(row);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public EntityData CloneData()
        {
            try
            {
                EntityData entityData = (EntityData)this.Clone();
                entityData.EntityTypeName = this.EntityTypeName;
                entityData.ClassName = this.ClassName;
                entityData.MainTableName = this.MainTableName;
                return entityData;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void CloneDataStucture(EntityData cloneentitydata)
        {
            try
            {
                cloneentitydata.EntityTypeName = this.EntityTypeName;
                cloneentitydata.ClassName = this.ClassName;
                cloneentitydata.MainTableName = this.MainTableName;
                cloneentitydata.Relations.Clear();
                cloneentitydata.Tables.Clear();
                foreach (DataTable table in (InternalDataCollectionBase)this.Tables)
                    cloneentitydata.Tables.Add(table.Clone());
                foreach (DataRelation relation in (InternalDataCollectionBase)this.Relations)
                {
                    DataTable childTable = relation.ChildTable;
                    DataTable parentTable = relation.ParentTable;
                    int length1 = relation.ChildColumns.Length;
                    int length2 = relation.ParentColumns.Length;
                    DataColumn[] childColumns = new DataColumn[length1];
                    DataColumn[] parentColumns = new DataColumn[length2];
                    for (int index = 0; index < length1; ++index)
                        childColumns[index] = cloneentitydata.Tables[childTable.TableName].Columns[relation.ChildColumns[index].ColumnName];
                    for (int index = 0; index < length2; ++index)
                        parentColumns[index] = cloneentitydata.Tables[parentTable.TableName].Columns[relation.ParentColumns[index].ColumnName];
                    cloneentitydata.Relations.Add(relation.RelationName, parentColumns, childColumns);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public DataRow GetNewRecord(string tableName) => this.Tables.Contains(tableName) ? this.Tables[tableName].NewRow() : throw new ApplicationException("不存在该表");

        public DataRow GetNewRecord() => this.Tables[this.m_CurrentTableIndex].NewRow();

        public DataRow GetRecord() => this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex];

        public DataRow GetRecord(string tableName)
        {
            if (!this.Tables.Contains(tableName))
                throw new ApplicationException("不存在该表");
            return this.Tables[tableName].Rows.Count < 1 ? (DataRow)null : this.Tables[tableName].Rows[this.m_CurrentRowIndex];
        }

        public DataRow GetRecord(int index) => this.Tables.Count < 1 || this.Tables[0].Rows.Count < index + 1 ? (DataRow)null : this.Tables[this.m_CurrentTableIndex].Rows[index];

        public DataRow GetRecord(string tableName, int index)
        {
            if (!this.Tables.Contains(tableName))
                throw new ApplicationException("不存在该表");
            return this.Tables[tableName].Rows.Count < index + 1 ? (DataRow)null : this.Tables[tableName].Rows[index];
        }

        public void SetCurrentTable(int tableIndex)
        {
            if (tableIndex < 0 || tableIndex >= this.Tables.Count)
                throw new ApplicationException("数据表索引超出范围");
            this.m_CurrentTableIndex = tableIndex;
            this.m_CurrentRowIndex = 0;
        }

        public void SetCurrentTable(string tableName)
        {
            this.m_CurrentTableIndex = this.Tables.Contains(tableName) ? this.Tables.IndexOf(tableName) : throw new ApplicationException("不存在该表");
            this.m_CurrentRowIndex = 0;
        }

        public void SetCurrentRow(int rowIndex)
        {
            if (rowIndex < 0 || rowIndex >= this.Tables[this.m_CurrentTableIndex].Rows.Count)
                throw new ApplicationException("数据行索引超出范围");
            this.m_CurrentRowIndex = rowIndex;
        }

        public DataTable CurrentTable => this.Tables[this.m_CurrentTableIndex];

        public DataRow CurrentRow => this.m_CurrentRowIndex >= this.Tables[this.m_CurrentTableIndex].Rows.Count ? (DataRow)null : this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex];

        public bool GetBoolean(string columnName)
        {
            try
            {
                return !this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName) && (bool)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName];
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public byte GetByte(string columnName)
        {
            try
            {
                return this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName) ? (byte)0 : (byte)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName];
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public string GetChar(string columnName)
        {
            try
            {
                return this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName) ? "" : ((char)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName]).ToString();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public string GetDateTime(string columnName)
        {
            try
            {
                return this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName) ? "" : ((DateTime)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName]).ToString();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public string GetDateTime(string columnName, string formatString)
        {
            try
            {
                return this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName) ? "" : ((DateTime)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName]).ToString(formatString);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public string GetDateTimeOnlyDate(string columnName)
        {
            try
            {
                return this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName) ? "" : ((DateTime)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName]).ToString("yyyy-MM-dd");
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public Decimal GetDecimal(string columnName)
        {
            try
            {
                return this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName) ? 0M : (Decimal)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName];
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public string GetDecimalString(string columnName)
        {
            try
            {
                string str = "";
                if (!this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName))
                    str = ((Decimal)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName]).ToString("F");
                return str;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public double GetDouble(string columnName)
        {
            try
            {
                return this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName) ? 0.0 : (double)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName];
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public string GetDoubleString(string columnName)
        {
            try
            {
                string str = "";
                if (!this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName))
                    str = ((double)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName]).ToString("F");
                return str;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public float GetFloat(string columnName)
        {
            try
            {
                return this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName) ? 0.0f : (float)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName];
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public string GetFloatString(string columnName)
        {
            try
            {
                string str = "";
                if (!this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName))
                    str = ((float)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName]).ToString("F");
                return str;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public int GetInt(string columnName)
        {
            try
            {
                return this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName) ? 0 : (int)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName];
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public string GetIntString(string columnName)
        {
            try
            {
                string str = "";
                if (!this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName))
                    str = ((int)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName]).ToString();
                return str;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public long GetLong(string columnName)
        {
            try
            {
                return this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName) ? 0L : (long)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName];
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public string GetLongString(string columnName)
        {
            try
            {
                string str = "";
                if (this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName))
                    str = ((long)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName]).ToString();
                return str;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public sbyte GetSByte(string columnName)
        {
            try
            {
                return this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName) ? (sbyte)0 : (sbyte)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName];
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public short GetShort(string columnName)
        {
            try
            {
                return this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName) ? (short)0 : (short)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName];
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public string GetShortString(string columnName)
        {
            try
            {
                string str = "";
                if (this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName))
                    str = ((short)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName]).ToString();
                return str;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public string GetString(string columnName)
        {
            try
            {
                return this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex].IsNull(columnName) ? "" : (string)this.Tables[this.m_CurrentTableIndex].Rows[this.m_CurrentRowIndex][columnName];
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public bool HasRecord() => this.Tables[this.m_CurrentTableIndex].Rows.Count > 0;

        public void DeleteAllTableRow(string tableName)
        {
            DataTable dataTable = this.Tables.Contains(tableName) ? this.Tables[tableName] : throw new ApplicationException("不存在该表：" + tableName);
            int count = dataTable.Rows.Count;
            for (int index = 0; index < count; ++index)
                dataTable.Rows[index].Delete();
        }
    }
}
