using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Project.Manager
{
    public class ModelManager
    {
        public DataSet1 dataSet;
        readonly private string fn_ModelV;
        readonly private string fn_ModelM;

        public ModelManager(string fnVision, string fnMachine)
        {
            this.fn_ModelV = fnVision;
            this.fn_ModelM = fnMachine;
            dataSet = new DataSet1();
        }

        public void LoadModelV()
        {
            //set filename
            string filename = fn_ModelV;
            int lineCount = 0;
            string buffer = string.Empty;

            //read file
            var fi = new FileInfo(filename);
            if (fi.Exists == false)
            {
                Pub.log.AddE("▣ No Load Model(Vision)-Data)");
                return;
            }

            lineCount = 0;
            try
            {
                buffer = System.IO.File.ReadAllText(fi.FullName, System.Text.Encoding.Default);
            }
            catch (Exception ex)
            {
                buffer = string.Empty;
                Pub.log.AddE(string.Format("Model(Vision) Error File={0},Message={1}", filename, ex.Message));
                return;
            }

            //존재하는 컬럼확인을 위해 미리 저장함
            List<String> dbCols = new List<string>();
            foreach (System.Data.DataColumn col in dataSet.Model.Columns)
                dbCols.Add(col.ColumnName);

            List<String> Cols = new List<string>();
            foreach (string items in buffer.Split('\r'))
            {
                lineCount += 1;
                var line = items.Replace("\r", "").Replace("\n", "");
                if (line.Trim() == "" || line.StartsWith("ver")) continue; //빈줄과 버젼표기는 제거한다.
                string[] buf = line.Split(',');

                //첫줄에는 컬럼명이 들어있다.
                if (Cols.Count < 1)
                {
                    foreach (string colname in buf)
                    {
                        if (colname.isEmpty()) continue; //비어있는값은 처리하지 않는다.
                        Cols.Add(colname);
                    }
                    continue;
                }

                //데이터를 각 컬럼에 넣는다.
                DataSet1.ModelRow dr = dataSet.Model.NewModelRow();

                //비젼속성은 컬럼명이 v_로 시작한다.
                for (int i = 0; i < Cols.Count; i++) //0번은 Mccode이므로 제외한다.
                {
                    try
                    {
                        if (dbCols.IndexOf(Cols[i]) == -1) continue; //존재하지 않는 컬럼은 제외한다.
                        if (Cols[i].ToUpper() == "IDX") continue;
                        dr[Cols[i]] = buf[i];
                    }
                    catch (Exception ex)
                    {
                        Pub.log.AddE("Model(Vision) Load Error:" + ex.Message);
                    }
                }

                //if (dr.TagBarcode.isEmpty()) dr.Delete();
                try
                {
                    if (dr.RowState == System.Data.DataRowState.Detached) dataSet.Model.AddModelRow(dr);//신규자료일경우에는 추가함                    
                    else if (dr.RowState != System.Data.DataRowState.Deleted) dr.EndEdit();
                }
                catch (Exception ex)
                {
                    Pub.log.AddE("Load Model(Vision) file" + ex.Message);
                }
            }

            dataSet.Model.AcceptChanges();
        }
        public void LoadModelM()
        {
            //set filename
            string filename = fn_ModelM;
            int lineCount = 0;
            string buffer = string.Empty;

            //read file
            var fi = new FileInfo(filename);
            if (fi.Exists == false)
            {
                Pub.log.AddE("▣ No Load M/C Model-Data)");
                return;
            }

            lineCount = 0;
            try
            {
                buffer = System.IO.File.ReadAllText(fi.FullName, System.Text.Encoding.Default);
            }
            catch (Exception ex)
            {
                buffer = string.Empty;
                Pub.log.AddE(string.Format("M/C ModelData Error File={0},Message={1}", filename, ex.Message));
                return;
            }

            //존재하는 컬럼확인을 위해 미리 저장함
            List<String> dbCols = new List<string>();
            foreach (System.Data.DataColumn col in dataSet.MCModel.Columns)
                dbCols.Add(col.ColumnName);

            List<String> Cols = new List<string>();
            foreach (string items in buffer.Split('\r'))
            {
                lineCount += 1;
                var line = items.Replace("\r", "").Replace("\n", "");
                if (line.Trim() == "" || line.StartsWith("ver")) continue; //빈줄과 버젼표기는 제거한다.
                string[] buf = line.Split('\t');

                //첫줄에는 컬럼명이 들어있다.
                if (Cols.Count < 1)
                {
                    foreach (string colname in buf)
                    {
                        if (colname.isEmpty()) continue; //비어있는값은 처리하지 않는다.
                        Cols.Add(colname);
                    }
                    continue;
                }

                //데이터를 각 컬럼에 넣는다.
                var dr = dataSet.MCModel.NewMCModelRow();

                //비젼속성은 컬럼명이 v_로 시작한다.
                for (int i = 0; i < Cols.Count; i++) //0번은 Mccode이므로 제외한다.
                {
                    try
                    {
                        if (dbCols.IndexOf(Cols[i]) == -1) continue; //존재하지 않는 컬럼은 제외한다.
                        // if (Cols[i].ToUpper() == "IDX") continue;
                        dr[Cols[i]] = buf[i];
                    }
                    catch (Exception ex)
                    {
                        Pub.log.AddE("M/C Model  Load Error:" + ex.Message);
                    }
                }

                //if (dr.TagBarcode.isEmpty()) dr.Delete();
                try
                {
                    if (dr.RowState == System.Data.DataRowState.Detached) dataSet.MCModel.AddMCModelRow(dr);//신규자료일경우에는 추가함                    
                    else if (dr.RowState != System.Data.DataRowState.Deleted) dr.EndEdit();
                }
                catch (Exception ex)
                {
                    Pub.log.AddE("Load M/C Model Data file" + ex.Message);
                }
            }

            //자료중 보정
            foreach (var dr in this.dataSet.MCModel)
            {
                if (dr.IsSpeedAccNull()) dr.SpeedAcc = 100;
                if (dr.IsSpeedDccNull()) dr.SpeedDcc = 0;
                if (dr.IsSpeedNull()) dr.Speed = 50;
            }
            dataSet.Model.AcceptChanges();

        }

        /// <summary>
        /// project , model read from file
        /// </summary>
        public void Load()
        {
            //데이터셋 초기화
            if (dataSet == null) dataSet = new DataSet1();
            else dataSet.Clear();

            //파일로부터 데이터를 읽어들인다.
            this.LoadModelV();
            this.LoadModelM();
            this.dataSet.AcceptChanges();

            int cnt2 = dataSet.Model.Rows.Count;
            int cnt1 = dataSet.MCModel.Rows.Count;
            Pub.log.AddI(string.Format("※ Model Manager : {0}/{1}", cnt1, cnt2));
        }

        public void Save()
        {
            this.dataSet.AcceptChanges();
            System.IO.DirectoryInfo di = new DirectoryInfo(modelPath);
            if (!di.Exists) di.Create();
            SaveModelM();
            SaveModelV();
        }

        public string modelPath
        {
            get
            {
                return System.IO.Path.Combine(Util.CurrentPath, "Model");
            }

        }

        public void SaveModelM()
        {
            this.dataSet.MCModel.AcceptChanges();
            var data = new StringBuilder();
            data.AppendLine("ver\t" + "1"); //version
            //       data.Append("Title"); //첫열에는 Mccode를 넣는다.

            List<String> cols = new List<string>();
            //cols.AddRange(new string[] { "title","idx","pidx"});

            foreach (System.Data.DataColumn col in this.dataSet.MCModel.Columns)
            {
                string colname = col.ColumnName.ToLower();
                if (cols.Contains(colname) == true) continue; //이미 존재하면 처리하지 않음
                //   if (colname == "idx") continue; //기본열은 제외한다.
                cols.Add(col.ColumnName);
            }

            //열을 정렬해서 추가한다.
            //var bb = cols.OrderBy(t => t);
            for (int i = 0; i < cols.Count; i++)
            {
                var colname = cols[i];
                if (i > 0) data.Append("\t");
                data.Append(colname);
            }
            data.AppendLine();

            //output data(글로벌 셋팅하고 MC코드값만 취한다)
            foreach (var list in dataSet.MCModel.Rows)
            {
                var dr = list as DataSet1.MCModelRow;
                //bb = cols.OrderBy(t => t);
                for (int i = 0; i < cols.Count; i++)
                {
                    var colname = cols[i];
                    if (i > 0) data.Append("\t");

                    if (dr[colname] != DBNull.Value) data.Append(dr[colname].ToString());
                    else if (dataSet.MCModel.Columns[colname].DataType == typeof(double) ||
                        dataSet.MCModel.Columns[colname].DataType == typeof(Int32) ||
                        dataSet.MCModel.Columns[colname].DataType == typeof(UInt32) ||
                        dataSet.MCModel.Columns[colname].DataType == typeof(Single) ||
                        dataSet.MCModel.Columns[colname].DataType == typeof(byte) ||
                        dataSet.MCModel.Columns[colname].DataType == typeof(Boolean) ||
                        dataSet.MCModel.Columns[colname].DataType == typeof(Int16) ||
                        dataSet.MCModel.Columns[colname].DataType == typeof(UInt16))
                    {
                        if (dataSet.MCModel.Columns[colname].DataType == typeof(Boolean)) data.Append("False");
                        else data.Append("0");
                    }
                    else data.Append("");
                }
                data.AppendLine();
            }
            try
            {
                var mfile = new System.IO.FileInfo(fn_ModelM);
                var bakfile = new System.IO.FileInfo(System.IO.Path.Combine(mfile.Directory.FullName, "Backup", "m" + DateTime.Now.ToString("yyyyMMddHHmmss") + mfile.Extension));
                if (bakfile.Exists) bakfile.Delete();
                if (bakfile.Directory.Exists == false) bakfile.Directory.Create();
                if (mfile.Exists) System.IO.File.Copy(mfile.FullName, bakfile.FullName, true);
                Pub.log.Add("model backup(motion) : " + bakfile.FullName);

                System.IO.File.WriteAllText(fn_ModelM, data.ToString(), System.Text.Encoding.Default);
                Pub.log.AddAT("Save M/C Model Parameter - OK");
            }
            catch (Exception ex)
            {
                Util.MsgE("M/C Model Save Error\r\n" + ex.Message);
                Pub.log.AddE("M/C Model Save Error :: " + ex.Message);
            }
        }

        public void SaveModelV()
        {
            this.dataSet.Model.AcceptChanges();
            var data = new StringBuilder();
            data.AppendLine("ver,:" + "1"); //version
            data.Append("Title"); //첫열에는 Mccode를 넣는다.

            List<String> cols = new List<string>();
            foreach (System.Data.DataColumn col in this.dataSet.Model.Columns)
            {
                string colname = col.ColumnName.ToLower();
                if (colname == "Memo" || colname == "idx") continue; //기본열은 제외한다.
                cols.Add(col.ColumnName);
            }
            cols.Add("Memo");

            //열을 정렬해서 추가한다.
            var bb = cols.OrderBy(t => t);
            foreach (string colname in bb)
                data.Append("," + colname);
            data.AppendLine();

            //output data(글로벌 셋팅하고 MC코드값만 취한다)
            foreach (var list in dataSet.Model.Select("isnull(Title,'') <> ''", "Title"))
            {
                var dr = list as DataSet1.ModelRow;
                data.Append(dr.Title); //일반셋팅은 mccode 값 그대로 넣는다.
                bb = cols.OrderBy(t => t);
                foreach (string colname in bb) //지정된 열제목의 데이터를 가져온다.
                {
                    data.Append(",");
                    if (dr[colname] != DBNull.Value) data.Append(dr[colname].ToString());
                    else if (dataSet.Model.Columns[colname].DataType == typeof(double) ||
                        dataSet.Model.Columns[colname].DataType == typeof(Int32) ||
                        dataSet.Model.Columns[colname].DataType == typeof(UInt32) ||
                        dataSet.Model.Columns[colname].DataType == typeof(Single) ||
                        dataSet.Model.Columns[colname].DataType == typeof(byte) ||
                        dataSet.Model.Columns[colname].DataType == typeof(Boolean) ||
                        dataSet.Model.Columns[colname].DataType == typeof(Int16) ||
                        dataSet.Model.Columns[colname].DataType == typeof(UInt16))
                    {
                        if (dataSet.Model.Columns[colname].DataType == typeof(Boolean)) data.Append("False");
                        else data.Append("0");
                    }
                    else data.Append("0");
                }
                data.AppendLine();
            }
            try
            {
                //기존파일은 백업을 한다.
                var mfile = new System.IO.FileInfo(fn_ModelV);
                var bakfile = new System.IO.FileInfo(System.IO.Path.Combine(mfile.Directory.FullName, "Backup", "v" + DateTime.Now.ToString("yyyyMMddHHmmss") + mfile.Extension));
                if (bakfile.Exists) bakfile.Delete();
                if (bakfile.Directory.Exists == false) bakfile.Directory.Create();
                if (mfile.Exists) System.IO.File.Copy(mfile.FullName, bakfile.FullName, true);
                Pub.log.Add("model backup(vision) : " + bakfile.FullName);
                System.IO.File.WriteAllText(fn_ModelV, data.ToString(), System.Text.Encoding.Default);
                Pub.log.AddAT("Save Model(Vision) Parameter - OK");
            }
            catch (Exception ex)
            {
                Util.MsgE(" Model(Vision) Save Error\r\n" + ex.Message);
                Pub.log.AddE(" Model(Vision) Save Error :: " + ex.Message);
            }
        }

        /// <summary>
        /// 지정된 mccode 의 개체를 반환합니다. (없거나 중복일경우 mccode 가 비어있습니다)
        /// </summary>
        /// <param name="tagBcd"></param>
        /// <returns></returns>
        public DataSet1.MCModelRow GetDataM(string title)
        {
            if (title.isEmpty()) return null;
            if (dataSet.Model == null || dataSet.MCModel.Rows.Count < 1) return null;
            var datas = dataSet.MCModel.Where(t => t.Title == title).ToArray();
            if (datas.Length != 1) return null;
            return datas[0];
        }
        public DataSet1.ModelRow GetDataV(string title)
        {
            if (title.isEmpty()) return null;
            if (dataSet.Model == null || dataSet.Model.Rows.Count < 1) return null;
            var datas = dataSet.Model.Where(t => t.Title == title).ToArray();
            if (datas.Length != 1) return null;
            return datas[0];
        }
        /// <summary>
        /// 0번 모델을 가져옵니다.
        /// </summary>
        /// <returns></returns>
        public DataSet1.MCModelRow GetDataM(int idx)
        {
            if (dataSet.MCModel == null || dataSet.MCModel.Rows.Count < 1) return null;
            return dataSet.MCModel[idx];
        }
        public DataSet1.ModelRow GetDataV(int idx)
        {
            if (dataSet.Model == null || dataSet.Model.Rows.Count < 1) return null;
            return dataSet.Model[idx];
        }
        public DataSet1.ModelRow GetDataVbyMidx(int midx)
        {
            if (dataSet.Model == null || dataSet.Model.Rows.Count < 1) return null;
            return dataSet.Model.Where(t => t.Midx == midx).FirstOrDefault();
        }
        public int GetMoelCountM
        {
            get
            {
                return this.dataSet.Model.Select("isnull(Title,'') <> '' ").Length;
            }
        }
        public int GetMoelCountV
        {
            get
            {
                return this.dataSet.MCModel.Select("isnull(Title,'') <> '' ").Length;
            }
        }

        public Boolean AddData(DataSet1.ModelRow data)
        {
            if (data.Title.Trim() == "") return false;
            var item = this.GetDataV(data.Title);
            if (item != null) return false; //존재한다면 넘어감
            dataSet.Model.AddModelRow(data);
            return true;
        }
        public Boolean AddData(DataSet1.MCModelRow data)
        {
            if (data.Title.Trim() == "") return false;
            var item = this.GetDataM(data.Title);
            if (item != null) return false; //존재한다면 넘어감
            dataSet.MCModel.AddMCModelRow(data);
            return true;
        }
        public Boolean DeleteDataM(string _mccode)
        {
            var item = GetDataM(_mccode);
            if (item == null) return false; //없는자료라면 넘어감
            dataSet.MCModel.RemoveMCModelRow(item);
            return true;
        }
        public Boolean DeleteDataV(string _mccode)
        {
            var item = GetDataV(_mccode);
            if (item == null) return false; //없는자료라면 넘어감
            dataSet.Model.RemoveModelRow(item);
            return true;
        }

    }

}
