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

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

		public ModelManager(string fnVision, string fnMachine, string fnError, string fnInput, string fnOutput)
		{
			this.fn_ModelV = fnVision;
			this.fn_ModelM = fnMachine;
			this.fn_Error = fnError;
			this.fn_Input = fnInput;
			this.fn_Output = fnOutput;

			dataSet = new DataSet1();
		}
		public void LoadModelE()
		{
			//set filename
			string filename = fn_Error;

			//read file
			var fi = new FileInfo(filename);
			if (fi.Exists == false)
			{
				PUB.log.AddE("▣ No Load Model(Error)-Data)");
				return;
			}
			dataSet.ErrorDescription.Clear();
			dataSet.ErrorDescription.ReadXml(fi.FullName);
			dataSet.ErrorDescription.AcceptChanges();
		}
		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.OPModel.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.OPModelRow dr = dataSet.OPModel.NewOPModelRow();

				//비젼속성은 컬럼명이 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.OPModel.AddOPModelRow(dr);//신규자료일경우에는 추가함                    
					else if (dr.RowState != System.Data.DataRowState.Deleted) dr.EndEdit();
				}
				catch (Exception ex)
				{
					PUB.log.AddE("Load Model(Vision) file" + ex.Message);
				}
			}

			dataSet.OPModel.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.OPModel.AcceptChanges();

		}
		public void LoadModelI()
		{
			//set filename
			string filename = fn_Input;

			//read file
			var fi = new FileInfo(filename);
			if (fi.Exists == false)
			{
				PUB.log.AddE("▣ No Load Model(Error)-Data)");
				return;
			}
			dataSet.InputDescription.Clear();
			dataSet.InputDescription.ReadXml(fi.FullName);
			dataSet.InputDescription.AcceptChanges();
		}
		public void LoadModelO()
		{
			//set filename
			string filename = fn_Output;

			//read file
			var fi = new FileInfo(filename);
			if (fi.Exists == false)
			{
				PUB.log.AddE("▣ No Load Model(Error)-Data)");
				return;
			}
			dataSet.OutputDescription.Clear();
			dataSet.OutputDescription.ReadXml(fi.FullName);
			dataSet.OutputDescription.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.LoadModelE();
			this.LoadModelI();
			this.LoadModelO();
			this.dataSet.AcceptChanges();

			var cntP = dataSet.OPModel.Rows.Count;
			var cntM = dataSet.MCModel.Rows.Count;
			var cntE = dataSet.ErrorDescription.Rows.Count;
			var cntI = dataSet.InputDescription.Rows.Count;
			var cntO = dataSet.OutputDescription.Rows.Count;

			PUB.log.AddI(string.Format("※ Model Manager : P{0},M{1},E{2},I{3},O:{4}", cntP, cntM, cntE, cntI, cntO));
		}

		//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(Boolean))
                        data.Append("False");
                    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(Int16) ||
						dataSet.MCModel.Columns[colname].DataType == typeof(UInt16))
					{
                        //숫자는 기본 0으로 처리한다
						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.OPModel.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.OPModel.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.OPModel.Select("isnull(Title,'') <> ''", "Title"))
			{
				var dr = list as DataSet1.OPModelRow;
				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.OPModel.Columns[colname].DataType == typeof(Boolean))
                        data.Append("False");
                    else if (dataSet.OPModel.Columns[colname].DataType == typeof(double) ||
                        dataSet.OPModel.Columns[colname].DataType == typeof(Int32) ||
                        dataSet.OPModel.Columns[colname].DataType == typeof(UInt32) ||
                        dataSet.OPModel.Columns[colname].DataType == typeof(Single) ||
                        dataSet.OPModel.Columns[colname].DataType == typeof(byte) ||
                        dataSet.OPModel.Columns[colname].DataType == typeof(Int16) ||
                        dataSet.OPModel.Columns[colname].DataType == typeof(UInt16))
                    {
                        //숫자는 기본 0으로 처리한다
                        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);
			}
		}
		public void SaveModelI()
		{
			SaveModel(fn_Input, "i", dataSet.InputDescription);
		}
		public void SaveModelO()
		{
			SaveModel(fn_Output, "o", dataSet.OutputDescription);
		}
		public void SaveModelE()
		{
			SaveModel(fn_Error, "e", dataSet.ErrorDescription);
		}

		void SaveModel(string fn, string prefix, System.Data.DataTable dt)
		{
			dt.AcceptChanges();

			try
			{
				var mfile = new System.IO.FileInfo(fn);
				var bakfile = new System.IO.FileInfo(System.IO.Path.Combine(mfile.Directory.FullName, "Backup", prefix + 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({dt.TableName}) : " + bakfile.FullName);

				var savefeil = mfile.FullName;
				if (savefeil.EndsWith(".csv")) savefeil = savefeil.Replace(".csv", ".xml");

				dt.WriteXml(savefeil, true);
				//System.IO.File.WriteAllText(savefeil, data.ToString(), System.Text.Encoding.Default);
				PUB.log.AddAT($"Save {dt.TableName} Model Parameter - OK");
			}
			catch (Exception ex)
			{
				UTIL.MsgE($"{dt.TableName} Model Save Error\r\n" + ex.Message);
				PUB.log.AddE($"{dt.TableName} Model 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.MCModel == 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.OPModelRow GetDataV(string title)
		{
			if (title.isEmpty()) return null;
			if (dataSet.OPModel == null || dataSet.OPModel.Rows.Count < 1) return null;
			var datas = dataSet.OPModel.Where(t => t.Title == title).ToArray();
			if (datas.Length != 1) return null;
			return datas[0];
		}


	}

}
