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

namespace NewsCrawler
{
	public class CodeList
	{
		public enum CODE_TYPE
		{
			NONE = 0,
			ORIGINAL = NONE,
			DENIAL = 1<<0,
			DUPLICATED = 1<<1,
			MANUAL = 1<<2,
		}

		public class CODE_VALUE
		{
			public CODE_TYPE m_enType;
			public string m_strCode;
			public string m_strName;

			override public string ToString()
			{
				return string.Format("{0}:{1}", m_strCode, m_strName);
			}
		}

		class SYNONYM_VALUE
		{
			public string m_strCode;
			public string m_strName;
		}


		CPUTILLib.CpStockCode m_StockCode = new CPUTILLib.CpStockCode();
		List<CODE_VALUE> m_CodeList = new List<CODE_VALUE>();
		List<SYNONYM_VALUE> m_SynonymList = new List<SYNONYM_VALUE>();

		public CodeList()
		{
			MakeList();
			LoadManualList();
			LoadDenialList();
			LoadDuplicatedList();
			LoadSynonym();
			Test();
		}

		void Test()
		{
			if(Util.IsDebugging() == false)
				return;

			SearchCode("[클릭 e종목]로엔, 본격적으로 시작되는 카카오 시너");
			SearchCode("[클릭 e종목]\"SK텔레콤, 투자심리 개선 가능성 주목해");
			SearchCode("[클릭 e종목]SK하이닉스, 추가 상승 낙관적");
			SearchCode("MBK, 45억 규모 유상증자 결정");
			SearchCode("다음주 코스피 1960~1990…산유량 감산여부에 주목");
		}

		void MakeList()
		{
			int iCnt = m_StockCode.GetCount();
			for(short i = 0; i<iCnt; i++)
			{
				CODE_VALUE Code = new CODE_VALUE();
				Code.m_enType = CODE_TYPE.ORIGINAL;
				Code.m_strCode = m_StockCode.GetData(0, i);
				Code.m_strName = m_StockCode.GetData(1, i);

				if(Code.m_strCode[0] == 'A')
					m_CodeList.Add(Code);
			}
		}

		void LoadCodeType(string strPath, CODE_TYPE enType)
		{
			m_CodeList.ForEach(a => a.m_enType &= ~enType);

			if(File.Exists(strPath) == false)
				return;

			string[] aLines = File.ReadAllLines(strPath);
			foreach(string strLine in aLines)
			{
				if(strLine.Trim().Length <= 0)
					continue;

				CODE_VALUE code = m_CodeList.Find(s => s.m_strName == strLine.Trim());
				if(code == null)
				{
					Util.Log(Util.LOG_TYPE.ERROR, string.Format("[code-{0}] 존재하지 않는 기업명입니다. ({1})", enType.ToString().ToLower(), strLine));
					continue;
				}

				code.m_enType |= enType;
			}
		}

		public void LoadManualList()
		{
			string strPath = Util.GetConfigPath()+"/code-manual.txt";
			LoadCodeType(strPath, CODE_TYPE.MANUAL);
		}

		public void LoadDenialList()
		{
			string strPath = Util.GetConfigPath()+"/code-deny.txt";
			LoadCodeType(strPath, CODE_TYPE.DENIAL);
		}

		public void LoadDuplicatedList()
		{
			string strPath = Util.GetConfigPath()+"/code-duplicated.txt";
			LoadCodeType(strPath, CODE_TYPE.DUPLICATED);
		}

		public bool IsBuyableCode(CODE_VALUE Code)
		{
			return ((Code.m_enType & CODE_TYPE.DENIAL) | (Code.m_enType & CODE_TYPE.DUPLICATED)) == CODE_TYPE.NONE;
		}

		public void AddDuplicatedList(string strCode, string strName)
		{
			CODE_VALUE Result = m_CodeList.Find(s => s.m_strCode == strCode);
			if(Result == null)
				return;

			if((Result.m_enType & CODE_TYPE.DUPLICATED) == CODE_TYPE.DUPLICATED)
				return;

			Result.m_enType |= CODE_TYPE.DUPLICATED;

			string strPath = Util.GetConfigPath()+"/code-duplicated.txt";
			File.AppendAllText(strPath, strName+Environment.NewLine);
		}

		public void MakeManualList(int iPrice)
		{
			m_CodeList.ForEach(a => a.m_enType &= ~CODE_TYPE.MANUAL);

			List<string> ReqList = new List<string>();

			int iCnt = 0;
			string strCodes = "";
			foreach(CODE_VALUE code in m_CodeList)
			{
				if(code.m_enType == CODE_TYPE.ORIGINAL)
				{
					strCodes += code.m_strCode;
					iCnt++;
				}	

				if(iCnt >= 110)
				{
					ReqList.Add(strCodes);
					strCodes = "";
					iCnt=0;
				}
			}

			if(iCnt > 0)
			{
				ReqList.Add(strCodes);
				strCodes = "";
				iCnt=0;
			}

			DSCBO1Lib.StockMstm stockMstM = new DSCBO1Lib.StockMstm();
			foreach(string codelist in ReqList)
			{
				stockMstM.SetInputValue(0, codelist);
				stockMstM.BlockRequest2(0);
				int iReturnCnt = stockMstM.GetHeaderValue(0);
				for(int i = 0; i<iReturnCnt; i++)
				{
					int iCurPrice = stockMstM.GetDataValue(4, i);
					if(iCurPrice >= iPrice)
					{
						string strCode = stockMstM.GetDataValue(0, i);
						m_CodeList.FindAll(s => s.m_strCode == strCode).ForEach(s => s.m_enType |= CODE_TYPE.MANUAL);
					}
				}
			}

			string strContents = "";
			m_CodeList.FindAll(s => (s.m_enType & CODE_TYPE.MANUAL) == CODE_TYPE.MANUAL)
				.ForEach(s => strContents += (s.m_strName+Environment.NewLine));

			string strPath = Util.GetConfigPath() + "/code-manual.txt";
			File.WriteAllText(strPath, strContents, new System.Text.UTF8Encoding(true));
		}

		public void LoadSynonym()
		{
			string strPath = Util.GetConfigPath() + "/code-synonym.txt";
			if(File.Exists(strPath) == true)
			{
				string[] aLines = File.ReadAllLines(strPath);
				foreach(string line in aLines)
				{
					string[] aTokens = line.Trim().Split('=');
					if(aTokens != null && aTokens.Length == 2)
					{
						string strSysnonym = aTokens[0].Trim();
						string strOrg = aTokens[1].Trim();
						CODE_VALUE Result = m_CodeList.Find(s => s.m_strName==strOrg);
						if(Result == null)
						{
							Util.Log(Util.LOG_TYPE.ERROR, string.Format("[code-synonym] 존재하지 않는 기업명입니다. ({0})", strOrg));
							continue;
						}

						SYNONYM_VALUE Code = new SYNONYM_VALUE();
						Code.m_strCode = Result.m_strCode;
						Code.m_strName = strSysnonym;
						m_SynonymList.Add(Code);
					}
				}
			}
		}

		public CODE_VALUE SearchCode(string strText)
		{
			CODE_VALUE Result = m_CodeList.Find(s => strText.Contains(s.m_strName));
			if(Result != null)
				return Result;

			SYNONYM_VALUE Synonym = m_SynonymList.Find(s => strText.Contains(s.m_strName));
			if(Synonym == null)
				return null;

			return m_CodeList.Find(s => s.m_strCode == Synonym.m_strCode);
		}

		public CODE_VALUE GetCode(string strCode)
		{
			CODE_VALUE Result = m_CodeList.Find(s => s.m_strCode == strCode);
			return Result;
		}
	}
}
