using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Forms;
using Aitex.Core.RT.Log;
using Aitex.Sorter.Common;
using MECF.Framework.Common.DataCenter;
using MECF.Framework.Common.Equipment;
using MECF.Framework.UI.Client.CenterViews.DataLogs.Event;
using MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory;
#if !EXPORT_TO_CSV
using MECF.Framework.Common.Utilities;
#endif
using MECF.Framework.UI.Client.CenterViews.Operations.RealTime;
using MECF.Framework.UI.Client.ClientBase;
using MECF.Framework.UI.Client.ClientBase.Charting;
using MECF.Framework.UI.Client.ClientBase.EventArgs;
using MECF.Framework.UI.Client.ClientBase.Pipelines;
using MECF.Framework.UI.Client.ClientBase.Tree;
using SciChart.Charting.Model.DataSeries;
using SciChart.Charting.Visuals.Axes;
using SciChart.Charting.Visuals.RenderableSeries;
using SciChart.Core.Extensions;
using SciChart.Core.Framework;
using SciChart.Data.Model;
using Cali = Caliburn.Micro;
using DataGridCell = System.Windows.Controls.DataGridCell;
using DateRange = SciChart.Data.Model.DateRange;
using MessageBox = System.Windows.MessageBox;
using TreeNode = MECF.Framework.UI.Client.ClientBase.Tree.TreeNode;
namespace MECF.Framework.UI.Client.CenterViews.DataLogs.DataHistory
{
    public class DataViewModel : BusyIndicateableUiViewModelBase
    {
        #region Variables
        /// 
        /// 一次最多查询的项目数。
        /// 
        private const int MAX_ITEMS_PER_QUERY = 50;
        private IRange _timeRange;
        private IRange _visibleRangeValue;
        private AutoRange _autoRange;
        private CancellationTokenSource _cancellationTokenSource;
        /// 
        /// 更新报告导出信息。
        /// 
        private readonly IProgress _progCsvExport;
        /// 
        /// 查询进度信息更新。
        /// 
        private IProgress _progQueryUpdate;
        /// 
        /// 挂起或恢复Chart更新
        /// 
        private readonly IProgress _progChartSuspendUpdating;
        private IUpdateSuspender _suspender;
        /// 
        /// 打开错误消息对话框。
        /// 
        private readonly IProgress _progShowErrorMessageBox;
        #endregion
        #region Constructors
        public DataViewModel()
        {
            DisplayName = "Data History";
            SelectedData = new ChartingLineSeriesCollection(DisplayName);
            var now = DateTime.Today;
            SearchBeginTime = DateTime.Now.AddHours(-1); // -new TimeSpan(1, 0, 0, 0);
            SearchEndTime = DateTime.Now;
            //SearchBeginTime = new DateTime(now.Year, now.Month, now.Day, 00, 00, 00); ;// -new TimeSpan(1, 0, 0, 0);
            //SearchEndTime = new DateTime(now.Year, now.Month, now.Day, 23, 59, 59);
            var provider = new RealtimeProvider();
            ParameterNodes = new TreeNode(DisplayName)
            {
                MaxTerminalSelectionAllowed = MAX_ITEMS_PER_QUERY
            };
            ParameterNodes.ChildNodes.AddRange(provider.GetTreeNodeParameters());
            VisibleRangeTime = new DateRange(DateTime.Now.AddMinutes(-60), DateTime.Now.AddMinutes(60));
            VisibleRangeValue = new DoubleRange(0, 10);
            _progQueryUpdate = new Progress(e =>
            {
                if (e.CurrentProgress == e.TotalProgress)
                {
                    IsBusy = false;
                    if (_cancellationTokenSource?.Token.IsCancellationRequested == false)
                    {
                        foreach (var renderableSeries in SelectedData)
                        {
                            var series = renderableSeries as FastLineSeries;
                            var dataSeries = series?.GetDataSeries();
                            try
                            {
                                if (series != null && dataSeries != null)
                                {
                                    var node = series.BackendParameterNode;
                                    if (double.IsInfinity((double)dataSeries.YRange.Diff))
                                    {
                                        node.ClearStatistic();
                                    }
                                    else
                                    {
                                        var min = ((double)dataSeries.YMin);
                                        var max = ((double)dataSeries.YMax);
                                        var average =
                                            dataSeries.Metadata.Cast().Average(x => x.Value);
                                        node.SetStatistic(min, max, average);
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                var err = $"It's failed to load data of {series?.DataName ?? "Unknown"}, {ex.Message}";
                                LOG.Error(err, ex);
                            }
                        }
                    }
                    ChartAutoRange = AutoRange.Never;
                    ((DataView)View).chart.ZoomExtents();
                }
                BusyIndicatorContent = e.Message;
            });
            _progCsvExport = new Progress(e =>
            {
                BusyIndicatorContent = e.Message;
            });
            _progChartSuspendUpdating = new Progress(isSuspend =>
            {
                if (isSuspend)
                    _suspender = ((DataView)View).chart.SuspendSuspendUpdates();
                else
                {
                    try
                    {
                        if (_suspender?.IsSuspended == true)
                            _suspender?.SafeDispose();
                    }
                    catch (Exception)
                    {
                        // 查询过程最后会强制恢复挂起一次,可能引发异常,忽略此异常。
                    }
                }
            });
            _progShowErrorMessageBox = new Progress((error =>
            {
                System.Windows.Forms.MessageBox.Show(error, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }));
        }
        #endregion
        #region Property
        public bool IsPermission => Permission == 3;
        private DataView view;
        public TreeNode ParameterNodes { get; }
        public ChartingLineSeriesCollection SelectedData { get; set; }
        public AutoRange ChartAutoRange
        {
            get => _autoRange;
            set
            {
                _autoRange = value;
                NotifyOfPropertyChange(nameof(ChartAutoRange));
            }
        }
        public IRange VisibleRangeTime
        {
            get => _timeRange;
            set
            {
                _timeRange = value;
                NotifyOfPropertyChange(nameof(VisibleRangeTime));
            }
        }
        public IRange VisibleRangeValue
        {
            get => _visibleRangeValue;
            set
            {
                _visibleRangeValue = value;
                NotifyOfPropertyChange(nameof(VisibleRangeValue));
            }
        }
        //public DateTime StartDateTime
        //{
        //    get => ((DataView)View).wfTimeFrom.Value;
        //    set
        //    {
        //        ((DataView)View).wfTimeFrom.Value = value;
        //        NotifyOfPropertyChange(nameof(StartDateTime));
        //    }
        //}
        //public DateTime EndDateTime
        //{
        //    get => ((DataView)View).wfTimeTo.Value;
        //    set
        //    {
        //        ((DataView)View).wfTimeTo.Value = value;
        //        NotifyOfPropertyChange(nameof(EndDateTime));
        //    }
        //}
        public DateTime SearchBeginTime { get; set; }
        public DateTime SearchEndTime { get; set; }
        #endregion
        #region Methods
        protected override void OnViewLoaded(object view)
        {
            base.OnViewLoaded(view);
            this.view = (DataView)view;
            //StartDateTime = DateTime.Now.Date;
            //EndDateTime = DateTime.Now.Date.AddDays(1).AddTicks(-1);
            this.view.wfTimeFrom.Content = SearchBeginTime.ToString("yyyy-MM-dd HH:mm:ss");
            this.view.wfTimeTo.Content = SearchEndTime.ToString("yyyy-MM-dd HH:mm:ss");
        }
        public void SelectDate(string SelectType)
        {
            var windowManager = Caliburn.Micro.Core.IoC.Get();
            if (SelectType == "Start")
            {
                this.SearchBeginTime = Convert.ToDateTime(this.view.wfTimeFrom.Content);
                SelectDateViewModel selectdateViewModel = new SelectDateViewModel(SearchBeginTime);
                var result = (windowManager as Caliburn.Micro.WindowManager)?.ShowDialogWithTitle(selectdateViewModel, null, "Start Time");
                if (result == true)
                {
                    SearchBeginTime = selectdateViewModel.SearchDate;
                    this.view.wfTimeFrom.Content = selectdateViewModel.SearchDate;
                }
            }
            else
            {
                this.SearchEndTime = Convert.ToDateTime(this.view.wfTimeTo.Content);
                SelectDateViewModel selectdateViewModel = new SelectDateViewModel(SearchEndTime);
                var result = (windowManager as Caliburn.Micro.WindowManager)?.ShowDialogWithTitle(selectdateViewModel, null, "End Time");
                if (result == true)
                {
                    this.view.wfTimeTo.Content = selectdateViewModel.SearchDate;
                }  
            }
        }
        public void ToLeftClick()
        {
            var view = GetView() as DataView;
            view.chart.sciChart.ChartModifier.XAxis.Scroll(-50, SciChart.Charting.ClipMode.ClipAtMin);
        }
        public void ToRightClick()
        {
            var view = GetView() as DataView;
            view.chart.sciChart.ChartModifier.XAxis.Scroll(50, SciChart.Charting.ClipMode.ClipAtMax);
        }
        public void ZoomInClick()
        {
            var view = GetView() as DataView;
            view.chart.sciChart.ChartModifier.XAxis.ZoomBy(-0.1, -0.1);
            view.chart.sciChart.ChartModifier.YAxis.ZoomBy(-0.1, -0.1);
        }
        public void ZoomOutClick()
        {
            var view = GetView() as DataView;
            view.chart.sciChart.ChartModifier.XAxis.ZoomBy(0.1, 0.1);
            view.chart.sciChart.ChartModifier.YAxis.ZoomBy(0.1, 0.1);
        }
        public void XZoomInClick()
        {
            var view = GetView() as DataView;
            view.chart.sciChart.ChartModifier.XAxis.ZoomBy(-0.1, -0.1);
        }
        public void XZoomOutClick()
        {
            var view = GetView() as DataView;
            view.chart.sciChart.ChartModifier.XAxis.ZoomBy(0.1, 0.1);
        }
        public void ToMoveUpClick()
        {
            var view = GetView() as DataView;
            view.chart.sciChart.ChartModifier.YAxis.Scroll(-50, SciChart.Charting.ClipMode.ClipAtMin);
        }
        public void ToMoveDownClick()
        {
            var view = GetView() as DataView;
            view.chart.sciChart.ChartModifier.YAxis.Scroll(50, SciChart.Charting.ClipMode.ClipAtMax);
        }
        public void Query(object parameter)
        {
            WaferHistoryRecipe waferHistoryRecipe = parameter as WaferHistoryRecipe;
            if (waferHistoryRecipe != null)
            {
                System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                {
                    if (waferHistoryRecipe.StartTime != DateTime.MinValue)
                        SearchBeginTime = waferHistoryRecipe.StartTime;
                    if (waferHistoryRecipe.EndTime != DateTime.MinValue)
                        SearchEndTime = waferHistoryRecipe.EndTime;
                    else
                        SearchEndTime = waferHistoryRecipe.StartTime.AddHours(1);
                    //ParameterNodes.ForEachDo((x) =>
                    //{
                    //    x.Selected = true;
                    //    ParameterCheck(x);
                    //});
                    QueryData();
                }));
            }
        }
        /// 
        /// 查询数据。
        /// 
        /// 
        public void QueryData(bool isAppend = false)
        {
            this.SearchBeginTime = Convert.ToDateTime(this.view.wfTimeFrom.Content);
            this.SearchEndTime = Convert.ToDateTime(this.view.wfTimeTo.Content);
            if (SearchBeginTime > SearchEndTime)
            {
                MessageBox.Show("time range invalid, start time should be early than end time.", "Error",
                    MessageBoxButton.OK,
                    MessageBoxImage.Error);
                return;
            }
            // 哪些模组(TreeView的顶层Nodes)有选中项。
            var selectedModules = ParameterNodes.ChildNodes.Where(x => x.HasTerminalSelected).ToList();
            if (!selectedModules.Any())
            {
                MessageBox.Show($"No item(s) are selected to query.", "Warning", MessageBoxButton.OK,
                    MessageBoxImage.Warning);
                return;
            }
            VisibleRangeTime = new DateRange(SearchBeginTime.AddHours(-1), SearchEndTime.AddHours(1));
            ChartAutoRange = AutoRange.Always;
            BusyIndicatorContent = "Preparing list ...";
            IsBusy = true;
            _cancellationTokenSource = new CancellationTokenSource();
            #region 生成曲线列表
            var selectedTerminal =
                selectedModules.SelectMany(x => x.Flatten(true).Where(p => p.IsSelected == true)).ToList();
            List appendedSeries = null;
            if (isAppend)
                appendedSeries = SelectedData.Append(selectedTerminal);
            else
            {
                SelectedData.ReArrange(selectedTerminal);
                appendedSeries = SelectedData.ToList();
            }
            SelectedData.ResetColors();
            #endregion
            var dataSeriesList = appendedSeries.Select(x => x.DataSeries).ToList();
            Task.Run(async () =>
            {
                // 延时启动,等待UI准备好
                await Task.Delay(500);
                var pipeline = new TwoStagePipelineBasedTaskExecutor();
                pipeline.Stage2ActionStarted += (s, e) =>
                {
                    // 挂起Chart
                    _progChartSuspendUpdating.Report(true);
                };
                pipeline.Stage2ActionFinished += (s, e) =>
                {
                    // 挂起刷新
                    _progChartSuspendUpdating.Report(false);
                };
                pipeline.Stage1Finished += (s, e) =>
                {
                    // 查询完毕,Chart可能仍在渲染。
                    _progQueryUpdate?.Report(new ProgressUpdatingEventArgs(50, 100, "Still rendering chart ..."));
                };
                using (pipeline)
                {
                    var plTasks = pipeline.Start(null);
                    try
                    {
                        //! 按时间分段查询,解决查询速度慢导致卡后台业务的问题。
                        var ts = SearchEndTime - SearchBeginTime;
                        if (ts.Days <= 1)
                        {
                            Query(pipeline, selectedModules, dataSeriesList, view.dataGrid1, SearchBeginTime, SearchEndTime,
                                _cancellationTokenSource, _progQueryUpdate);
                            // 结束流水线
                            pipeline.AppendFunc1(null);
                            pipeline.AppendFunc2(null);
                        }
                        else
                        {
                            var daySlices =
                                DateRangeHelper.SplitInToHours(new DateRangeHelper(SearchBeginTime, SearchEndTime), 12);
                            foreach (var range in daySlices)
                            {
                                Query(pipeline, selectedModules, dataSeriesList, view.dataGrid1, range.Start, range.End,
                                    _cancellationTokenSource, _progQueryUpdate);
                                if (_cancellationTokenSource.Token.IsCancellationRequested)
                                    break;
                                await Task.Delay(1);
                            }
                            // 结束流水线
                            pipeline.AppendFunc1(null);
                            pipeline.AppendFunc2(null);
                        }
                        await Task.WhenAll(plTasks.ToArray());
                    }
                    catch (ThreadAbortException ex)
                    {
                        Thread.Sleep(500);
                        // 查询操作被取消。
                        Debug.WriteLine(ex);
                    }
                    catch (AggregateException ae)
                    {
                        var errs = new StringBuilder();
                        foreach (var ex in ae.Flatten().InnerExceptions)
                        {
                            LOG.Error(ex.Message, ex);
                            errs.AppendLine(ex.Message);
                        }
                        var errMsg = $"It's failed to query data, {errs}";
                        _progShowErrorMessageBox.Report(errMsg);
                        LOG.Error(errMsg, ae);
                    }
                    catch (Exception ex)
                    {
                        var errMsg = $"It's failed to query data, {ex.Message}";
                        _progShowErrorMessageBox.Report(errMsg);
                        LOG.Error(errMsg, ex);
                    }
                    finally
                    {
                        // 等待一下UI
                        Thread.Sleep(100);
                        _progQueryUpdate.Report(new ProgressUpdatingEventArgs(100, 100, ""));
                        // 强制恢复Chart刷新,避免异常情况导致的Chart挂起。
                        _progChartSuspendUpdating.Report(false);
                    }
                }
            });
        }
        /// 
        /// 查询数据
        /// 
        private static void Query(TwoStagePipelineBasedTaskExecutor pipeline, IEnumerable selectedModules, List dataSeriesList, System.Windows.Controls.DataGrid dataGrid, DateTime startTime, DateTime endTime,
            CancellationTokenSource cancellation, IProgress progressReporter = null)
        {
            pipeline.AppendFunc1(() =>
                SearchDataBaseAsync(
                    selectedModules,
                    new DateRangeHelper(startTime, endTime),
                    cancellation,
                    progressReporter));
            pipeline.AppendFunc2(ds =>
            {
                RenderChartAndTable(ds, dataSeriesList, dataGrid, cancellation, progressReporter);
                return null;
            });
            //pipeline.AppendFunc2(ds =>
            //{
            //    RenderDataGridTable(ds, , cancellation, progressReporter);
            //    return null;
            //});
        }
        /// 
        /// 取消查询。
        /// 
        public void CancelQuery()
        {
            Task.Run(() =>
            {
                if (_cancellationTokenSource?.Token.CanBeCanceled == true)
                {
                    _cancellationTokenSource.Cancel();
                }
                Thread.Sleep(100);
                _progQueryUpdate.Report(new ProgressUpdatingEventArgs(100, 100, ""));
                _progChartSuspendUpdating.Report(false);
            });
            if (View is DataView view)
                view.dataGrid.CancelOperation();
        }
        /// 
        /// 检查指定的表名是否存在。
        /// 
        /// 
        /// 
        private static bool CheckTableExists(string tableName)
        {
            var sql =
                $"SELECT EXISTS ( SELECT FROM pg_tables WHERE schemaname = 'public' AND tablename = '{tableName}' );";
            var table = QueryDataClient.Instance.Service.QueryData(sql);
            if (table == null)
                return false;
            if (table.Rows.Count <= 0)
                return false;
            var value = table.Rows[0][0].ToString();
            if (value.ToLower() == "true")
                return true;
            return false;
        }
        /// 
        /// 根据左侧选项查询数据
        /// 
        /// 
        private static DataSet SearchDataBaseAsync(
            IEnumerable modules, DateRangeHelper dateRange,
            CancellationTokenSource cancellation = null,
            IProgress progressReporter = null)
        {
            var ds = new DataSet();
            using (cancellation?.Token.Register(Thread.CurrentThread.Abort, true))
            {
                // 遍历模组
                foreach (var module in modules)
                {
                    var sql = new StringBuilder();
                    //! 因为数据库中按天拆表,无法一次性查询数据,需使用UNION合并多表查询,因此此处按天拼接SQL表达式
                    // 最终SQL表达式结构为:
                    // (select xx from date1.xx) union (select xx from date2.xx) union (select xx from date3.xx)
                    // where time between xxx and xxx
                    // order by time asc
                    var ts = dateRange.Diff;
                    for (var day = 0; day <= ts.Days; day++)
                    {
                        // 检查表名是否存在,否则SQL执行出错。
                        var tblName = $"{dateRange.Start.AddDays(day):yyyyMMdd}.{module}";
                        if (module.ToString() == "IO")
                        {
                            //var node = module.ChildNodes.FirstOrDefault(x => (bool)x.HasTerminalSelected);
                            tblName = $"{dateRange.Start.AddDays(day):yyyyMMdd}.System";
                        }
                        else
                        if (!ModuleHelper.IsPm(module.ToString()))
                        {
                            tblName = $"{dateRange.Start.AddDays(day):yyyyMMdd}.System";
                        }
                        if (CheckTableExists(tblName))
                        {
                            sql.Append("select \"time\" AS InternalTimeStamp");
                            var selectedParams = module.Flatten(true)
                                .Where(x => x.IsSelected == true);
                            // 添加待查询的列
                            foreach (var item in selectedParams)
                            {
                                sql.Append("," + $"\"{item}\"");
                            }
                            sql.Append($" from \"{tblName}\" ");
                            if (day < ts.Days)
                                sql.Append(" UNION ");
                        }
                    }
                    // 所有表名不可用,可能是日期范围错误
                    if (sql.Length <= 0)
                    {
                        continue;
                    }
                    sql.Append(
                        $" where \"time\" between {dateRange.Start.Ticks} and {dateRange.End.Ticks} order by InternalTimeStamp asc");
                    progressReporter?.Report(new ProgressUpdatingEventArgs(20, 100,
                        $"Querying {dateRange}..."));
                    if (cancellation?.Token.IsCancellationRequested == true)
                        return null;
                    // 查询数据并将返回的结果存储在DataSet中
                    var dataTable = QueryDataClient.Instance.Service.QueryData(sql.ToString());
                    if (cancellation?.Token.IsCancellationRequested == true)
                        return null;
                    //! 返回的 DataTable 可能不存在,原因是上述代码自动生成的表明可能不存在。
                    if (dataTable == null)
                        continue;
                    dataTable.TableName = module.Name;
                    ds.Tables.Add(dataTable);
                }
            }
            return ds;
        }
        /// 
        /// 渲染图表。
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        private static void RenderChartAndTable(
            DataSet ds, List dataSeriesList, System.Windows.Controls.DataGrid dataGrid,
            CancellationTokenSource cancellation = null,
            IProgress progressReporter = null)
        {
            if (ds == null || ds.Tables.Count <= 0)
                return;
            Dictionary> bigTable = new Dictionary>();
            System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            {
                dataGrid.Columns.Clear();
                DataGridTextColumn dataGridTextColumn = new DataGridTextColumn();
                dataGridTextColumn.Header = "Time";
                dataGridTextColumn.Binding = new System.Windows.Data.Binding("internaltimestamp");
                ((System.Windows.Data.Binding)dataGridTextColumn.Binding).Converter = new StringToDateTimeStringConvert();
                dataGrid.Columns.Add(dataGridTextColumn);
            }));
            // 一个Table一个模组
            foreach (var table in ds.Tables.Cast())
            {
                if (table.Rows.Count <= 0)
                    continue;
                // 一列对应模组中的某个数据记录点
                foreach (var col in table.Columns.Cast())
                {
                    // 忽略时间列
                    if (col.Ordinal == 0)
                        continue;
                    Dictionary dictColumn = new Dictionary();
                    var fullName = col.ColumnName;
                    col.ColumnName = col.ColumnName.Replace(".", "");
                    var dataSeries =
                        dataSeriesList.FirstOrDefault(x => x.SeriesName == fullName) as XyDataSeries;
                    if (dataSeries == null)
                        continue;
                    var rows = table.Rows;
                    var dateList = new List();
                    var valueList = new List();
                    var metaList = new List();
                    for (var i = 0; i < rows.Count; i++)
                    {
                        var date = new DateTime(long.Parse(rows[i][0].ToString()));
                        var cellValue = rows[i][col];
                        var value = double.NaN;
                        if (cellValue is bool b)
                            value = b ? 1 : 0;
                        else if (double.TryParse(cellValue.ToString(), out var num))
                            value = num;
                        else
                            value = 0;
                        dateList.Add(date);
                        valueList.Add(value);
                        metaList.Add(new ParameterNodePoint(date, value));
                        dictColumn.Add(long.Parse(rows[i][0].ToString()), value.ToString());
                        if (cancellation?.Token.IsCancellationRequested == true)
                            return;
                    }
                    bigTable.Add(fullName.Replace(".", ""), dictColumn);
                    System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        DataGridTextColumn dataGridTextColumn2 = new DataGridTextColumn();
                        dataGridTextColumn2.Header = fullName;
                        dataGridTextColumn2.Binding = new System.Windows.Data.Binding(fullName.Replace(".", ""));
                        var MyStyle = new Style(typeof(DataGridCell))
                        {
                            Setters = {
        new Setter(TextBlock.TextAlignmentProperty, TextAlignment.Center)
    }
                        };
                        dataGridTextColumn2.CellStyle = MyStyle;
                        dataGrid.Columns.Add(dataGridTextColumn2);
                    }));
                    if (cancellation?.Token.IsCancellationRequested == true)
                        return;
                    dataSeries.Append(dateList, valueList, metaList);
                }
                if (cancellation?.Token.IsCancellationRequested == true)
                    return;
                // 每一轮更新完毕后会恢复Chart刷新,
                // 数据量太小时会频繁挂起和恢复Chart,导致Chart不刷新,需要稍等一下UI。
                Thread.Sleep(50);
            }
            System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            {
                System.Data.DataTable dt = new System.Data.DataTable();
                dt = new System.Data.DataTable($"Temp");
                dt.Columns.Add("internaltimestamp", typeof(long));
                foreach (var item in bigTable.Keys)
                {
                    dt.Columns.Add(item, typeof(string));
                }
                if (bigTable.Count > 0)
                {
                    foreach (var subitem in bigTable[bigTable.FirstOrDefault().Key].Keys)
                    {
                        var row = dt.NewRow();
                        row[0] = subitem;
                        foreach (var col in bigTable.Keys)
                        {
                            row[col] = bigTable[col][subitem];
                        }
                        dt.Rows.Add(row);
                    }
                }
                dataGrid.ItemsSource = dt.DefaultView;
            }));
        }
        public void Exporting(object sender, EventArgs e)
        {
            BusyIndicatorContent = "Exporting Start ...";
            IsBusy = true;
        }
        public void Exported(object sender, EventArgs e)
        {
            IsBusy = false;
        }
        public void Deleted(object sender, EventArgs e)
        {
            ((DataView)View).tvParameterNodes.ClearPresetGroupSelectionOnly();
        }
        public void ProgressUpdating(object sender, ProgressUpdatingEventArgs e)
        {
            _progCsvExport.Report(e);
        }
        #endregion
    }
    public class StringToDateTimeStringConvert : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return new DateTime((Int64)value).ToString("yyyy/MM/dd HH:mm:ss");
        }
        public object ConvertBack(object value, Type targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }
    }
}