using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Log;
using Aitex.Core.UI.ControlDataContext;
using ControlzEx.Standard;
using LiveCharts.Wpf;
using MECF.Framework.Common.CommonData;
using MECF.Framework.Common.ControlDataContext;
using MECF.Framework.Common.DataCenter;
using Newtonsoft.Json;
using OpenSEMI.ClientBase;
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using System.Xml;
using CyberX8_MainPages.Unity;
using CyberX8_MainPages.Views;
using WPF.Themes.UserControls;
using Xceed.Wpf.DataGrid;

namespace CyberX8_MainPages.ViewModels
{
    public class DataHistoryViewModel : BindableBase
    {
        #region 私有字段
        private DataHistoryView DataHistoryView;
        private ObservableCollection<ParameterNode> _ParameterNodes;
        RealtimeProvider _provider = new RealtimeProvider();
        private object _lockSelection = new object();
        ConcurrentBag<QueryIndexer> _lstTokenTimeData = new ConcurrentBag<QueryIndexer>();
        ObservableCollection<string> m_Keys=new ObservableCollection<string> ();
        ObservableCollection<KeyData> m_KeyDataObservableCollection = new ObservableCollection<KeyData>();
        DispatcherTimer timer = new DispatcherTimer();
        public List<SolidColorBrush> solidColorBrushes = new List<SolidColorBrush> ();
        DateTime currentTime;
        private bool firstFlag = true;
        private DateTime startTime=DateTime.Now;
        #endregion

        #region 属性
        public ObservableCollection<KeyData> OldKeyDataCollection { get; set; }
        public ObservableCollection<ParameterNode> ParameterNodes
        {
            get { return _ParameterNodes; }
            set { SetProperty(ref _ParameterNodes, value); }
        }
        public ObservableCollection<string> Keys
        {
            get { return m_Keys; }
            set { SetProperty(ref m_Keys, value); }
        }
        public ObservableCollection<KeyData> KeyDataObservableCollection
        {
            get { return m_KeyDataObservableCollection; }
            set { SetProperty(ref m_KeyDataObservableCollection, value); }
        }
        #endregion

        #region 命令
        private DelegateCommand<object> _LoadCommand;
        public DelegateCommand<object> LoadCommand =>
            _LoadCommand ?? (_LoadCommand = new DelegateCommand<object>(OnLoad));

        private DelegateCommand _UnLoadCommand;
        public DelegateCommand UnLoadCommand =>
            _UnLoadCommand ?? (_UnLoadCommand = new DelegateCommand(OnUnLoad));

        private DelegateCommand<object> _ParameterCheckCommand;
        public DelegateCommand<object> ParameterCheckCommand =>
            _ParameterCheckCommand ?? (_ParameterCheckCommand = new DelegateCommand<object>(OnParameterCheck));

        private DelegateCommand _StartCommand;
        public DelegateCommand StartCommand =>
            _StartCommand ?? (_StartCommand = new DelegateCommand(OnStart));

        private DelegateCommand _ClearCommand;
        public DelegateCommand ClearCommand =>
            _ClearCommand ?? (_ClearCommand = new DelegateCommand(OnClear));

        private DelegateCommand<object> _StartRealTimeCommand;
        public DelegateCommand<object> StartRealTimeCommand =>
            _StartRealTimeCommand ?? (_StartRealTimeCommand = new DelegateCommand<object>(OnStartRealTime));

        private DelegateCommand _StopRealTimeCommand;
        public DelegateCommand StopRealTimeCommand =>
            _StopRealTimeCommand ?? (_StopRealTimeCommand = new DelegateCommand(OnStopRealTime));
        #endregion

        #region 构造函数
        public DataHistoryViewModel() 
        {
            OldKeyDataCollection = new ObservableCollection<KeyData>();
            ParameterNodes = _provider.GetParameters();
            timer.Interval = TimeSpan.FromSeconds(1);
            timer.Tick += Timer_Tick;
            solidColorBrushes.Add(new SolidColorBrush (Colors.Green));
            solidColorBrushes.Add(new SolidColorBrush(Colors.Red));
            solidColorBrushes.Add(new SolidColorBrush(Colors.Blue));
            solidColorBrushes.Add(new SolidColorBrush(Colors.Orange));
            solidColorBrushes.Add(new SolidColorBrush(Colors.Yellow));
            solidColorBrushes.Add(new SolidColorBrush(Colors.YellowGreen));
            solidColorBrushes.Add(new SolidColorBrush(Colors.AliceBlue));
            solidColorBrushes.Add(new SolidColorBrush(Colors.Chocolate));
            solidColorBrushes.Add(new SolidColorBrush(Colors.Cyan));
            solidColorBrushes.Add(new SolidColorBrush(Colors.DarkGreen));


        }


        #endregion

        #region 命令方法
        private void OnLoad(Object eventView)
        {
            if (firstFlag)
            {
                this.DataHistoryView = (DataHistoryView)eventView;
                this.DataHistoryView.wfTimeFrom.Value = DateTime.Today;
                this.DataHistoryView.wfTimeTo.Value = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 23, 59, 59, 999);
                //this.DataHistoryView.MyDrawGraphicsControl.PointCollections=new PointCollection(new Point[] {})
            }
        }
        private void OnUnLoad()
        {
            GC.Collect(); // This should pick up the control removed at a previous MouseDown
            GC.WaitForPendingFinalizers(); // Doesn't help either
            GC.Collect();
            GC.WaitForPendingFinalizers(); // Doesn't help either
        }
        private void OnParameterCheck(object obj)
        {
            startTime= DateTime.Now;
            ParameterNode node = obj as ParameterNode;
            if (!RefreshTreeStatusToChild(node))
            {
                node.Selected = !node.Selected;
            }
            else
            {
                RefreshTreeStatusToParent(node);
            }

            Keys.Clear();
            for (int i = 0; i < ParameterNodes.Count; i++)
            {
                CalKeys(ParameterNodes[i]);
            }
            OldKeyDataCollection.Clear();
            OldKeyDataCollection = DeepCopyJson(KeyDataObservableCollection);
            KeyDataObservableCollection.Clear();
            for (int i = 0; i < Keys.Count; i++)
            {
                if (i == 10)
                {
                    break;
                }
                KeyDataObservableCollection.Add(new KeyData() { Key = Keys[i], Color = solidColorBrushes[i],UniqueId=i });
            }
            Compare(OldKeyDataCollection, KeyDataObservableCollection);
            KeyDataObservableCollection = DeepCopyJson(OldKeyDataCollection);
        }
        public void Compare(ObservableCollection<KeyData> olddata, ObservableCollection<KeyData> newdata)
        {
            if (newdata != null)
            {
                for (int i = 0; i < newdata.Count; i++)
                {
                    var lists = olddata.ToList().Find(t => t.Key == newdata[i].Key);
                    if (lists == null)
                    {
                        olddata.Add(new KeyData() { Key = newdata[i].Key, Color = solidColorBrushes[i], UniqueId = olddata.Count + 1 });
                    }
                }
                for (int i = 0; i < olddata.Count; i++)
                {
                    var lists = newdata.ToList().Find(t => t.Key == olddata[i].Key);
                    if (lists == null)
                    {
                        olddata.Remove(olddata[i]);
                    }
                }

            }
        }
        public static T DeepCopyJson<T>(T obj)
        {
            // 序列化
            string json = JsonConvert.SerializeObject(obj);
            // 反序列化
            return JsonConvert.DeserializeObject<T>(json);
        }
        private void OnStartRealTime(object obj)
        {
            
            if (Keys.Count > 10)
            {
                ((System.Windows.Controls.CheckBox)obj).IsChecked= false;
                timer.Stop();
                WPFMessageBox.ShowWarning("最多显示10个数据");
                return;
            }

            currentTime = DateTime.Now;
            timer.Start();
        }
        private void OnStopRealTime()
        {
            timer.Stop();
        }
      
        public void OnStart()
        {
           
            if (Keys.Count > 10)
            {
                WPFMessageBox.ShowWarning("最多显示10个数据");
                return;
            }
            this.DataHistoryView.MyDrawGraphicsControl.ClearPlotPoints();
            var result = GetData(Keys.Distinct().ToList(), this.DataHistoryView.wfTimeFrom.Value, this.DataHistoryView.wfTimeTo.Value);
            if (result == null)
            {
                return;
            }
            List<PointCollection> cls = new List<PointCollection>(); 
            for (int i = 0; i < Keys.Count; i++)
            {
                PointCollection points = new PointCollection();
                int k = 1;
                result[Keys[i]].ForEach(point => 
                {
                    points.Add(new Point() { X = point.dateTime.ToOADate(), Y = point.value });
                    k += 1;
                });
                cls.Add(points);
            }
            for (int i = 0; i < KeyDataObservableCollection.Count(); i++)
            {
                var _color = KeyDataObservableCollection[i].Color.Color;
                this.DataHistoryView.MyDrawGraphicsControl.m_PenCollencteions[i] = new System.Drawing.Pen(System.Drawing.Color.FromArgb(_color.A, _color.R, _color.G, _color.B), 2);
            }
            this.DataHistoryView.MyDrawGraphicsControl.PointCollections = cls;
            this.DataHistoryView.MyDrawGraphicsControl.FitControl();
            this.DataHistoryView.MyDrawGraphicsControl.YPoints.Clear();
            var item = QueryDataClient.Instance.Service.GetHistorySteps(this.DataHistoryView.wfTimeFrom.Value, this.DataHistoryView.wfTimeTo.Value);
            if (item != null)
            {
                item.ForEach(x =>
                {
                    this.DataHistoryView.MyDrawGraphicsControl.YPoints.Add(new CyberX8_Core.StepItem() { StartValue = x.StartTime.ToOADate(), Information = $"{x.RecipeId}:{x.StepNo}" });
                });
            }
        }
        private void CloseAll(ObservableCollection<ParameterNode> parameterNodes)
        {
            foreach (var item in parameterNodes)
            {
                item.Selected = false;
                if (item.ChildNodes.Count > 0)
                {
                    CloseAll(item.ChildNodes);
                }
            }
        }
        private void OnClear()
        {
            this.DataHistoryView.MyDrawGraphicsControl.ClearPlotPoints();
            this.DataHistoryView.MyDrawGraphicsControl.YPoints = new List<CyberX8_Core.StepItem>();
            KeyDataObservableCollection.Clear();
            CloseAll(ParameterNodes);
        }
        #endregion

        #region 私有方法
        private bool RefreshTreeStatusToChild(ParameterNode node)
        {
            if (node.ChildNodes.Count > 0)
            {
                for (int i = 0; i < node.ChildNodes.Count; i++)
                {
                    ParameterNode n = node.ChildNodes[i];
                    n.Selected = node.Selected;

                    if (!RefreshTreeStatusToChild(n))
                    {
                        //uncheck left node
                        for (int j = i; j < node.ChildNodes.Count; j++)
                        {
                            node.ChildNodes[j].Selected = !node.Selected;
                        }
                        //node.Selected = !node.Selected;
                        return false;
                    }
                }
            }
            //else
            //{
            //    if (node.Selected == true)
            //    {
            //        keys.Add(node.Name);
            //    }
            //    else
            //    { 
            //    keys.Remove(node.Name);
            //    }
            //}     
            return true;
        }
        private void RefreshTreeStatusToParent(ParameterNode node)
        {
            if (node.ParentNode != null)
            {
                if (node.Selected)
                {
                    bool flag = true;
                    for (int i = 0; i < node.ParentNode.ChildNodes.Count; i++)
                    {
                        if (!node.ParentNode.ChildNodes[i].Selected)
                        {
                            flag = false;  //as least one child is unselected
                            break;
                        }
                    }
                    if (flag)
                        node.ParentNode.Selected = true;
                }
                else
                {
                    node.ParentNode.Selected = false;
                }
                RefreshTreeStatusToParent(node.ParentNode);
                
            }
        }

        private Dictionary<string, List<HistoryDataItem>> GetData(List<string> keys, DateTime from, DateTime to)
        {
            string sql = "select time AS InternalTimeStamp";
            foreach (var dataId in keys)
            {
                sql += "," + string.Format("\"{0}\"", dataId);
            }
            sql += string.Format(" from \"{0}\" where time > {1} and time <= {2} order by time asc",
                from.ToString("yyyyMMdd") + "." + "Data", from.Ticks, to.Ticks);

            DataTable dataTable = QueryDataClient.Instance.Service.QueryData(sql);

            Dictionary<string, List<HistoryDataItem>> historyData = new Dictionary<string, List<HistoryDataItem>>();
            if (dataTable == null || dataTable.Rows.Count == 0)
                return null;

            DateTime dt = new DateTime();
            Dictionary<int, string> colName = new Dictionary<int, string>();
            for (int colNo = 0; colNo < dataTable.Columns.Count; colNo++)
            {
                colName.Add(colNo, dataTable.Columns[colNo].ColumnName);
                historyData[dataTable.Columns[colNo].ColumnName] = new List<HistoryDataItem>();
            }
            for (int rowNo = 0; rowNo < dataTable.Rows.Count; rowNo++)
            {
                PointCollection points = new PointCollection();

                var row = dataTable.Rows[rowNo];

                for (int i = 0; i < dataTable.Columns.Count; i++)
                {
                    HistoryDataItem data = new HistoryDataItem();
                    if (i == 0)
                    {
                        long ticks = (long)row[i];
                        dt = new DateTime(ticks);
                        continue;
                    }
                    else
                    {
                        string dataId = colName[i];
                        if (row[i] is DBNull || row[i] == null)
                        {
                            data.dateTime = dt;
                            data.dbName = colName[i];
                            data.value = 0;
                        }
                        else if (row[i] is bool)
                        {
                            data.dateTime = dt;
                            data.dbName = colName[i];
                            data.value = (bool)row[i] ? 1 : 0;
                        }
                        else
                        {
                            data.dateTime = dt;
                            data.dbName = colName[i];
                            data.value = float.Parse(row[i].ToString());
                        }
                    }
                    historyData[data.dbName].Add(data);
                }

            }

            foreach (var item in historyData)
            {
                item.Value.Sort((x, y) => DateTime.Compare(x.dateTime, y.dateTime));
            }
            return historyData;

        }
        private void CalKeys(ParameterNode parameterNode)
        {           
            if (parameterNode.ChildNodes.Count > 0)
            {
                foreach (var item in parameterNode.ChildNodes)
                {
                    CalKeys(item);
                }
            }
            else
            {
                if (parameterNode.Selected == true)
                {
                    Keys.Add(parameterNode.Name);
                }
            }
            

        }
        private void Timer_Tick(object sender, EventArgs e)
        {    
            if (Keys.Count > 10)
            {
                WPFMessageBox.ShowWarning("最多显示10个数据");
                timer.Stop();
                return;
            }
            this.DataHistoryView.MyDrawGraphicsControl.ClearPlotPoints();
            var result = GetData(Keys.Distinct().ToList(), currentTime.AddMinutes(-1), DateTime.Now);
            if (result == null)
            {
                return;
            }
            List<PointCollection> cls = new List<PointCollection>();
            for (int i = 0; i < Keys.Count; i++)
            {
                PointCollection points = new PointCollection();
                int k = 1;
                result[Keys[i]].ForEach(point =>
                {
                    points.Add(new Point() { X = point.dateTime.ToOADate(), Y = point.value });
                    k += 1;
                });
                cls.Add(points);
            }
            
            this.DataHistoryView.MyDrawGraphicsControl.PointCollections = cls;
            //if (this.DataHistoryView.MyDrawGraphicsControl.IsHorizontalNavigationEnabled == false && this.DataHistoryView.MyDrawGraphicsControl.IsVerticalNavigationEnabled == false)
            //{
            //    this.DataHistoryView.MyDrawGraphicsControl.FitControlWithoutDrawing();
            //}
            //DateTime dateTimeNow = DateTime.Now;
            this.DataHistoryView.MyDrawGraphicsControl.YPoints.Clear();
            var item = QueryDataClient.Instance.Service.GetHistorySteps(startTime, DateTime.Now);
            if (item.Count > 0)
            {
                item.ForEach(x =>
                {
                    this.DataHistoryView.MyDrawGraphicsControl.YPoints.Add(new CyberX8_Core.StepItem() { StartValue = x.StartTime.ToOADate(),Information=$"{x.RecipeId}:{x.StepNo}" });
                });
            }
        }
        #endregion

    }

    public class QueryIndexer
    {
        public DateTime TimeToken { get; set; }
        public List<string> DataList { get; set; }
        public string Module { get; set; }
    }
    public class KeyData:BindableBase
    {
        public string Key { get; set; }
        public SolidColorBrush _Color;
        public SolidColorBrush Color
        {
            get { return _Color; }
            set { SetProperty(ref _Color, value); }
        }
        public int UniqueId { get; set; }
    }
}