using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using Newtonsoft.Json;
using Repository.Models;
using System.IO;
using System.Net;
using System.Xml.Linq;
using System.Diagnostics;
using Repository.BackendRepository.Implement;
using Repository.Helper;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Components.Routing;

namespace Backend.Services.Implement
{
    public class webRequestService
    {
        private Stopwatch stopwatch = new Stopwatch();
        private Stopwatch stopwatchSection = new Stopwatch();

        public List<Device_value> obixQuery(string urlString, string bql, string tag_quantity, string acc, string pass)
        {
            stopwatch = new Stopwatch();
            stopwatch.Start();
            List<Device_value> result = new List<Device_value>();
            //String username = "obixUser";
            //String password = "Admin123456";
            //String username = "stanGG";
            //String password = "St12345678";
            String username = acc;
            String password = pass;
            String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
            String API_Url = urlString;

            stopwatchSection = new Stopwatch();
            stopwatchSection.Start();
            HttpWebRequest Postrequest = (HttpWebRequest)WebRequest.Create(API_Url);
            Postrequest.Method = "POST";
            Postrequest.Headers.Add("Authorization", "Basic " + encoded);
            Postrequest.PreAuthenticate = true;

            using (var streamWriter = new StreamWriter(Postrequest.GetRequestStream()))
            {
                string json = "<str val='" + bql + "'/>";

                streamWriter.Write(json);
            }
            HttpWebResponse response = (HttpWebResponse)Postrequest.GetResponse();
            var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
            stopwatchSection.Stop();
            KeepTimeLog("request data from niagara", stopwatchSection.ElapsedMilliseconds);

            stopwatchSection = new Stopwatch();
            stopwatchSection.Start();
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(responseString);
            //xmlDoc.Load("N4v1021.xml");//N4v1021

            //xmlDoc.Save("N4.xml");

            string jsonText = JsonConvert.SerializeXmlNode(xmlDoc);
            var data = Welcome.FromJson(jsonText);

            foreach (var item in data.Obj.Str)
            {
                Device_value row = new Device_value();
                row.value = item.Val;
                string[] s1 = item.Val.Split(',');

                string[] s2 = s1[0].Remove(s1[0].Length - 1, 1).Remove(0, 1).Split('/');

                string displayName = s1[1].Split('=')[1];
                row.tag_name = "";
                if (int.Parse(tag_quantity) == 8)
                {
                    if (s2.Length == 8)
                    {
                        for (int i = 0; i < s2.Length; i++)
                        {
                            if (i == s2.Length - 2)
                            {
                                row.point_name = s2[i];
                            }
                        
                            if (i == 0)
                            {
                                row.tag_name += s2[i];
                            }
                            else
                            {
                                row.tag_name += "_" + s2[i];
                            }
                        } 
                        row.displayName = displayName;
                        result.Add(row);
                    }
                }
                else {
                    if (s2.Length >=5)
                    {
                        // tag 在最後一段: Arena/D2/B/B2F/EL/D2_B_B2F_EL_424/
                        var lastStr = s2[s2.Length-1].Split('_');

                        if (lastStr.Length > 3)
                        {
                            row.tag_name = s2[s2.Length-1];
                        }
                        else
                        { // tag 需要串接前幾段:Arena/D2/B/B2F/EL/  
                          // 這種的不需要匯入
                            //for (int i = 0; i < s2.Length; i++)
                            //{
                            //    if (i == 0)
                            //    {
                            //        row.tag_name += s2[i];
                            //    }
                            //    else
                            //    {
                            //        row.tag_name += "_" + s2[i];
                            //    }
                            //}
                        }

                        row.displayName = displayName;
                        result.Add(row);
                    }
                } 
            }
            stopwatchSection.Stop();
            KeepTimeLog("Serialize xml data, and filter data", stopwatchSection.ElapsedMilliseconds);

            stopwatch.Stop();
            KeepTimeLog("obixQuery", stopwatch.ElapsedMilliseconds);
            return result;
        }

        /// <summary>
        /// 獲取 niagara history 中的點位
        /// </summary>
        /// <param name="bqlUrlString"></param>
        /// <param name="urlString"></param>
        /// <param name="slot"></param>
        /// <returns></returns>
        public List<ImpNiaItem> obixHisQuery(string bqlUrlString, string urlString, string slot, string acc, string pass, string AreaTag)
        {
            stopwatch = new Stopwatch();
            stopwatch.Start();
            //String username = "obixUser";
            //String password = "Admin123456";
            //String username = "stanGG";
            //String password = "St12345678";
            String username = acc;
            String password = pass;
            String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
            String oneStationName = null;
            #region get control point data
            List<control_point> conPoint = new List<control_point>();
            String cp_API_Url = bqlUrlString;
            String building_tag = slot.Split("/")[2].Replace("|", "_").Trim(); //Ex: D2_, M_

            stopwatchSection = new Stopwatch();
            stopwatchSection.Start();
            HttpWebRequest cp_Postrequest = (HttpWebRequest)WebRequest.Create(cp_API_Url);
            cp_Postrequest.Method = "POST";
            cp_Postrequest.Headers.Add("Authorization", "Basic " + encoded);
            cp_Postrequest.PreAuthenticate = true;

            using (var streamWriter = new StreamWriter(cp_Postrequest.GetRequestStream()))
            {
                string json = "<str val='" + slot + "bql: select * from control:ControlPoint'/>";

                streamWriter.Write(json);
            }
            cp_Postrequest.Timeout = System.Threading.Timeout.Infinite;
            HttpWebResponse cp_response = (HttpWebResponse)cp_Postrequest.GetResponse();
            var cp_responseString = new StreamReader(cp_response.GetResponseStream()).ReadToEnd();
            stopwatchSection.Stop();
            KeepTimeLog("request data from niagara", stopwatchSection.ElapsedMilliseconds);

            stopwatchSection = new Stopwatch();
            stopwatchSection.Start();
            XmlDocument cp_xmlDoc = new XmlDocument();
            cp_xmlDoc.LoadXml(cp_responseString);

            string cp_jsonText = JsonConvert.SerializeXmlNode(cp_xmlDoc);
            var cp_data = Welcome.FromJson(cp_jsonText);

            foreach (var item in cp_data.Obj.Str)
            {
                control_point row = new control_point();
                string[] s1 = item.Val.Split(',');

                string[] s2 = s1[0].Split('/');
                var displayName = s1[1].Split('=')[1];

                row.name = s1[0].Remove(s1[0].Length - 1, 1).Remove(0, 1);
                row.displayName = displayName;
                row.isHistory = false;

                conPoint.Add(row);
            }
            #endregion

            List<ImpNiaItem> result = new List<ImpNiaItem>();
            #region main program (deleted)
            //String API_Url = urlString;

            //HttpWebRequest Postrequest = (HttpWebRequest)WebRequest.Create(API_Url);
            //Postrequest.Method = "GET";
            //Postrequest.Headers.Add("Authorization", "Basic " + encoded);
            //Postrequest.PreAuthenticate = true;
            //Postrequest.Timeout = System.Threading.Timeout.Infinite;

            //HttpWebResponse response = (HttpWebResponse)Postrequest.GetResponse();
            //var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();

            //XmlDocument xmlDoc = new XmlDocument();
            //xmlDoc.LoadXml(responseString);

            ////ref https://stackoverflow.com/questions/642293/how-do-i-read-and-parse-an-xml-file-in-c
            //foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes)
            //{
            //    var stationName = node.Attributes["name"].InnerText; // WSP_Supervisor
            //    if (stationName.Split("_").Length > 1 && stationName.Split("_")[1] == building_tag.Split("_")[0])
            //    {
            //        oneStationName = oneStationName ?? stationName;
            //        String API_Url2 = urlString + "/" + stationName; // http://192.168.0.136:8081/obix/histories/WSP_Supervisor

            //        HttpWebRequest Postrequest2 = (HttpWebRequest)WebRequest.Create(API_Url2);
            //        Postrequest2.Method = "GET";
            //        Postrequest2.Headers.Add("Authorization", "Basic " + encoded);
            //        Postrequest2.PreAuthenticate = true;
            //        Postrequest2.Timeout = System.Threading.Timeout.Infinite;

            //        HttpWebResponse response2 = (HttpWebResponse)Postrequest2.GetResponse();
            //        var responseString2 = new StreamReader(response2.GetResponseStream()).ReadToEnd();

            //        XmlDocument xmlDoc2 = new XmlDocument();
            //        xmlDoc2.LoadXml(responseString2);
            //        // Create a namespace manager to handle the XML namespace
            //        XmlNamespaceManager namespaceManager = new XmlNamespaceManager(xmlDoc2.NameTable);
            //        string xmlns = xmlDoc2.DocumentElement.GetAttribute("xmlns") ?? "http://obix.org/ns/schema/1.0";
            //        namespaceManager.AddNamespace("obix", xmlns);

            //        // Select all "ref" nodes using an XPath expression
            //        XmlNodeList refNodes = xmlDoc2.SelectNodes($"//obix:ref[starts-with(@name, '{AreaTag ?? building_tag}')]", namespaceManager);
            //        foreach (XmlNode node2 in refNodes)
            //        {
            //            string tagName = node2.Attributes["name"].InnerText;
            //            if (tagName.Split('_').Length == 9)
            //            {
            //                ImpNiaItem row = new ImpNiaItem();
            //                row.device_area_tag = tagName.Split('_')[0];
            //                row.device_building_tag = tagName.Split('_')[1];
            //                row.device_system_tag = tagName.Split('_')[2];
            //                row.device_name_tag = tagName.Split('_')[3];
            //                row.device_point_name = tagName.Split('_')[8];
            //                row.parent_path = stationName;

            //                //full_name 其實是點位名稱 point_name 
            //                row.full_name = conPoint.Where(x => x.name == tagName.Replace('_', '/') && !x.isHistory).Select(x => x.displayName).FirstOrDefault();
            //                if (conPoint.Where(x => x.name == tagName.Replace('_', '/') && !x.isHistory).FirstOrDefault() != null)
            //                    conPoint.Where(x => x.name == tagName.Replace('_', '/') && !x.isHistory).FirstOrDefault().isHistory = true;
            //                row.isHistory = true;

            //                result.Add(row);
            //            }
            //            else if (tagName.Split('_').Length == 6)
            //            { //巨蛋 tag 5 段版本
            //                ImpNiaItem row = new ImpNiaItem();
            //                if (tagName.Split('_')[1] == "S" || tagName.Split('_')[1] == "B" || tagName.Split('_')[1] == "CWB") //for security system and parking system
            //                {
            //                    row.device_building_tag = tagName.Split('_')[0];
            //                    row.device_system_tag = tagName.Split('_')[1];
            //                    row.device_floor_tag = tagName.Split('_')[2];
            //                    row.device_name_tag = tagName.Split('_')[3];
            //                    row.device_point_name = tagName.Split('_')[5];
            //                }
            //                else //for normal
            //                {
            //                    row.device_building_tag = tagName.Split('_')[0];
            //                    row.device_floor_tag = tagName.Split('_')[2];
            //                    row.device_name_tag = tagName.Split('_')[1];
            //                    row.device_point_name = tagName.Split('_')[5];
            //                }

            //                row.parent_path = stationName;
            //                //full_name 其實是點位名稱 point_name 
            //                var deviceNumber = tagName.Substring(0, tagName.LastIndexOf(tagName.Split("_")[5]) - 1);
            //                var point = tagName.Split("_")[5];
            //                conPoint = conPoint.Where(x => x.name.Split("/").Length > 6).ToList();
            //                row.full_name = conPoint.Where(x => x.name.Split("/")[5] == deviceNumber && x.name.Split("/")[6] == point && !x.isHistory).Select(x => x.displayName).FirstOrDefault();
            //                if (conPoint.Where(x => x.name.Split("/")[5] == deviceNumber && x.name.Split("/")[6] == point && !x.isHistory).FirstOrDefault() != null)
            //                    conPoint.Where(x => x.name.Split("/")[5] == deviceNumber && x.name.Split("/")[6] == point && !x.isHistory).FirstOrDefault().isHistory = true;
            //                row.isHistory = true;
            //                result.Add(row);
            //            }
            //        }
            //    }
            //}
            #endregion

            foreach (var n in conPoint)
            {
                if (n.name.Split('/').Length == 9)
                {
                    result.Add(new ImpNiaItem
                    {
                        device_area_tag = n.name.Split('/')[0],
                        device_building_tag = n.name.Split('/')[1],
                        device_system_tag = n.name.Split('/')[2],
                        device_name_tag = n.name.Split('/')[3],
                        device_point_name = n.name.Split('/')[8],
                        full_name = n.displayName
                    });
                }
                else if (n.name.Split('/').Length == 7) // Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET1/Summery
                {
                    if (n.name.Split('/')[2] == "S" || n.name.Split('/')[2] == "B" || n.name.Split('/')[2] == "CWB") //for security system and CWB system
                    {
                        result.Add(new ImpNiaItem {
                            device_building_tag = n.name.Split('/')[1],
                            device_system_tag = n.name.Split('/')[2],
                            device_floor_tag = n.name.Split('/')[3],
                            device_name_tag = n.name.Split('/')[4],
                            device_point_name = n.name.Split('/')[6],
                            full_name = n.displayName
                        });
                    }
                    else //for normal
                    {
                        result.Add(new ImpNiaItem
                        {
                            device_building_tag = n.name.Split('/')[1],
                            //device_system_tag = n.name.Split('/')[1],
                            device_floor_tag = n.name.Split('/')[3],
                            device_name_tag = n.name.Split('/')[2],
                            device_point_name = n.name.Split('/')[6],
                            full_name = n.displayName
                        });
                    }
                }
            }
            stopwatchSection.Stop();
            KeepTimeLog("Serialize xml data, and filter data", stopwatchSection.ElapsedMilliseconds);

            stopwatch.Stop();
            KeepTimeLog("obixHisQuery", stopwatch.ElapsedMilliseconds);
            return result.ToList();
        }

        public List<Device_value_disaster> obixDevDisaster(string urlString, string bql, string tag_quantity, string acc, string pass, string dt)
        {
            stopwatch = new Stopwatch();
            stopwatch.Start();
            List<Device_value_disaster> result = new List<Device_value_disaster>();
            try
            {
                //String username = "obixUser";
                //String password = "Admin123456";
                String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(acc + ":" + pass));
                String API_Url = urlString;

                stopwatchSection = new Stopwatch();
                stopwatchSection.Start();
                HttpWebRequest Postrequest = (HttpWebRequest)WebRequest.Create(API_Url);
                Postrequest.Method = "POST";
                Postrequest.Headers.Add("Authorization", "Basic " + encoded);
                Postrequest.PreAuthenticate = true;

                using (var streamWriter = new StreamWriter(Postrequest.GetRequestStream()))
                {
                    string json = "<str val='" + bql + "'/>";

                    streamWriter.Write(json);
                }

                HttpWebResponse response = (HttpWebResponse)Postrequest.GetResponse();
                var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
                stopwatchSection.Stop();
                KeepTimeLog("get data from niagara", stopwatchSection.ElapsedMilliseconds);

                stopwatchSection = new Stopwatch();
                stopwatchSection.Start();
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(responseString);

                string jsonText = JsonConvert.SerializeXmlNode(xmlDoc);
                bool welcome = false;
                try
                {
                    Welcome.FromJson(jsonText);
                    welcome = true;
                }
                catch
                {
                    
                }

                if (welcome)
                {
                    var data = Welcome.FromJson(jsonText);
                    if (data.Obj.Str != null)
                    {
                        foreach (var item in data.Obj.Str)
                        {
                            Device_value_disaster row = new Device_value_disaster();
                            row.value = item.Val;
                            string[] s1 = item.Val.Split(',');
                            string[] s2 = s1[0].Split('/');
                            row.tag_name = "";
                            row.disasterValue = dt;

                            for (int i = 0; i < s2.Length; i++)
                            {
                                if (i == s2.Length - 2)
                                {
                                    row.point_name = s2[i];
                                }
                                else if (i == 1)
                                {
                                    row.tag_name += s2[i];
                                }
                                else if (i > 1 && i < s2.Length - 2)
                                {
                                    row.tag_name += "_" + s2[i].Replace("$3", "");
                                }
                            }
                            result.Add(row);
                        }
                    }
                }
                else
                {
                    var data = WelcomeSingle.FromJson(jsonText);

                    if (data.Obj.Str != null)
                    {
                        var item = data.Obj.Str;
                        Device_value_disaster row = new Device_value_disaster();
                        row.value = item.Val;
                        string[] s1 = item.Val.Split(',');
                        string[] s2 = s1[0].Split('/');
                        row.tag_name = "";
                        row.disasterValue = dt;

                        for (int i = 0; i < s2.Length; i++)
                        {
                            if (i == s2.Length - 2)
                            {
                                row.point_name = s2[i];
                            }
                            else if (i == 1)
                            {
                                row.tag_name += s2[i];
                            }
                            else if (i > 1 && i < s2.Length - 2)
                            {
                                row.tag_name += "_" + s2[i].Replace("$3", "");
                            }
                        }
                        result.Add(row);
                    }
                }
            }
            catch(Exception e)
            {
            }
            stopwatchSection.Stop();
            KeepTimeLog("Serialize xml data, and filter data", stopwatchSection.ElapsedMilliseconds);

            stopwatch.Stop();
            KeepTimeLog("obixHisQuery", stopwatch.ElapsedMilliseconds);
            return result;
        }

        /// <summary>
        /// 獲取 niagara history 中的點位
        /// </summary>
        /// <param name="bqlUrlString"></param>
        /// <param name="urlString"></param>
        /// <param name="slot"></param>
        /// <returns></returns>
        public List<ImpNiaItem> obixHisQuery_v2(string bqlUrlString, string urlString, string slot, string acc, string pass)
        {
            stopwatch = new Stopwatch();
            stopwatch.Start();
            //String username = "obixUser";
            //String password = "Admin123456";
            //String username = "stanGG";
            //String password = "St12345678";
            String username = acc;
            String password = pass;
            String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
            String oneStationName = null;
            #region get control point data
            List<control_point> conPoint = new List<control_point>();
            String cp_API_Url = bqlUrlString;

            HttpWebRequest cp_Postrequest = (HttpWebRequest)WebRequest.Create(cp_API_Url);
            cp_Postrequest.Method = "POST";
            cp_Postrequest.Headers.Add("Authorization", "Basic " + encoded);
            cp_Postrequest.PreAuthenticate = true;

            //using (var streamWriter = new StreamWriter(cp_Postrequest.GetRequestStream()))
            //{
            //    string json = "<str val='" + slot + "bql: select * from control:ControlPoint'/>";

            //    streamWriter.Write(json);
            //}
            //HttpWebResponse cp_response = (HttpWebResponse)cp_Postrequest.GetResponse();
            //var cp_responseString = new StreamReader(cp_response.GetResponseStream()).ReadToEnd();

            //XmlDocument cp_xmlDoc = new XmlDocument();
            //cp_xmlDoc.LoadXml(cp_responseString);

            //string cp_jsonText = JsonConvert.SerializeXmlNode(cp_xmlDoc);
            //var cp_data = Welcome.FromJson(cp_jsonText);

            //foreach (var item in cp_data.Obj.Str)
            //{
            //    control_point row = new control_point();
            //    string[] s1 = item.Val.Split(',');

            //    string[] s2 = s1[0].Split('/');
            //    var displayName = s1[1].Split('=')[1];

            //    row.name = s1[0].Remove(s1[0].Length - 1, 1).Remove(0, 1);
            //    row.displayName = displayName;
            //    row.isHistory = false;

            //    conPoint.Add(row);
            //}
            #endregion

            #region main program
            List<ImpNiaItem> result = new List<ImpNiaItem>();
            String API_Url = urlString;

            stopwatchSection = new Stopwatch();
            stopwatchSection.Start();
            HttpWebRequest Postrequest = (HttpWebRequest)WebRequest.Create(API_Url);
            Postrequest.Method = "GET";
            Postrequest.Headers.Add("Authorization", "Basic " + encoded);
            Postrequest.PreAuthenticate = true;
            Postrequest.Timeout = System.Threading.Timeout.Infinite;

            HttpWebResponse response = (HttpWebResponse)Postrequest.GetResponse();
            var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
            stopwatchSection.Stop();
            KeepTimeLog("get data from niagara", stopwatchSection.ElapsedMilliseconds);

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(responseString);

            // 1.循環所有的 station
            //ref https://stackoverflow.com/questions/642293/how-do-i-read-and-parse-an-xml-file-in-c
            stopwatchSection = new Stopwatch();
            stopwatchSection.Start();
            foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes)
            {
                var stationName = node.Attributes["name"].InnerText; // WSP_Supervisor
                oneStationName = oneStationName ?? stationName;
                String API_Url2 = urlString + "/" + stationName; // http://192.168.0.136:8081/obix/histories/WSP_Supervisor

                HttpWebRequest Postrequest2 = (HttpWebRequest)WebRequest.Create(API_Url2);
                Postrequest2.Method = "GET";
                Postrequest2.Headers.Add("Authorization", "Basic " + encoded);
                Postrequest2.PreAuthenticate = true;
                Postrequest2.Timeout = System.Threading.Timeout.Infinite;

                HttpWebResponse response2 = (HttpWebResponse)Postrequest2.GetResponse();
                var responseString2 = new StreamReader(response2.GetResponseStream()).ReadToEnd();

                XmlDocument xmlDoc2 = new XmlDocument();
                xmlDoc2.LoadXml(responseString2);
                // 2.獲取 station 中全部的設備+點位
                foreach (XmlNode node2 in xmlDoc2.DocumentElement.ChildNodes)
                {
                    string tagName = node2.Attributes["name"].InnerText;
                    if (tagName.Split('_').Length == 9)
                    {
                        if (tagName.Split('_')[1].IndexOf("8F5") != -1)
                        {
                            string ss = tagName.Split('_')[1];
                        }
                        ImpNiaItem row = new ImpNiaItem();
                        row.device_area_tag = tagName.Split('_')[0];
                        row.device_building_tag = tagName.Split('_')[1];
                        row.device_system_tag = tagName.Split('_')[2];
                        row.device_name_tag = tagName.Split('_')[3];
                        row.device_floor_tag = tagName.Split('_')[4];
                        row.device_master_tag = tagName.Split('_')[5];
                        row.device_last_name_tag = tagName.Split('_')[6];
                        row.device_serial_tag = tagName.Split('_')[7];
                        row.device_point_name = tagName.Split('_')[8];
                        row.parent_path = stationName;

                        result.Add(row);
                    }
                    else if (tagName.Split('_').Length == 6)
                    { //巨蛋 tag 5 段版本
                        ImpNiaItem row = new ImpNiaItem();
                        if (tagName.Split('_')[1] == "S" || tagName.Split('_')[1] == "B" || tagName.Split('_')[1] == "CWB") //for security system
                        {
                            row.device_building_tag = tagName.Split('_')[0];
                            row.device_system_tag = tagName.Split('_')[1];
                            row.device_floor_tag = tagName.Split('_')[2];
                            row.device_name_tag = tagName.Split('_')[3];
                            row.device_point_name = tagName.Split('_')[5];
                        }
                        else //for normal
                        {
                            row.device_building_tag = tagName.Split('_')[0];
                            //row.device_system_tag = tagName.Split('_')[1];
                            row.device_floor_tag = tagName.Split('_')[2];
                            row.device_name_tag = tagName.Split('_')[1];
                            row.device_point_name = tagName.Split('_')[5];
                        }
                        row.parent_path = stationName;
                        result.Add(row);
                    }
                }
            }
            stopwatchSection.Stop();
            KeepTimeLog("Serialize xml data, and filter data", stopwatchSection.ElapsedMilliseconds);
            #endregion

            stopwatch.Stop();
            KeepTimeLog("obixHisQuery_v2", stopwatch.ElapsedMilliseconds);
            return result.ToList();
            //return result.Where(x => x.full_name != null).ToList();
        }

        //private static void getRefData(string urlString, string encoded, List<control_point> conPoint, List<ImpNiaItem> result, Welcome data ) //obixHistory data
        //{
        //    foreach (var item in data.Obj.Ref)
        //    {
        //        //var item = data.Obj.Ref;
        //        String API_Url2 = urlString + "/" + item.Name;

        //        HttpWebRequest Postrequest2 = (HttpWebRequest)WebRequest.Create(API_Url2);
        //        Postrequest2.Method = "GET";
        //        Postrequest2.Headers.Add("Authorization", "Basic " + encoded);
        //        Postrequest2.PreAuthenticate = true;

        //        HttpWebResponse response2 = (HttpWebResponse)Postrequest2.GetResponse();
        //        var responseString2 = new StreamReader(response2.GetResponseStream()).ReadToEnd();

        //        XmlDocument xmlDoc2 = new XmlDocument();
        //        xmlDoc2.LoadXml(responseString2);

        //        string jsonText2 = JsonConvert.SerializeXmlNode(xmlDoc2);
        //        var data2 = Welcome.FromJson(jsonText2);

        //        foreach (var item2 in data2.Obj.Ref)
        //        {
        //            if (item2.Name.Split('_').Length == 9)
        //            {
        //                ImpNiaItem row = new ImpNiaItem();
        //                row.device_area_tag = item2.Name.Split('_')[0];
        //                row.device_building_tag = item2.Name.Split('_')[1];
        //                row.device_system_tag = item2.Name.Split('_')[2];
        //                row.device_name_tag = item2.Name.Split('_')[3];
        //                row.device_point_name = item2.Name.Split('_')[8];
        //                row.parent_path = item.Name;

        //                //full_name 其實是點位名稱 point_name 
        //                row.full_name = conPoint.Where(x => x.name == item2.Name).Select(x => x.displayName).FirstOrDefault();

        //                result.Add(row);
        //            }
        //        }
        //    }
        //}

        //private static void getRefData(string urlString, string encoded, List<control_point> conPoint, List<ImpNiaItem> result, Welcome4 data)
        //{
        //    foreach (var item in data.Obj.Ref)
        //    {
        //        String API_Url2 = urlString + "/" + item.Name;

        //        HttpWebRequest Postrequest2 = (HttpWebRequest)WebRequest.Create(API_Url2);
        //        Postrequest2.Method = "GET";
        //        Postrequest2.Headers.Add("Authorization", "Basic " + encoded);
        //        Postrequest2.PreAuthenticate = true;

        //        HttpWebResponse response2 = (HttpWebResponse)Postrequest2.GetResponse();
        //        var responseString2 = new StreamReader(response2.GetResponseStream()).ReadToEnd();

        //        XmlDocument xmlDoc2 = new XmlDocument();
        //        xmlDoc2.LoadXml(responseString2);

        //        string jsonText2 = JsonConvert.SerializeXmlNode(xmlDoc2);
        //        var data2 = Welcome.FromJson(jsonText2);

        //        foreach (var item2 in data2.Obj.Ref)
        //        {
        //            if (item2.Name.Split('_').Length == 9)
        //            {
        //                ImpNiaItem row = new ImpNiaItem();
        //                row.device_area_tag = item2.Name.Split('_')[0];
        //                row.device_building_tag = item2.Name.Split('_')[1];
        //                row.device_system_tag = item2.Name.Split('_')[2];
        //                row.device_name_tag = item2.Name.Split('_')[3];
        //                row.device_point_name = item2.Name.Split('_')[8];
        //                row.parent_path = item.Name;

        //                //full_name 其實是點位名稱 point_name 
        //                row.full_name = conPoint.Where(x => x.name == item2.Name).Select(x => x.displayName).FirstOrDefault();

        //                result.Add(row);
        //            }
        //        }
        //    }
        //}

        //public void getObix()
        //{
        //    //#region 取得obix 設定
        //    //var obixApiConfig = new ObixApiConfig();

        //    //var sqlObix = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'";

        //    //var variableObix = await backgroundServiceRepository.GetAllAsync<KeyValue>(sqlObix);
        //    //obixApiConfig.ApiBase = variableObix.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault();
        //    //obixApiConfig.UserName = ed.AESDecrypt(variableObix.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault());
        //    //obixApiConfig.Password = ed.AESDecrypt(variableObix.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault());

        //    //String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password));
        //    //#endregion 取得obix 設定


        //    HttpWebRequest archiveMonthRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/");
        //    //HttpWebRequest archiveMonthRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
        //    archiveMonthRequest.Method = "POST";
        //    archiveMonthRequest.Headers.Add("Authorization", "Basic " + encoded);
        //    archiveMonthRequest.PreAuthenticate = true;

        //    byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
        //    using (Stream reqStream = archiveMonthRequest.GetRequestStream())
        //    {
        //        reqStream.Write(byteArray, 0, byteArray.Length);
        //    }

        //    HttpWebResponse archiveMonthResponse = (HttpWebResponse)archiveMonthRequest.GetResponse();
        //    var archiveMonthResponseContent = new StreamReader(archiveMonthResponse.GetResponseStream()).ReadToEnd();

        //    xmlDocument.LoadXml(archiveMonthResponseContent);
        //    string archiveMonthJson = JsonConvert.SerializeXmlNode(xmlDocument);
        //    JObject archiveMonthJsonResult = (JObject)JsonConvert.DeserializeObject(archiveMonthJson);

        //    if (archiveMonthJsonResult.ContainsKey("err")) //抓取錯誤
        //    {
        //        //logger.LogError("【ArchiveElectricMeterDayJob】【月歸檔】【取得資料失敗】");
        //        //logger.LogError("【ArchiveElectricMeterDayJob】【月歸檔】【取得資料失敗】[錯誤內容]:{0}", archiveMonthJsonResult);

        //        Dictionary<string, object> archiveMonthRawData = new Dictionary<string, object>();
        //        archiveMonthRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
        //        archiveMonthRawData.Add("@point", deviceNumberPoint.Point);
        //        archiveMonthRawData.Add("@start_timestamp", startTimestamp.Replace("T", " ").Substring(0, 19));
        //        archiveMonthRawData.Add("@end_timestamp", endTimestamp.Replace("T", " ").Substring(0, 19));
        //        archiveMonthRawData.Add("@is_complete", 0);
        //        archiveMonthRawData.Add("@repeat_times", 0);
        //        archiveMonthRawData.Add("@fail_reason", archiveMonthJson);

        //        archiveMonthRawData.Add("@count_rawdata", 0);
        //        archiveMonthRawData.Add("@min_rawdata", 0);
        //        archiveMonthRawData.Add("@max_rawdata", 0);
        //        archiveMonthRawData.Add("@avg_rawdata", 0);
        //        archiveMonthRawData.Add("@sum_rawdata", 0);
        //        archiveMonthRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));

        //        archiveMonthRawDatas.Add(archiveMonthRawData);
        //    }

        //    if (archiveMonthJsonResult.ContainsKey("obj")) //表示可以讀取到內容
        //    {
        //        var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveMonthJsonResult);
        //        if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
        //        {
        //            archiveMonthRawDatas.AddRange(ArrangeRawDatas);
        //        }
        //    }
        //}

        /// <summary>
        /// 獲取 niagara history 中的點位
        /// </summary>
        /// <param name="bqlUrlString"></param>
        /// <param name="urlString"></param>
        /// <param name="slot"></param>
        /// <returns></returns>
        public List<DeviceControlPoint> obixAllDevicePoint(string bqlUrlString, string urlString, string slot, string acc, string pass, string AreaTag)
        {
            stopwatch = new Stopwatch();
            stopwatch.Start();
            String username = acc;
            String password = pass;
            String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
            
            #region get control point data
            List<control_point> conPoint = new List<control_point>();
            String cp_API_Url = bqlUrlString;
            String building_tag = slot.Split("/")[2].Replace("|", "_").Trim(); //Ex: D2_, M_

            stopwatchSection = new Stopwatch();
            stopwatchSection.Start();
            HttpWebRequest cp_Postrequest = (HttpWebRequest)WebRequest.Create(cp_API_Url);
            cp_Postrequest.Method = "POST";
            cp_Postrequest.Headers.Add("Authorization", "Basic " + encoded);
            cp_Postrequest.PreAuthenticate = true;

            using (var streamWriter = new StreamWriter(cp_Postrequest.GetRequestStream()))
            {
                string json = "<str val='" + slot + "bql: select * from control:ControlPoint'/>";

                streamWriter.Write(json);
            }
            cp_Postrequest.Timeout = System.Threading.Timeout.Infinite;
            HttpWebResponse cp_response = (HttpWebResponse)cp_Postrequest.GetResponse();
            var cp_responseString = new StreamReader(cp_response.GetResponseStream()).ReadToEnd();
            stopwatchSection.Stop();
            KeepTimeLog("get data from niagara", stopwatchSection.ElapsedMilliseconds);

            stopwatchSection = new Stopwatch();
            stopwatchSection.Start();
            XmlDocument cp_xmlDoc = new XmlDocument();
            cp_xmlDoc.LoadXml(cp_responseString);

            string cp_jsonText = JsonConvert.SerializeXmlNode(cp_xmlDoc);
            var cp_data = Welcome.FromJson(cp_jsonText);

            foreach (var item in cp_data.Obj.Str)
            {
                control_point row = new control_point();
                string[] s1 = item.Val.Split(',');

                string[] s2 = s1[0].Split('/');
                var displayName = s1[1].Split('=')[1];

                row.name = s1[0].Remove(s1[0].Length - 1, 1).Remove(0, 1);
                row.displayName = displayName;
                row.isHistory = false;

                conPoint.Add(row);
            }
            #endregion

            var result = new List<DeviceControlPoint>();
            foreach (var n in conPoint)
            {
                if (n.name.Split('/').Length == 9)
                {
                    result.Add(new DeviceControlPoint
                    {
                        name = n.name,
                        displayName = n.displayName,
                        device_area_tag = n.name.Split('/')[0],
                        device_building_tag = n.name.Split('/')[1],
                        device_system_tag = n.name.Split('/')[2],
                        device_name_tag = n.name.Split('/')[3],
                        device_point_name = n.name.Split('/')[8],
                    });
                }
                else if (n.name.Split('/').Length == 7) // Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET1/Summery
                {
                    if (n.name.Split('/')[2] == "S" || n.name.Split('/')[2] == "B" || n.name.Split('/')[2] == "CWB") //for security system and CWB system
                    {
                        result.Add(new DeviceControlPoint
                        {
                            name = n.name,
                            displayName = n.displayName,
                            device_building_tag = n.name.Split('/')[1],
                            device_system_tag = n.name.Split('/')[2],
                            device_floor_tag = n.name.Split('/')[3],
                            device_name_tag = n.name.Split('/')[4],
                            device_point_name = n.name.Split('/')[6],
                            device_number = n.name.Split('/')[5]
                        });
                    }
                    else //for normal
                    {
                        result.Add(new DeviceControlPoint
                        {
                            name = n.name,
                            displayName = n.displayName,
                            device_building_tag = n.name.Split('/')[1],
                            //device_system_tag = n.name.Split('/')[1],
                            device_floor_tag = n.name.Split('/')[3],
                            device_name_tag = n.name.Split('/')[2],
                            device_point_name = n.name.Split('/')[6],
                            device_number = n.name.Split('/')[5]
                        });
                    }
                }
            }
            stopwatchSection.Stop();
            KeepTimeLog("Serialize xml data, and filter data", stopwatchSection.ElapsedMilliseconds);

            stopwatch.Stop();
            KeepTimeLog("obixHisQuery", stopwatch.ElapsedMilliseconds);
            return result.ToList();
        }

        public void KeepTimeLog(string functionName, long millisecond, [CallerLineNumber] int line = 0, [CallerMemberName] string name = "")
        {
            string path = System.IO.Path.Combine(Directory.GetCurrentDirectory(), "Logs");
            string filepath = System.IO.Path.Combine(path, "SyncLog" + DateTime.Now.ToString("yyyyMMdd") + ".txt");

            using (FileStream fs = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write))
            {
                StreamWriter sw = new StreamWriter(fs);
                sw.BaseStream.Seek(0, SeekOrigin.End);
                sw.WriteLine($"Log current time {DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")}, Log function name: {functionName}, Log function usage time: {TimeSpan.FromMilliseconds(millisecond)}, Log function record line: {line}, Log called function name: {name}");
                sw.WriteLine(Environment.NewLine);
                sw.Flush();
                sw.Close();
                fs.Close();
            }
        }
    }
}