using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using System.Text.RegularExpressions;
using System.Data.SqlClient;
using System.Collections.Concurrent;
using System.Diagnostics;

namespace BEMSDataGateway
{
    class Expression_Process
    {
        private string[] temp;
        LogFileCreate LFC = new LogFileCreate();
        // CSV파일을 읽는 메서드
        public void ReadCSV_Passing_Expression(IDictionary<string, float[]> AllDic, string Hour, int NowMin, string Table_Type, IDictionary<string, string> MatchingDic)
        {
            Stopwatch SW = new Stopwatch();
            StreamReader sr = new StreamReader("Expression.csv", Encoding.GetEncoding("euc-kr"));
            Parsing Ps = new Parsing();
            My_DB_DML MDD = new My_DB_DML();

            string[] tempId = new string[4];
            string strcon = MDD.ConnDBInfo();
            string query = "";

            string TempExp = "";
            string ResultValue = "";
            string[] Store_Type = new string[3];

            int Count = 0;
            SW.Reset(); // 
            SW.Start();
            while (!sr.EndOfStream) // Stream의 끝이 올때까지 반복
            {
                //s의 형태는 '1/XXX/식/가상관제점' 의 포맷으로 되어있음
                string s = sr.ReadLine(); // 한줄을 읽음.                
                temp = s.Split(',');        // Split() 메서드를 이용하여 ',' 구분하여 잘라냄              
                //temp[0] = 일련번호
                //temp[1] = 데이터 삽입 형태 (15분 단위냐,, 1시간단위냐,, 하루단위냐..)
                //temp[2] = 성능분석식 및 단위 환산 부
                //temp[3] = 1.100.4900.30 // 순서대로 SiteId.FacilityTypeId.FacilityCode.PropertyId 의 순서임.  

                tempId = temp[3].Split('.');
                string Virtual_SiteId = tempId[0];
                string Virtual_FacilityTypeId = tempId[1];
                string Virtual_FacilityCode = tempId[2];
                string Virtual_PropertyId = tempId[3];

                Store_Type = temp[1].Split('.');

                if (!("".Equals(s))) // 읽은 값이 null이 아닌 경우.
                {
                    object resultexp = 0;

                    MSScriptControl.ScriptControl sc = new MSScriptControl.ScriptControl(); // Script를 사용할 수 있게 만드는 스크립트 컨트롤을 객체 선언
                    sc.Language = "VBScript"; // 사용할 스크립트 언어는 Visaul Basic Script

                    string Pattern = "Tag" + @"\d{1,5}";

                    Regex regex = new Regex(Pattern);

                    // 불러들인 수식에서 포인트 명을 값으로...
                    foreach (Match match in regex.Matches(temp[2]))
                    {
                        string Tag_Name = Convert.ToString(match); //Matching 된 값을 string형식으로 변환. Tag_name 은 Tag1, Tag2 등등....

                        if (Table_Type == "Raw" && Store_Type[0] == "T")
                        {
                            temp[2] = temp[2].Replace(Tag_Name, AllDic[MatchingDic[Tag_Name]][0].ToString()); // 파싱한 식의 값을 Tag를 '값'으로 치환 // [Key] = TagXXX [Value] = 1.1.4478.xxx
                            Count++;
                        }
                        else if (Table_Type == "FiftMin" && Store_Type[1] == "T")
                        {
                            int Array_Value_Select = Ps.Select_MinTime_Data(NowMin); //시간에 따른 Array 변수뽑아냄
                            temp[2] = temp[2].Replace(Tag_Name, AllDic[MatchingDic[Tag_Name]][Array_Value_Select].ToString()); // 파싱한 식의 값을 Tag를 '값'으로 치환
                            Count++;
                        }
                        else if (Table_Type == "Hour" && Store_Type[2] == "T" && NowMin == 00)
                        {

                            temp[2] = temp[2].Replace(Tag_Name, AllDic[MatchingDic[Tag_Name]][12].ToString());
                            Count++;
                        }
                        else if (Table_Type == "Daily" && Store_Type[3] == "T")
                        {
                            temp[2] = temp[2].Replace(Tag_Name, AllDic[MatchingDic[Tag_Name]][12].ToString());
                            Count++;
                        }
                    }
                    if (Count > 0)
                    {
                        TempExp = temp[2];
                        resultexp = sc.Eval(TempExp); // 문자열 값을 계산    
                        ResultValue = Convert.ToString(Math.Round(Convert.ToDouble(resultexp), 4, MidpointRounding.AwayFromZero));

                        using (SqlConnection conn = new SqlConnection(strcon))
                        {
                            conn.Open();
                            string InsertDate = DateTime.Now.ToString("yyyy-MM-dd HH:" + NowMin + ":00.000");

                            switch (Table_Type)
                            {
                                case "Raw":
                                    query = "INSERT INTO " + Table.RawT + "(SiteId,FacilityTypeId,FacilityCode,PropertyId,CreatedDateTime,CurrentValue) "
                                                    + "VALUES(" + Virtual_SiteId + "," + Virtual_FacilityTypeId + "," + Virtual_FacilityCode + "," + Virtual_PropertyId + ",'" + InsertDate + "'," + ResultValue + ")";
                                    SqlCommand cmd = new SqlCommand(query, conn);
                                    //LFC.Log("[Expression_Process.cs] Query : " + query + Environment.NewLine);
                                    cmd.ExecuteNonQuery();
                                    cmd.Dispose();
                                    conn.Close();
                                    conn.Dispose();
                                    break;

                                case "FiftMin":
                                    query = "INSERT INTO " + Table.FiFt + "(SiteId,FacilityTypeId,FacilityCode,PropertyId,CreatedDateTime,CurrentValue) "
                                                    + "VALUES(" + Virtual_SiteId + "," + Virtual_FacilityTypeId + "," + Virtual_FacilityCode + "," + Virtual_PropertyId + ",'" + InsertDate + "'," + ResultValue + ")";
                                    SqlCommand cmd1 = new SqlCommand(query, conn);
                                    //LFC.Log("[Expression_Process.cs] Query : " + query + Environment.NewLine);
                                    cmd1.ExecuteNonQuery();
                                    cmd1.Dispose();
                                    conn.Close();
                                    conn.Dispose();
                                    break;

                                case "Hour":
                                    query = "INSERT INTO " + Table.Hourly + "(SiteId,FacilityTypeId,FacilityCode,PropertyId,CreatedDateTime,CurrentValue) "
                                                    + "VALUES(" + Virtual_SiteId + "," + Virtual_FacilityTypeId + "," + Virtual_FacilityCode + "," + Virtual_PropertyId + ",'" + InsertDate + "'," + ResultValue + ")";
                                    SqlCommand cmd2 = new SqlCommand(query, conn);
                                    //LFC.Log("[Expression_Process.cs] Query : " + query + Environment.NewLine);
                                    cmd2.ExecuteNonQuery();
                                    cmd2.Dispose();
                                    conn.Close();
                                    conn.Dispose();
                                    break;
                                case "Daily":
                                    DB_Day_Update(Virtual_SiteId, Virtual_FacilityTypeId, Virtual_FacilityCode, Virtual_PropertyId, ResultValue, NowMin, Hour);
                                    break;
                            }
                        }
                    }
                    Count = 0;
                }
            }
            sr.Close();
            sr.Dispose();
            string sTemp5;
            SW.Stop();   // 현재 인스턴스가 측정한 총 경과 시간을 가져옵니다.
            sTemp5 = SW.Elapsed.ToString();
            if (Form1.Enable_EnglishMode)//영어
            {
                LFC.Log("[ReadCSV_Passing_Expression] " + Table_Type + "Completed, Run time : " + sTemp5);
            }
            else//한글
            {
                LFC.Log("[ReadCSV_Passing_Expression] " + Table_Type + "수행 완료, 수행시간 : " + sTemp5);
            }        
        }
        private StringBuilder Tmp1_sb = new StringBuilder();
        private StringBuilder Tmp2_sb = new StringBuilder();
        private StringBuilder Tmp3_sb = new StringBuilder();
        private StringBuilder Tmp4_sb = new StringBuilder();
        private StringBuilder Tmp5_sb = new StringBuilder();
        private StringBuilder Tmp8_sb = new StringBuilder();
        private StringBuilder Tmp9_sb = new StringBuilder();
        private StringBuilder Tmp10_sb = new StringBuilder();
        public void DB_Day_Update(string SiteId, string FacilityTypeId, string FacilityCode, string PropertyId, string Value, int NowMin, string Hour)
        {
            string ConnInfo = "";
            string DailyDate = "";
            string Max_DailyDate = "";
            string Min_DailyDate = "";
            My_DB_DML MDD = new My_DB_DML();
            string strcon = MDD.ConnDBInfo();

            float[] SelectValue = new float[2];

            if (NowMin == 00 && (Convert.ToDateTime(Hour).ToString("HH") == "00"))
            {
                DailyDate = Convert.ToDateTime(Hour).AddDays(-1).ToString("yyyy-MM-dd 00:00:00.000");
                //LogFileCreate LFC = new LogFileCreate();
                Max_DailyDate = Convert.ToDateTime(Hour).AddDays(-1).ToString("yyyy-MM-dd 00:00:00.000");
                Min_DailyDate = Convert.ToDateTime(Hour).AddDays(-1).ToString("yyyy-MM-dd 00:00:00.000");
            }
            else
            {
                DailyDate = Convert.ToDateTime(Hour).ToString("yyyy-MM-dd 00:00:00.000");
                Max_DailyDate = Convert.ToDateTime(Hour).ToString("yyyy-MM-dd 00:00:00.000");
                Min_DailyDate = Convert.ToDateTime(Hour).ToString("yyyy-MM-dd 00:00:00.000");
            }
            ReturnValue RV = new ReturnValue();

            ConnInfo = MDD.ConnDBInfo(); // DB접속정보를 담고 있음.

            using (SqlConnection conn = new SqlConnection(strcon))
            {
                object o = 0;
                object o2 = 0;
                object o3 = 0;
                object o4 = 0;
                string query = "";
                string query2 = "";
                int countvalue = 0;
                Double Maxvalue = 0;
                Double Minvalue = 0;
                Double Currentvalue = 0;
                /// Key값과 Value값을 담기 위한 TKey, TValue

                conn.Open();

                string tmpDailyDatestart = Convert.ToDateTime(Hour).ToString("yyyy-MM-dd 00:00:00.000");
                string tmpDailyDateend = Convert.ToDateTime(Hour).ToString("yyyy-MM-dd 23:59:59.000");
                Tmp2_sb.Append("select Max(CurrentValue) FROM ");
                Tmp2_sb.Append(Table.FiFt);
                Tmp2_sb.Append(" where ");
                Tmp2_sb.Append("SiteId = " + SiteId + " and  FacilityTypeId = " + FacilityTypeId + " and FacilityCode = " + FacilityCode + " and PropertyId = " + PropertyId + " and CreatedDateTime >= '" + tmpDailyDatestart + "' and CreatedDateTime <= '" + tmpDailyDateend + "'");

                query2 = Tmp2_sb.ToString();
                Tmp2_sb.Clear();
                SqlCommand cmd3 = new SqlCommand(query2, conn);
                query2 = "";
                o2 = cmd3.ExecuteScalar();
                cmd3.Dispose();
                if (o2.GetType() != typeof(DBNull))
                {
                    Maxvalue = Convert.ToDouble(o2);
                }

                Tmp4_sb.Append("select Min(CurrentValue) FROM ");
                Tmp4_sb.Append(Table.FiFt);
                Tmp4_sb.Append(" where ");
                Tmp4_sb.Append("SiteId = " + SiteId + " and  FacilityTypeId = " + FacilityTypeId + " and FacilityCode = " + FacilityCode + " and PropertyId = " + PropertyId + " and CreatedDateTime >= '" + tmpDailyDatestart + "' and CreatedDateTime <= '" + tmpDailyDateend + "'");

                query2 = Tmp4_sb.ToString();
                Tmp4_sb.Clear();
                SqlCommand cmd4 = new SqlCommand(query2, conn);
                query2 = "";
                o3 = cmd4.ExecuteScalar();
                cmd4.Dispose();
                if (o3.GetType() != typeof(DBNull))
                {
                    Minvalue = Convert.ToDouble(o3);
                }

                //DailYvALUE
                Tmp5_sb.Append("select Sum(CurrentValue) FROM ");
                Tmp5_sb.Append(Table.FiFt);
                Tmp5_sb.Append(" where ");
                Tmp5_sb.Append("SiteId = " + SiteId + " and  FacilityTypeId = " + FacilityTypeId + " and FacilityCode = " + FacilityCode + " and PropertyId = " + PropertyId + " and CreatedDateTime >= '" + tmpDailyDatestart + "' and CreatedDateTime <= '" + tmpDailyDateend + "'");

                query2 = Tmp5_sb.ToString();
                Tmp5_sb.Clear();
                SqlCommand cmd5 = new SqlCommand(query2, conn);
                query2 = "";
                o4 = cmd5.ExecuteScalar();
                cmd5.Dispose();
                if (o4.GetType() != typeof(DBNull))
                {
                    Currentvalue = Convert.ToDouble(o4);
                }

                Tmp1_sb.Append("select count(*) FROM ");
                Tmp1_sb.Append(Table.Daily);
                Tmp1_sb.Append(" where ");
                Tmp1_sb.Append("SiteId = " + SiteId + " and  FacilityTypeId = " + FacilityTypeId + " and FacilityCode = " + FacilityCode + " and PropertyId = " + PropertyId + " and CreatedDateTime = '" + tmpDailyDatestart + "'");

                query = Tmp1_sb.ToString();
                Tmp1_sb.Clear();
                SqlCommand cmd1 = new SqlCommand(query, conn);
                query = "";
                o = cmd1.ExecuteScalar();
                cmd1.Dispose();
                if (o.GetType() != typeof(DBNull))
                {
                    countvalue = Convert.ToInt32(o);
                }

                if ((NowMin == 00 && (Convert.ToDateTime(Hour).ToString("HH") == "00")) || countvalue == 0)
                {
                    string tmpDailyDate = Convert.ToDateTime(Hour).ToString("yyyy-MM-dd 00:00:00.000");
                    Tmp3_sb.Append("INSERT INTO ");
                    Tmp3_sb.Append(Table.Daily);
                    Tmp3_sb.Append("(SiteId,FacilityTypeId,FacilityCode,PropertyId,CreatedDateTime,DailyValue,MaxValue,MinValue)");
                    Tmp3_sb.Append(" VALUES(" + SiteId + ", " + FacilityTypeId + ", " + FacilityCode + ", " + PropertyId + ", '" + tmpDailyDate + "',0," + Maxvalue + "," + Minvalue + ")");

                    query = Tmp3_sb.ToString();
                    Tmp3_sb.Clear();
                    SqlCommand cmd11 = new SqlCommand(query, conn);
                    cmd11.ExecuteNonQuery();
                    cmd11.Dispose();
                    query = "";
                }

                Tmp8_sb.Append(" UPDATE ");
                Tmp8_sb.Append(Table.Daily);
                Tmp8_sb.Append(" SET MaxValue = ");
                Tmp8_sb.Append(Maxvalue);
                Tmp8_sb.Append("WHERE SiteId = ");
                Tmp8_sb.Append(SiteId);
                Tmp8_sb.Append(" AND FacilityTypeId = ");
                Tmp8_sb.Append(FacilityTypeId);
                Tmp8_sb.Append(" AND FacilityCode = ");
                Tmp8_sb.Append(FacilityCode);
                Tmp8_sb.Append(" AND PropertyId = ");
                Tmp8_sb.Append(PropertyId);
                Tmp8_sb.Append(" AND CreatedDateTime = '");
                Tmp8_sb.Append(Max_DailyDate);
                Tmp8_sb.Append("'");

                query += Tmp8_sb.ToString();
                Tmp8_sb.Clear();
                SqlCommand cmd12 = new SqlCommand(query, conn);
                cmd12.ExecuteNonQuery();
                cmd12.Dispose();
                query = "";

                Tmp9_sb.Append(" UPDATE ");
                Tmp9_sb.Append(Table.Daily);
                Tmp9_sb.Append(" SET MinValue = ");
                Tmp9_sb.Append(Minvalue);
                Tmp9_sb.Append("WHERE SiteId = ");
                Tmp9_sb.Append(SiteId);
                Tmp9_sb.Append(" AND FacilityTypeId = ");
                Tmp9_sb.Append(FacilityTypeId);
                Tmp9_sb.Append(" AND FacilityCode = ");
                Tmp9_sb.Append(FacilityCode);
                Tmp9_sb.Append(" AND PropertyId = ");
                Tmp9_sb.Append(PropertyId);
                Tmp9_sb.Append(" AND CreatedDateTime = '");
                Tmp9_sb.Append(Min_DailyDate);
                Tmp9_sb.Append("'");

                query += Tmp9_sb.ToString();
                SqlCommand cmd13 = new SqlCommand(query, conn);
                cmd13.ExecuteNonQuery();
                cmd13.Dispose();
                query = "";

                Tmp10_sb.Append(" UPDATE ");
                Tmp10_sb.Append(Table.Daily);
                Tmp10_sb.Append(" SET DailyValue = ");
                Tmp10_sb.Append(Currentvalue);
                Tmp10_sb.Append("WHERE SiteId = ");
                Tmp10_sb.Append(SiteId);
                Tmp10_sb.Append(" AND FacilityTypeId = ");
                Tmp10_sb.Append(FacilityTypeId);
                Tmp10_sb.Append(" AND FacilityCode = ");
                Tmp10_sb.Append(FacilityCode);
                Tmp10_sb.Append(" AND PropertyId = ");
                Tmp10_sb.Append(PropertyId);
                Tmp10_sb.Append(" AND CreatedDateTime = '");
                Tmp10_sb.Append(Min_DailyDate);
                Tmp10_sb.Append("'");

                query += Tmp10_sb.ToString();

                SqlCommand cmd7 = new SqlCommand(query, conn);
                cmd7.ExecuteNonQuery();
                cmd7.Dispose();
                Tmp9_sb.Clear();
                Tmp10_sb.Clear();
                conn.Close();
                conn.Dispose();
            }
        }
    }
}
