using CPSYSDIBLib;
using DSCBO1Lib;
using OfficeOpenXml;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AutoSellerNS
{
	class SimulationHelper
	{
		CybosHelper m_CybosHelper = null;
		RichTextBox m_tbLogView = null;

		public SimulationHelper(CybosHelper CybosHelper, RichTextBox tbLog)
		{
			m_CybosHelper = CybosHelper;
			m_tbLogView = tbLog;
		}

		public void LoadTxt()
		{
			List<string> aItems = new List<string>();
			StockChart CPStockChart = new StockChart();

			foreach(string strLine  in File.ReadLines(Util.GetSimulationPath()+"/0-input.txt", Encoding.UTF8))
			{
				var tokens = strLine.Split('\t');

				var strDate = tokens[0];
				var strNewTime = tokens[1];
				var strSimulationTime = tokens[2];
				var strCodeName = tokens[3];
				var strCode = tokens[4];
				var strStartPrice = tokens[5];

				DateTime StartDT;
				DateTime.TryParse(strDate+" "+strSimulationTime, out StartDT);
				uint uiStartDate;
				uint.TryParse(StartDT.ToString("yyyyMMdd"), out uiStartDate);

				string strOutFileName = Util.GetSimulationPath() + "/" + strCodeName + "-" + StartDT.ToString("yyyy-MM-dd") + ".txt";
				if(File.Exists(strOutFileName) == true)
					continue;

				CPStockChart.SetInputValue(0, "A"+strCode);
				CPStockChart.SetInputValue(1, '1');
				CPStockChart.SetInputValue(2, uiStartDate);
				CPStockChart.SetInputValue(3, uiStartDate);
				CPStockChart.SetInputValue(4, 100000);
				CPStockChart.SetInputValue(5, new int[] { 0, 1, 5, 8, 9, 10, 11 });
				CPStockChart.SetInputValue(6, 'T');
				CPStockChart.BlockRequest2(0);

				int iFieldCnt = CPStockChart.GetHeaderValue(1);
				string[] astrFieldName = CPStockChart.GetHeaderValue(2);

				string strOutLine = "";
				for(int j = 0; j<iFieldCnt; j++)
				{
					strOutLine += astrFieldName[j];
					strOutLine += '\t';
				}
				File.AppendAllText(strOutFileName, strOutLine+Environment.NewLine, new UTF8Encoding(true));
				strOutLine = "";

				bool bContinue = true;
				while(bContinue == true)
				{
					int iCnt = CPStockChart.GetHeaderValue(3);
					for(int i = 0; i<iCnt; i++)
					{
						for(int j = 0; j<iFieldCnt; j++)
						{
							strOutLine += CPStockChart.GetDataValue(j, i);
							strOutLine += '\t';
						}

						strOutLine += Environment.NewLine;

						if(i % 1000 == 999)
						{
							File.AppendAllText(strOutFileName, strOutLine, new UTF8Encoding(true));
							strOutLine = "";
						}
					}

					bContinue = (CPStockChart.Continue==1);
					if(bContinue == true)
						CPStockChart.BlockRequest2(0);

					m_tbLogView.AppendText(string.Format("RequestRQ({0})", m_CybosHelper.GetLimitRemainCountRQ()));
				}

				if(strOutLine.Length > 0)
				{
					File.AppendAllText(strOutFileName, strOutLine, new UTF8Encoding(true));
					strOutLine = "";
				}

				m_tbLogView.AppendText(string.Format("[Load] " + strOutFileName + " End"));
			}

			m_tbLogView.AppendText(string.Format("[Load] All End"));
		}

		public void LoadExcel()
		{
			List<string> aItems = new List<string>();
			StockChart CPStockChart = new StockChart();
			ExcelHandler Excel = null;

			foreach(string strLine in File.ReadLines(Util.GetSimulationPath()+"/0-input.txt", Encoding.UTF8))
			{
				var tokens = strLine.Split('\t');

				var strDate = tokens[0];
				var strNewTime = tokens[1];
				var strSimulationTime = tokens[2];
				var strCodeName = tokens[3];
				var strCode = tokens[4];
				var strStartPrice = tokens[5];

				DateTime StartDT;
				DateTime.TryParse(strDate+" "+strSimulationTime, out StartDT);

				string strOutFileName = Util.GetSimulationPath() + "/" + strCodeName + "-" + StartDT.ToString("yyyy-MM-dd") + ".xlsx";
				if(File.Exists(strOutFileName) == true)
				{
					if(StartDT.DayOfYear == DateTime.Now.DayOfYear)
						File.Delete(strOutFileName);
					else
						continue;
				}

				CPStockChart.SetInputValue(0, "A"+strCode);
				CPStockChart.SetInputValue(1, '1');
				CPStockChart.SetInputValue(2, StartDT.ToString("yyyyMMdd"));
				CPStockChart.SetInputValue(3, StartDT.ToString("yyyyMMdd"));
				CPStockChart.SetInputValue(5, new int[] { 0, 1, 5, 8, 9, 10, 11 });
				CPStockChart.SetInputValue(6, 'T');
				CPStockChart.BlockRequest2(0);

				int iFieldCnt = CPStockChart.GetHeaderValue(1);
				string[] astrFieldName = CPStockChart.GetHeaderValue(2);
				List<object> aRow = new List<object>();
				List<object[]> aaRows = new List<object[]>();

				Excel = new ExcelHandler(strOutFileName, astrFieldName);

				bool bContinue = true;
				while(bContinue == true)
				{
					int iCnt = CPStockChart.GetHeaderValue(3);
					for(int i = 0; i<iCnt; i++)
					{
						for(int j = 0; j<iFieldCnt; j++)
							aRow.Add(CPStockChart.GetDataValue(j, i));

						if(aaRows.Count == 0)
						{
							aRow.Add(0);
							aRow.Add(0);
						}
						else
						{
							aRow.Add((uint)aaRows.Last()[5]-(uint)aRow[5]);
							aRow.Add((uint)aaRows.Last()[6]-(uint)aRow[6]);
						}

						aaRows.Add(aRow.ToArray());
						aRow.Clear();	
					}

					bContinue = (CPStockChart.Continue==1);
					if(bContinue == true)
						CPStockChart.BlockRequest2(0);

					m_tbLogView.AppendText(string.Format("RequestRQ({0})\n", m_CybosHelper.GetLimitRemainCountRQ()));
				}

				aaRows.Reverse();
				Excel.AddRows(aaRows.ToArray());

				m_tbLogView.AppendText(string.Format("[Load] " + strOutFileName + " End\n"));
			}

			m_tbLogView.AppendText(string.Format("[Load] All End\n\n"));
			m_tbLogView.SelectionStart = m_tbLogView.TextLength;
			m_tbLogView.ScrollToCaret();
		}

		public void LoadExcel2()
		{
			List<string> aItems = new List<string>();
			StockBid CPStockBid = new StockBid();
			ExcelHandler Excel = null;

			foreach(string strLine in File.ReadLines(Util.GetSimulationPath()+"/0-input.txt", Encoding.UTF8))
			{
				var tokens = strLine.Split('\t');

				var strDate = tokens[0];
				var strNewTime = tokens[1];
				var strSimulationTime = tokens[2];
				var strCodeName = tokens[3];
				var strCode = tokens[4];
				var strStartPrice = tokens[5];

				DateTime StartDT;
				DateTime.TryParse(strDate+" "+strSimulationTime, out StartDT);

				string strOutFileName = Util.GetSimulationPath() + "/" + strCodeName + "-" + StartDT.ToString("yyyy-MM-dd") + ".xlsx";
				if(File.Exists(strOutFileName) == true)
				{
					if(StartDT.DayOfYear == DateTime.Now.DayOfYear)
						File.Delete(strOutFileName);
					else
						continue;
				}

				CPStockBid.SetInputValue(0, "A"+strCode);
				CPStockBid.SetInputValue(2, 20000);
				CPStockBid.SetInputValue(3, 'C');
				CPStockBid.SetInputValue(4, "2000");
				CPStockBid.BlockRequest2(0);

				List<object[]> aaRows = new List<object[]>();

				bool bContinue = true;
				while(bContinue)
				{
					int iCnt = CPStockBid.GetHeaderValue(2);
					for(int i = 0; i<iCnt; i++)
					{
						var Time = (uint)(int)CPStockBid.GetDataValue(9, i);
						var AskPrice = CPStockBid.GetDataValue(2, i);
						var BidPrice = CPStockBid.GetDataValue(3, i);
						var CurPrice = CPStockBid.GetDataValue(4, i);
						var AccDealCount = CPStockBid.GetDataValue(5, i);
						var Flag = CPStockBid.GetDataValue(10, i) == '1' ? "*" : "";
						var DealCount = CPStockBid.GetDataValue(6, i);

						aaRows.Add(new object[]{ Time, Flag, CurPrice, AskPrice, BidPrice, AccDealCount, DealCount,  });
					}

					bContinue = (CPStockBid.Continue == 1);
					if(bContinue == true)
					{
						while(m_CybosHelper.GetLimitRemainCountRQ() < 2)
							Thread.Sleep(100);
						CPStockBid.BlockRequest2(0);
					}

					m_tbLogView.AppendText(string.Format("RequestRQ({0})\n", m_CybosHelper.GetLimitRemainCountRQ()));
				}

				aaRows.Reverse();

				Excel = new ExcelHandler(strOutFileName, new string[]{ "시간", "동시호가", "현재가", "매도호가", "매수호가", "거래량", "순간체결량" });
				Excel.AddRows(aaRows.ToArray());

				m_tbLogView.AppendText(string.Format("[Load] " + strOutFileName + " End\n"));
			}

			m_tbLogView.AppendText(string.Format("[Load] All End\n\n"));
			m_tbLogView.SelectionStart = m_tbLogView.TextLength;
			m_tbLogView.ScrollToCaret();
		}

		public void StartSimuation()
		{
			m_tbLogView.AppendText(string.Format("[시뮬레이션 시작] 조건 : {0}회, 트레일링 : {1}%, {2}회\n", Config.GetBidCount(), Config.GetTrailingRate(), Config.GetTrailingCnt()));

			int iTotalProfit = 0;
			int iTotalBid = 0;

			foreach(string strLine in File.ReadLines(Util.GetSimulationPath()+"/0-input.txt", Encoding.UTF8))
			{
				var tokens = strLine.Split('\t');

				var strDate = tokens[0];
				var strNewTime = tokens[1];
				var strSimulationTime = tokens[2];
				var strCodeName = tokens[3];
				var strCode = tokens[4];
				var strStartPrice = tokens[5];

				DateTime StartDT;
				DateTime.TryParse(strDate+" "+strSimulationTime, out StartDT);

				int iStartPrice;
				int.TryParse(strStartPrice, NumberStyles.AllowThousands, CultureInfo.CurrentCulture, out iStartPrice);

				string strFileName = Util.GetSimulationPath() + "/" + strCodeName + "-" + StartDT.ToString("yyyy-MM-dd") + ".xlsx";


				FileInfo newFile = new FileInfo(strFileName);
				ExcelPackage package = new ExcelPackage(newFile);
				ExcelWorksheet Sheet = package.Workbook.Worksheets["sheet"];

				int iMaxRow = Sheet.Dimension.Rows;

				DateTime RowDT;
				bool bStart = false;
				int iTotalAskCount = 0;
				int iTotalBidCount = 0;
				int iPrevAskCount = 0;
				int iPrevBidCount = 0;
				bool bBid = false;
				int iAskCount = 0;
				int iTrailingCount = 0;
				int iMaxPrice = int.MinValue;
				int iStockCount = 0;
				int iStartRow = 0;
				int iPrevPrice = 0;
				for(int iRow = 2; iRow<=iMaxRow; iRow++)
				{
					int iTime = (int)(double)Sheet.Cells[iRow, 2].Value;
					int iPrice = (int)(double)Sheet.Cells[iRow, 3].Value;
					iTotalAskCount = (int)(double)Sheet.Cells[iRow, 6].Value;
					iTotalBidCount = (int)(double)Sheet.Cells[iRow, 7].Value;

					bBid = (iTotalAskCount == iPrevAskCount);
					DateTime.TryParse(strDate+" "+string.Format("{0}:{1}:{2}", iTime/100, iTime%100, 59), out RowDT);

					iStockCount = 1000000/iStartPrice;

					if(bStart == false)
					{
						if(RowDT >= StartDT && iPrice==iStartPrice)
						{
							bStart = true;
							iStartRow = iRow;
						}
					}
					else
					{
						if(bBid == false)
							iAskCount++;
						else
							iAskCount = 0;

						if(iAskCount >= Config.GetBidCount())
						{
							m_tbLogView.AppendText(string.Format("[{0,-10}] 조건 매도 {1} line:{2} {3:n0}원 ({4} : {5:n2}%) (매수 : {6:n0}원, line:{7})\n",
								strCodeName,
								RowDT.ToString("yyyy-MM-dd HH:mm:00"), 
								iRow, 
								iPrice, 
								iPrice-iStartPrice,
								(iPrice-iStartPrice)*100/(float)iStartPrice,
								iStartPrice,
								iStartRow
								));
							iTotalProfit += (iPrice-iStartPrice)*iStockCount;
							iTotalBid += iStartPrice*iStockCount;
							break;
						}

						if(iPrice > iMaxPrice)
							iTrailingCount = 0;
						else if(iPrice <= iMaxPrice*(100-Config.GetTrailingRate())/100)
							iTrailingCount++;
						iMaxPrice = Math.Max(iPrice, iMaxPrice);

						if(iTrailingCount >= Config.GetTrailingCnt())
						{
							m_tbLogView.AppendText(string.Format("[{0}] 트레일링 매도 {1} line:{2} {3:n0}원 ({4} : {5:n2}%) (매수 : {6:n0}원, line:{7})\n", 
								strCodeName, 
								RowDT.ToString("yyyy-MM-dd HH:mm:00"), 
								iRow, 
								iPrice, 
								iPrice-iStartPrice,
								(iPrice-iStartPrice)*100/(float)iStartPrice,
								iStartPrice,
								iStartRow
								));
							iTotalProfit += (iPrice-iStartPrice)*iStockCount;
							iTotalBid += iStartPrice*iStockCount;
							break;
						}
					}

					iPrevPrice = iPrice;
					iPrevAskCount = iTotalAskCount;
					iPrevBidCount = iTotalBidCount;
				}
			}

			m_tbLogView.AppendText(string.Format("[시뮬레이션 종료] 총수익 : {0:n0}원 : {1:n2}%\n\n", iTotalProfit, iTotalProfit*100/(float)iTotalBid));
			m_tbLogView.SelectionStart = m_tbLogView.TextLength;
			m_tbLogView.ScrollToCaret();
		}

		public void StartSimuation2()
		{
			m_tbLogView.AppendText(string.Format("[시뮬레이션 시작] 조건 : {0}회, 트레일링 : {1}%, {2}회\n", Config.GetBidCount(), Config.GetTrailingRate(), Config.GetTrailingCnt()));

			int iTotalProfit = 0;
			int iTotalBid = 0;

			foreach(string strLine in File.ReadLines(Util.GetSimulationPath()+"/0-input.txt", Encoding.UTF8))
			{
				var tokens = strLine.Split('\t');

				var strDate = tokens[0];
				var strNewTime = tokens[1];
				var strSimulationTime = tokens[2];
				var strCodeName = tokens[3];
				var strCode = tokens[4];
				var strStartPrice = tokens[5];

				DateTime StartDT;
				DateTime.TryParse(strDate+" "+strSimulationTime, out StartDT);

				int iStartPrice;
				int.TryParse(strStartPrice, NumberStyles.AllowThousands, CultureInfo.CurrentCulture, out iStartPrice);

				string strFileName = Util.GetSimulationPath() + "/" + strCodeName + "-" + StartDT.ToString("yyyy-MM-dd") + ".xlsx";


				FileInfo newFile = new FileInfo(strFileName);
				ExcelPackage package = new ExcelPackage(newFile);
				ExcelWorksheet Sheet = package.Workbook.Worksheets["sheet"];

				int iMaxRow = Sheet.Dimension.Rows;

				DateTime RowDT = DateTime.Now;
				List<DateTime> aPrevDT = new List<DateTime>();

				bool bStart = false;
				int iAskCount = 0;
				int iAskDownCount = 0;
				int iDealCountInSec = 0;

				int iTrailingCount = 0;
				int iMaxPrice = int.MinValue;
				int iStockCount = 0;
				int iStartRow = 0;
				int iPrevPrice = 0;
				bool bPrevAsk = false;
				int iMaxAskPrice = 0;

				int iPrevAskPrice = 0;

				for(int iRow = 2; iRow<=iMaxRow; iRow++)
				{
					int iTime = (int)(double)Sheet.Cells[iRow, 1].Value;
					int iPrice = (int)(double)Sheet.Cells[iRow, 3].Value;
					int iAskPrice = (int)(double)Sheet.Cells[iRow, 4].Value;
					int iBidPrice = (int)(double)Sheet.Cells[iRow, 5].Value;

					DateTime.TryParse(strDate+" "+string.Format("{0}:{1}:{2}", iTime/10000, (iTime/100)%100, iTime%100), out RowDT);

					iStockCount = 1000000/iStartPrice;

					if(bStart == false)
					{
						if(RowDT >= StartDT && iPrice==iStartPrice)
						{
							bStart = true;
							iStartRow = iRow;
							iMaxAskPrice = iAskPrice;
							iPrevAskPrice = iAskPrice;
						}
					}
					else
					{
						//// 체결가 비교
						//if(iPrice > iPrevPrice)
						//{
						//	iAskCount = 0;
						//	bPrevAsk = false;
						//}
						//else if(iPrice < iPrevPrice)
						//{
						//	iAskCount++;
						//	bPrevAsk = true;
						//}
						//else if(bPrevAsk == true)
						//{
						//	iAskCount++;
						//}

						//// 호가 비교 - 중간 유지
						//if(iPrice >= iAskPrice)
						//{
						//	iAskCount = 0;
						//	bPrevAsk = false;
						//}
						//else if(iPrice <= iBidPrice)
						//{
						//	iAskCount++;
						//	bPrevAsk = true;
						//}
						//else if(bPrevAsk == true)
						//{
						//	iAskCount++;
						//}

						// 호가 비교 - 매수호가 기준
						if(iPrice <= iBidPrice)
							iAskCount++;
						else
							iAskCount = 0;

						//// 호가 비교 - 매도호가 기준
						//if(iPrice < iAskPrice)
						//	iAskCount++;
						//else
						//	iAskCount = 0;

						//// 매도호가 최고가 미만 연속
						//if(iAskPrice < iMaxAskPrice)
						//	iAskDownCount++;
						//else
						//	iAskDownCount=0;
						//iMaxAskPrice = Math.Max(iMaxAskPrice, iAskPrice);

						//// 매도호가 최고가 미만 누적
						//if(iAskPrice < iMaxAskPrice)
						//	iAskDownCount++;
						//int iNextMaxAskPrice = Math.Max(iMaxAskPrice, iAskPrice);
						//if(iNextMaxAskPrice > iMaxAskPrice)
						//	iAskDownCount = 0;
						//iMaxAskPrice = iNextMaxAskPrice;

						//// 매도호가 하락 - 최고 갱신시 리셋
						//if(iAskPrice < iPrevAskPrice)
						//	iAskDownCount++;
						//int iNextMaxAskPrice = Math.Max(iMaxAskPrice, iAskPrice);
						//if(iNextMaxAskPrice > iMaxAskPrice)
						//	iAskDownCount = 0;
						//iMaxAskPrice = iNextMaxAskPrice;

						//if(PrevRowDT.Second == RowDT.Second)
						//	iDealCountInSec++;
						//else
						//	iDealCountInSec = 1;

						if(iAskCount >= Config.GetBidCount())
						{
							m_tbLogView.AppendText(string.Format("[{0,-10}] 조건1 매도 {1} line:{2} {3:n0}원 ({4} : {5:n2}%) (매수 : {6:n0}원, {7}, line:{8})\n",
								strCodeName,
								RowDT.ToString("yyyy-MM-dd HH:mm:ss"),
								iRow,
								iPrice,
								iPrice-iStartPrice,
								(iPrice-iStartPrice)*100/(float)iStartPrice,
								iStartPrice,
								StartDT.ToString("yyyy-MM-dd HH:mm:ss"),
								iStartRow
								));
							iTotalProfit += (iPrice-iStartPrice)*iStockCount;
							iTotalBid += iStartPrice*iStockCount;
							break;
						}

						//if(aPrevDT.Count > 3 && aPrevDT.Last() - aPrevDT[aPrevDT.Count-3] > TimeSpan.FromSeconds(1) && iAskDownCount >= Config.GetBidCount())
						//if(iAskDownCount >= 5)
						//{
						//	m_tbLogView.AppendText(string.Format("[{0,-10}] 조건2 매도 {1} line:{2} {3:n0}원 ({4} : {5:n2}%) (매수 : {6:n0}원, {7}, line:{8})\n",
						//		strCodeName,
						//		RowDT.ToString("yyyy-MM-dd HH:mm:ss"),
						//		iRow,
						//		iPrice,
						//		iPrice-iStartPrice,
						//		(iPrice-iStartPrice)*100/(float)iStartPrice,
						//		iStartPrice,
						//		StartDT.ToString("yyyy-MM-dd HH:mm:ss"),
						//		iStartRow
						//		));
						//	iTotalProfit += (iPrice-iStartPrice)*iStockCount;
						//	iTotalBid += iStartPrice*iStockCount;
						//	break;
						//}

						if(iPrice > iMaxPrice)
							iTrailingCount = 0;
						else if(iPrice <= iMaxPrice*(100-Config.GetTrailingRate())/100)
							iTrailingCount++;
						iMaxPrice = Math.Max(iPrice, iMaxPrice);

						if(iTrailingCount >= Config.GetTrailingCnt())
						{
							m_tbLogView.AppendText(string.Format("[{0}] 트레일링 매도 {1} line:{2} {3:n0}원 ({4} : {5:n2}%) (매수 : {6:n0}원, {7} line:{8})\n",
								strCodeName,
								RowDT.ToString("yyyy-MM-dd HH:mm:ss"),
								iRow,
								iPrice,
								iPrice-iStartPrice,
								(iPrice-iStartPrice)*100/(float)iStartPrice,
								iStartPrice,
								StartDT.ToString("yyyy-MM-dd HH:mm:ss"),
								iStartRow
								));
							iTotalProfit += (iPrice-iStartPrice)*iStockCount;
							iTotalBid += iStartPrice*iStockCount;
							break;
						}
					}

					iPrevPrice = iPrice;
					iPrevAskPrice = iAskPrice;
					aPrevDT.Add(RowDT);
					if(aPrevDT.Count > 15)
						aPrevDT.RemoveAt(0);
				}
			}

			m_tbLogView.AppendText(string.Format("[시뮬레이션 종료] 총수익 : {0:n0}원 : {1:n2}%\n\n", iTotalProfit, iTotalProfit*100/(float)iTotalBid));
			m_tbLogView.SelectionStart = m_tbLogView.TextLength;
			m_tbLogView.ScrollToCaret();
		}
	}
}

