using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using SystemX.Net.BaseProtocol;
using SystemX.Net.DB;

using CpTesterPlatform.CpLogUtil;

using static SystemX.Net.Platform.Common.Util.LogMessage;

namespace SystemX.Common.Log.Query
{
    /// <summary>
    /// Query Base Infomation
    /// </summary>
    /// 
    public class CallPreMadeQueryInfo
    {
        public bool bReadInfoState { set; get; }
        public bool bHasItem { set; get; }

        public bool bLoading { set; get; }

        private string strInfoFilePos;

        //TestID, TableName
        private Dictionary<string, int> dicIDInfo;
        //ID - FROM - QUERY TEXT - RETURN FIELD(INDEX OR FIELD NAME)
        private Dictionary<int, Tuple<string, string, string, string>> dicUserQueryItem;

        public CallPreMadeQueryInfo(string strGetInfoPath) 
        {
            strInfoFilePos = strGetInfoPath;

            dicIDInfo = new Dictionary<string, int>();
            dicUserQueryItem = new Dictionary<int, Tuple<string, string, string, string>>();

            bHasItem = false;
            bReadInfoState = false;
            bLoading = false;
        }
      
        public List<KeyValuePair<int, Tuple<string, string, string, string>>> GetUserQueryInfo(string strTestID)
        {
            if (dicIDInfo.Keys.Contains(strTestID))
                return dicUserQueryItem.ToList().FindAll(x => x.Value.Item1 == strTestID);
            else
                return null;
        }

        public Tuple<string, string> GetUserQueryText(string strTestID, List<string> LstParam = null)
        {
            string strResultQueryText = string.Empty;

            string strMakeQueryText = string.Empty;
            string strVarParam1 = string.Empty;

            try
            {
                if (bHasItem == false)
                    throw new Exception("User query no have item.");

                if (dicIDInfo.Keys.Contains(strTestID) == false)
                    throw new Exception("Can't find call id.");

                var getQuery = dicUserQueryItem.ToList().FindAll(x => x.Value.Item1 == strTestID);

                if (getQuery == null)
                    throw new Exception("Can't find [" + strTestID + "] ID user query.");

                //받은 파라미터 개수
                int nParamNum = LstParam != null ? LstParam.Count() : 0;

                string strQueryID = getQuery[0].Value.Item1;
                string strQueryFrom = getQuery[0].Value.Item2;
                strMakeQueryText = getQuery[0].Value.Item3;
                strVarParam1 = getQuery[0].Value.Item4;

                //From 부분 대체
                int nParamPos = 0;
                if (strQueryFrom.Length > 0)
                {
                    if (strMakeQueryText.IndexOf("@$UseFrom@$") < 0)
                        throw new Exception("Access table argument format [@$UseFrom@$] syntax does not exist.");

                    string[] strLstQueryForms = strQueryFrom.Split(';');

                    foreach (string strFormParam in strLstQueryForms)
                    {
                        if (strMakeQueryText.IndexOf("@$UseFrom@$") < 0)
                            throw new Exception("The number of parameters and the number of argument types do not match.");

                        strMakeQueryText = strMakeQueryText.Replace("@$UseFrom@$[" + (nParamPos + 1).ToString() + "]", strFormParam);

                        nParamPos++;
                    }
                }

                //사용자 입력 쿼리 텍스트 파라미터 개수 파악
                if (nParamNum > 0)
                {
                    int nQueryParamNum = 0;
                    string strTemp = strMakeQueryText;
                    while (true)
                    {
                        if (strTemp.IndexOf("@$PARAM@$") >= 0)
                            nQueryParamNum++;
                        else
                            break;

                        strTemp = strTemp.Remove(strTemp.IndexOf("@$PARAM@$"), 12);
                    }

                    if (nParamNum != nQueryParamNum)
                        throw new Exception("The number of parameters does not match.");

                    //파라미터 위치 값으로 대체
                    nParamPos = 0;
                    foreach (string strParamValue in LstParam)
                    {
                        strMakeQueryText = strMakeQueryText.Replace("@$PARAM@$[" + (nParamPos + 1).ToString() + "]", strParamValue);

                        nParamPos++;
                    }
                }
            }
            catch
            {
                ;//
            }
            finally
            {
                strResultQueryText = strMakeQueryText;
            }

            //Query Text, Return Field Pos or Field Name
            return new Tuple<string, string>(strResultQueryText, strVarParam1);
        }

        private void GetUserQueryItemInfo(List<XElement> ListGetElement)
        {
            bLoading = true;

            dicIDInfo.Clear();
            dicUserQueryItem.Clear();

            int nSetPos = 0;
            foreach (var getXElement in ListGetElement)
            {
                bHasItem = true;

                string strBaseID = getXElement.Attribute("ID").Value;
                string strUseFrom = getXElement.Attribute("UseFrom").Value;

                dicIDInfo.Add(strBaseID, nSetPos);

                if (getXElement.Elements().ToList().Count == 1)
                {
                    for (int i = 0; i < getXElement.Elements().ToList().Count; i++)
                    {
                        string strQueryText = getXElement.Element("QueryDetail").Attribute("QueryText").Value;
                        string strVarParam1 = getXElement.Element("QueryDetail").Attribute("ReturnField").Value;

                        dicUserQueryItem.Add(nSetPos++,
                        new Tuple<string, string, string, string>(
                            strBaseID,
                            strUseFrom,
                            strQueryText,
                            strVarParam1));
                    }
                }
                else
                    throw new Exception("Need only one by one Query-Information!");
            }

            bLoading = false;
        }

        public bool Load()
        {
            bReadInfoState = true;

            try
            {
                XDocument xDoc = XDocument.Load(strInfoFilePos);
                var xElement = xDoc.Element("ROOT");

                if (xElement != null)
                {
                    var ListGetElement = xElement.Elements("UserQueryItem").ToList();

                    GetUserQueryItemInfo(ListGetElement);
                }
            }
            catch (Exception ex)
            {
                bReadInfoState = false;

                MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"UserQueryItem read failed. [SystemX.Common.Protocol.Log.Query : UserQueryInfo.Load]\r\n" + ex.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);
            }

            return bReadInfoState;
        }
    }
}
