using parkMonitor.model;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace parkMonitor.server.monitorServer {
	/// <summary>加载监控参数配置文件</summary>
	public class PLCParamCtl {
		public List<ListRootParam> lstParamData = new List<ListRootParam>();       //参数数据
		public int minAddr = Int32.MaxValue;   //最小地址
		public int maxAddr = 0;                //最大地址

		public void load() {
			string path = SysConst.inlineResPath() + @"plcAddr.csv";

			Assembly assm = Assembly.GetExecutingAssembly();
			Stream istr = null;
			StreamReader sr = null;

			string data = "";

			try {
				istr = assm.GetManifestResourceStream(path);
				sr = new StreamReader(istr, Encoding.Unicode);

				data = sr.ReadToEnd();
				//Debug.WriteLine(data);
			} catch(Exception) {

			}

			if(sr != null) {
				sr.Close();
			}

			if(istr != null) {
				istr.Close();
			}

			if(data != "") {
				parseParam(data);
				//initViewModel();
			}
		}

		/// <summary>解析监控参数配置文件</summary>
		private void parseParam(string data) {
			List<ListRootParam> lstResult = new List<ListRootParam>();
			Dictionary<string, ListRootParam> mapRoot = new Dictionary<string, ListRootParam>();

			string gap = "\t";
			string endl = "\r\n";

			string[] arrLine = data.Split(new string[] { endl }, StringSplitOptions.RemoveEmptyEntries);
			if(arrLine.Length <= 0) {
				return;
			}

			Dictionary<string, int> mapHead = new Dictionary<string, int>();

			//获取头部
			string[] arrHead = arrLine[0].Split(new string[] { gap }, StringSplitOptions.None);
			List<string> lstHead = new List<string>();
			//int colCount = arrHead.Length;
			for(int i = 0; i < arrHead.Length; ++i) {
				string strHead = arrHead[i].Trim();
				if(strHead == "") {
					break;
				}
				lstHead.Add(strHead);
				mapHead[strHead] = i;
			}

			//ListRootParam lastRootParam = null;
			Dictionary<string, ListRootParam> mapRootParam = new Dictionary<string, ListRootParam>();
			ListMiddleParam lastMiddleParam = null;
			DevParamModel lastParamModel = null;
			List<string> arrLastCol = null;
			//遍历行
			for(int i = 1; i < arrLine.Length; ++i) {
				List<string> arrCol = arrLine[i].Split(new string[] { gap }, StringSplitOptions.None).ToList();
				int col = Math.Min(arrCol.Count, lstHead.Count);

				//填充空数据
				for(int j = 0; j < col; ++j) {
					if(arrCol[j] == "" && i != 1) {
						arrCol[j] = arrLastCol[j];
					}
				}
				for(int j = col; j < lstHead.Count; ++j) {
					arrCol.Add(arrLastCol[j]);
				}
				arrLastCol = arrCol;

				//get model
				DevParamModel md = getParamModel(mapHead, lastParamModel, arrCol);

				//初始化大类
				if(!mapRootParam.ContainsKey(md.typeDesc)) {
					ListRootParam root = new ListRootParam();
					root.nameDesc = md.typeDesc;
					root.type = md.type;
					lstResult.Add(root);
					mapRootParam[md.typeDesc] = root;
				}
				ListRootParam lastRootParam = mapRootParam[md.typeDesc];

				//初始化小类
				if(lastMiddleParam == null || lastMiddleParam.nameDesc != md.subTypeDesc) {
					lastMiddleParam = new ListMiddleParam();
					lastMiddleParam.type = md.type;
					lastMiddleParam.nameDesc = md.subTypeDesc;
					lastMiddleParam.uiType = md.uiType;
					lastMiddleParam.imgType = md.imgType;
					lastMiddleParam.canReset = md.canReset;
					lastMiddleParam.isShow = md.isShow;
					lastMiddleParam.subTypeIdx = md.subTypeIdx;
					lastMiddleParam.shortNameType = md.shortSubTypeDesc;
					lastRootParam.Add(lastMiddleParam);
				}
				if(lastParamModel != md) {
					lastMiddleParam.Add(md);
				}
				lastParamModel = md;
			}

			//排序
			//遍历大类
			for(int i = 0; i < lstResult.Count; ++i) {
				lstResult[i].Sort((x, y) => x.subTypeIdx.CompareTo(y.subTypeIdx));
				//遍历小类
				for(int j = 0; j < lstResult[i].Count; ++j) {
					lstResult[i][j].Sort((x, y) => x.statusIdx.CompareTo(y.statusIdx));
				}
			}

			lstParamData = lstResult;

			//test show
			//for(int i = 0; i < lstResult.Count; ++i) {
			//	for(int j = 0; j < lstResult[i].Count; ++j) {
			//		for(int k = 0; k < lstResult[i][j].Count; ++k) {
			//			var item = lstResult[i][j][k];
			//			if(item.mapCbx.Count != 0) {
			//				foreach(string key in item.mapCbx.Keys) {
			//					//Debug.WriteLine("" + item.type + "," + item.subType + "," + item.statusName + "," + item.addr + "," + item.valueType + "," + item.showType + "," + item.mapCbx[key].value + "," + item.mapCbx[key].warnLevel + "," + item.ioType + "," + item.isShow + "," + item.typeDesc + "," + item.subTypeDesc + "," + item.statusDesc + "," + item.mapCbx[key].desc);
			//					Debug.WriteLine("" + item.uiType + "," + item.imgType + "," + item.addr + "," + item.valueType + "," + item.showType + "," + item.mapCbx[key].value + "," + item.mapCbx[key].warnLevel + "," + item.ioType + "," + item.isShow + "," + item.typeDesc + "," + item.subTypeDesc + "," + item.statusDesc + "," + item.mapCbx[key].desc);
			//				}
			//			} else {
			//				//Debug.WriteLine("" + item.type + "," + item.subType + "," + item.statusName + "," + item.addr + "," + item.valueType + "," + item.showType + "," + "-" + "," + "-" + "," + item.ioType + "," + item.typeDesc + "," + item.subTypeDesc + "," + item.statusDesc + "," + "-");
			//				Debug.WriteLine("" + item.uiType + "," + item.imgType + "," + item.addr + "," + item.valueType + "," + item.showType + "," + "-" + "," + "-" + "," + item.ioType + "," + item.typeDesc + "," + item.subTypeDesc + "," + item.statusDesc + "," + "-");
			//			}
			//		}
			//	}
			//}
		}

		private DevParamModel getParamModel(Dictionary<string, int> mapHead, DevParamModel lastParamModel, List<string> arrCol) {
			string strType = getCol(mapHead, arrCol, "type");
			//string subType = getCol(mapHead, arrCol, "subType");
			string strUiType = getCol(mapHead, arrCol, "uiType");
			string strImgType = getCol(mapHead, arrCol, "imgType");
			//string statusName = getCol(mapHead, arrCol, "status");
			string strAddr = getCol(mapHead, arrCol, "addr");
			string strValueType = "e_" + getCol(mapHead, arrCol, "valueType");
			string strShowType = "e_" + getCol(mapHead, arrCol, "showType");
			string strDefaultValue = getCol(mapHead, arrCol, "defaultValue");
			string strCbxValue = getCol(mapHead, arrCol, "cbxValue");
			string strCbxDesc = getCol(mapHead, arrCol, "cbxDesc");
			string strWarnLevel = getCol(mapHead, arrCol, "warnLevel");
			string strIOType = getCol(mapHead, arrCol, "canWrite");
			string strCanReset = getCol(mapHead, arrCol, "canReset").Trim();
			string strIsShow = getCol(mapHead, arrCol, "isShow").Trim();
			string strSubTypeIdx = getCol(mapHead, arrCol, "subTypeIdx");
			string strStatusIdx = getCol(mapHead, arrCol, "statusIdx");
			string strStatusDescWidth = getCol(mapHead, arrCol, "statusDescWidth");
			string strTypeDesc = getCol(mapHead, arrCol, "typeDesc");
			strTypeDesc = strTypeDesc.Replace('$', '_');
			string strSubTypeDesc = getCol(mapHead, arrCol, "subTypeDesc");
			strSubTypeDesc = strSubTypeDesc.Replace('$', '_');
			string strStatusDesc = getCol(mapHead, arrCol, "statusDesc");
			string strShortSubTypeDesc = getCol(mapHead, arrCol, "shortSubTypeDesc");
			if(strShortSubTypeDesc == "-") { strShortSubTypeDesc = strSubTypeDesc; }
			string strShortStatusDesc = getCol(mapHead, arrCol, "shortStatusDesc");
			if(strShortStatusDesc == "-") { strShortStatusDesc = strStatusDesc; }
			string strShortCbxDesc = getCol(mapHead, arrCol, "shortCbxDesc");
			if(strShortCbxDesc == "-") { strShortCbxDesc = strCbxDesc; }

			DeviceType type = DeviceType.Unknown;
			Enum.TryParse(strType, out type);
			int addr = Int32.Parse(strAddr);
			DevTreeItemShowType uiType = (DevTreeItemShowType)Enum.Parse(typeof(DevTreeItemShowType), strUiType);
			DeviceType imgType = DeviceType.Unknown;
			Enum.TryParse(strImgType, out imgType);
			ParamValueType valueType = (ParamValueType)Enum.Parse(typeof(ParamValueType), strValueType);
			ParamShowType showType = (ParamShowType)Enum.Parse(typeof(ParamShowType), strShowType);
			ParamIOType ioType = (ParamIOType)Enum.Parse(typeof(ParamIOType), strIOType);
			int subTypeIdx = 0;
			Int32.TryParse(strSubTypeIdx, out subTypeIdx);
			int statusIdx = 0;
			Int32.TryParse(strStatusIdx, out statusIdx);
			AlarmStatus warnLevel = AlarmStatus.None;
			Enum.TryParse(strWarnLevel, out warnLevel);
			Double statusDescWidth = Double.NaN;
			Double.TryParse(strStatusDescWidth, out statusDescWidth);

			DevParamModel md = lastParamModel;
			bool isLast = false;
			if(md == null) {
				md = new DevParamModel();
			} else if(
				  (strTypeDesc == md.typeDesc) &&
				  (strSubTypeDesc == md.subTypeDesc) &&
				  (strStatusDesc == md.statusDesc)
				  ) {
				isLast = true;
			} else {
				md = new DevParamModel();
			}

			if(!isLast) {
				md.type = type;
				//md.subType = (DeviceType)eSubType;
				md.uiType = uiType;
				md.imgType = imgType;
				//md.statusName = statusName;
				md.addr = addr;
				minAddr = Math.Min(minAddr, addr);
				maxAddr = Math.Max(maxAddr, addr);
				md.valueType = valueType;
				md.showType = showType;
				md.ioType = ioType;
				md.canReset = strCanReset != "0";
				md.isShow = strIsShow != "0";
				md.subTypeIdx = subTypeIdx;
				md.statusIdx = statusIdx;
				md.statusDescWidth = statusDescWidth;
				md.typeDesc = strTypeDesc;
				md.subTypeDesc = strSubTypeDesc;
				md.statusDesc = strStatusDesc;
				md.shortSubTypeDesc = strShortSubTypeDesc;
				md.shortStatusDesc = strShortStatusDesc;
				md.defaultValue = strDefaultValue;
			}
			if(md.showType == ParamShowType.e_cbx) {
				md.mapCbx[strCbxValue] = new CbxModel() {
					value = strCbxValue,
					desc = strCbxDesc,
					shortDesc = strShortCbxDesc,
					warnLevel = warnLevel
				};
			}
			return md;
		}

		private string getCol(Dictionary<string, int> mapHead, List<string> arrCol, string strCol) {
			if(!mapHead.ContainsKey(strCol)) {
				return "";
			}

			int idx = mapHead[strCol];
			if(idx < 0 || idx >= arrCol.Count) {
				return "";
			}

			return arrCol[idx];
		}

	}
}
