using Arction.Wpf.ChartingMVVM;
using Arction.Wpf.ChartingMVVM.Axes;
using Arction.Wpf.ChartingMVVM.Views.ViewXY;
using mseedChart.Core;
using mseedChart.MainModule.Models;
using Prism.Events;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;

namespace mseedChart.MainModule.ViewModels
{
    public class ChartPlotViewModel : BindableBase
    {
        #region variable
        Dispatcher _dispatcher;
        /// <summary>
        /// Delegate for data generation.
        /// </summary>
        /// <summary>
        /// 当前采样数
        /// </summary>
        public int CurPoints;
        private readonly IEventAggregator _ea;
        private int _selectResult = 0;
        public int SelectResult
        {
            get { return _selectResult; }

            set
            {
                SetProperty(ref _selectResult, value);
            }
        }
        int _channelCount = 60;          // Channel count.
        double _samplingFrequency = 500;  // Sampling frequency (Hz).
        double _xLength = 10;            // X axis length.
        double _previousX = 0;          // Latest X value on axis.
        long _now;                      // Latest time stamp. 
        long _startTicks;               // Controls timing.
        long _samplesOutput;            // Generated samples quantity.

        // Constants
        const double YMin = 30000;       // Minimal y-value.
        const double YMax = 33000;        // Maximal y-value.

        WavesModel _wavesModel;
        #endregion
        /// <summary>
        /// Thread.
        /// </summary>

        private delegate void ChartUpdateFromThreadHandler(double[][] samples);


        private ChartUpdateFromThreadHandler _chartUpdate;

        private Random _rand = new Random((int)DateTime.Now.Ticks);

        #region "属性"
        private int _lChartCount = 1;
        /// <summary>
        /// 波形控件数量
        /// </summary>
        public int LChartCount
        {
            get { return _lChartCount; }
            set { _lChartCount = value; }
        }
        public List<ShareProperty> WaveComList { get; set; }
        private ShareProperty _wavesCombination;
        /// <summary>
        /// 波形组合
        /// </summary>
        public ShareProperty WavesCombination
        {
            get { return _wavesCombination; }
            set
            {
                _wavesCombination = value;
                SetWavesCombination();
            }
        }
        private DataSourcesEnum _dataSources;
        /// <summary>
        /// 数据来源
        /// </summary>
        public DataSourcesEnum DataSources
        {
            get { return _dataSources; }
            set { _dataSources = value; }
        }

        private DataTypeEnum _wavesType;
        /// <summary>
        /// 波形类型
        /// </summary>
        public DataTypeEnum WavesType
        {
            get { return _wavesType; }
            set { _wavesType = value; }
        }

        private DisplayModeEnum _displayMode;
        /// <summary>
        /// 显示模式
        /// </summary>
        public DisplayModeEnum DisplayMode
        {
            get { return _displayMode; }
            set { _displayMode = value; }
        }

        private ScollModeEnum _scollMode;
        /// <summary>
        /// 滚动方式
        /// </summary>
        public ScollModeEnum ScollMode
        {
            get { return _scollMode; }
            set { _scollMode = value; }
        }

        private DateTime _startTime;
        /// <summary>
        /// 开始时间
        /// </summary>
        public DateTime StartTime
        {
            get { return _startTime; }
            set { _startTime = value; }
        }
        private DateTime _endTime;
        /// <summary>
        /// 开始时间
        /// </summary>
        public DateTime EndTime
        {
            get { return _endTime; }
            set { _endTime = value; }
        }

        private int _sampling = 500;
        /// <summary>
        /// 采样频率
        /// </summary>
        public int Sampling
        {
            get { return _sampling; }
            set { _sampling = value; }
        }
        /// <summary>
        /// 延时(min)
        /// </summary>
        public int DelayMin { get; set; } = 10;
        /// <summary>
        /// 文件数据位置
        /// </summary>
        public string FileDataPath { get; set; } = @"D:\TaySystemPath\Downloads";
        private string _cachePath;

        private int _cacheSize;
        /// <summary>
        /// 缓存大小
        /// </summary>
        public int CacheSize
        {
            get { return _cacheSize; }
            set { _cacheSize = value; }
        }
        private ObservableCollection<int> _stationList;
        /// <summary>
        /// 台站列表
        /// </summary>
        public ObservableCollection<int> StationList
        {
            get { return _stationList; }
            set { _stationList = value; }
        }

        private LightningChart _lChartAll;
        /// <summary>
        /// 所有波形
        /// </summary>
        public LightningChart LChartALL
        {
            get { return _lChartAll; }
            set { _lChartAll = value; }
        }
        private LightningChart _lChartZ;
        /// <summary>
        /// Z通道波形
        /// </summary>
        public LightningChart LChartZ
        {
            get { return _lChartZ; }
            set { _lChartZ = value; }
        }
        private LightningChart _lChartE;
        /// <summary>
        /// E通道波形
        /// </summary>
        public LightningChart LChartE
        {
            get { return _lChartE; }
            set { _lChartE = value; }
        }
        private LightningChart _lChartN;
        /// <summary>
        /// N通道波形
        /// </summary>
        public LightningChart LChartN
        {
            get { return _lChartN; }
            set { _lChartN = value; }
        }

        private FrameworkElement childContent;
        public FrameworkElement ChildContent
        {
            get { return childContent; }
            set { childContent = value; }
        }

        private Grid gridChart;

        public Grid GridChart
        {
            get { return gridChart; }
            set { gridChart = value; }
        }


        public List<StationModel> smList;

        #endregion

        public ChartPlotViewModel()
        {
            _dispatcher = Application.Current.Dispatcher;
            SelectResult = 10;
            var wcList = (WavesCombinationEnum[])Enum.GetValues(typeof(WavesCombinationEnum));
            WaveComList = wcList.Select(value => new ShareProperty((int)value, value.ToString())).ToList();
            WavesCombination = WaveComList.SingleOrDefault(wc => wc.ID == 0);

            _chartUpdate = new ChartUpdateFromThreadHandler(FeedNewDataToChartPingPu);


            _wavesModel = new WavesModel();
            LChartALL.ViewXY.XAxes = new AxisXCollection();
            LChartALL.ViewXY.XAxes.Add(_wavesModel.GetAxisX(10));
            InitData();
            (Application.Current.MainWindow as System.Windows.Window).Closing += ApplicationClosingDispose;
            ShowWave();
        }

        private void ShowWave(string obj= "2023-03-29T06:41:21.348")
        {
            string EventTimeStr = obj;
            string datePath = EventTimeStr.Substring(0, 4) + EventTimeStr.Substring(5, 2) + EventTimeStr.Substring(8, 2);
            string dataFilePath = RegionNames.MseedFilePath + "\\" + datePath + "\\";
            string dataFileName = "HA." + EventTimeStr.Substring(0, 4) + EventTimeStr.Substring(5, 2)
                + EventTimeStr.Substring(8, 2) + EventTimeStr.Substring(10, 3)
                + EventTimeStr.Substring(14, 2) + EventTimeStr.Substring(17, 2) + ".01" + RegionNames.DataTypeString;
            string mseedStr = ".mseed";
            string asciiSavePath = RegionNames.TxtFilePath + "\\" + datePath + "\\" + dataFileName + ".txt";
            if (!Directory.Exists(dataFilePath))
            {
                Directory.CreateDirectory(dataFilePath);
            }
            if (!Directory.Exists(Path.GetDirectoryName(asciiSavePath)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(asciiSavePath));
            }
            if (!File.Exists(dataFilePath + dataFileName + mseedStr))
            {

                //TaskData taskData = new TaskData();
                //taskData.EventTimeStr = EventTimeStr;
                //taskData.Tasks = new Task(() =>
                //{
                //    int res = new DownloadWavedata().Download(EventTimeStr, dataFilePath, dataFileName + mseedStr, GlobalConfig.UseWaveDataTable);
                //    if (res > -1)
                //    {
                //        MSeed2Asc(dataFilePath + dataFileName + mseedStr, asciiSavePath);
                //    }
                //    //Console.WriteLine(taskData.IsComplete);
                //});
                //taskData.CallBack = (string res) =>
                //{
                //    _dispatcher.Invoke(() =>
                //    {
                //        UpdateWavesFromTxt(asciiSavePath);
                //        _channelCount = smList.Count * 3;
                //        UpdateChart();
                //        UpdateChartData();
                //    });
                //};
                //TaskQueue.Instance.AddTaskAndRuning(taskData);
            }
            else
            {
                if (!File.Exists(asciiSavePath))
                {
                    MSeed2Asc(dataFilePath + dataFileName + mseedStr, asciiSavePath);
                }
                _dispatcher.Invoke(() =>
                {
                    UpdateWavesFromTxt(asciiSavePath);
                    _channelCount = smList.Count * 3;
                    UpdateChart();
                    UpdateChartData();
                });
            }



        }

        private void UpdateChart()
        {
            //线程问题
            LChartALL.ViewXY.YAxes = new AxisYCollection();
            LChartALL.ViewXY.YAxes.Clear();
            LChartALL.ViewXY.YAxes.AddRange(_wavesModel.CreateYAxisPingPu(smList, LChartALL));
            for (int i = 0; i < LChartALL.ViewXY.YAxes.Count; i++)
            {
                LChartALL.ViewXY.YAxes[i].LabelsColor = Colors.Black;
                LChartALL.ViewXY.YAxes[i].AxisColor = Colors.Black;
                LChartALL.ViewXY.YAxes[i].GridStripColor = Colors.Black;
                LChartALL.ViewXY.YAxes[i].Title.Color = Colors.Black;
                LChartALL.ViewXY.YAxes[i].Title.Shadow.DropColor = Colors.Transparent;
                LChartALL.ViewXY.YAxes[i].Title.Shadow.ContrastColor = Colors.Transparent;
            }
            LChartALL.ViewXY.XAxes = new AxisXCollection();
            LChartALL.ViewXY.XAxes.Add(_wavesModel.GetAxisX(CurPoints / Sampling));
            LChartALL.ViewXY.XAxes[0].LabelsColor = Colors.Black;

            LChartALL.ViewXY.SampleDataSeries = new SampleDataSeriesCollection();
            LChartALL.ViewXY.SampleDataSeries.AddRange(
                _wavesModel.GetSampleDataSeriesPingPu(smList, LChartALL, LChartALL.ViewXY.XAxes[0],
                LChartALL.ViewXY.YAxes, _samplingFrequency));
        }
        private void UpdateChartData()
        {
            double[][] multiChannelData = new double[smList.Count * 3][];
            try
            {
                for (int channelIndex = 0; channelIndex < smList.Count; channelIndex++)
                {
                    multiChannelData[channelIndex * 3] = smList[channelIndex].dz.ToArray();
                    multiChannelData[channelIndex * 3 + 1] = smList[channelIndex].dn.ToArray();
                    multiChannelData[channelIndex * 3 + 2] = smList[channelIndex].de.ToArray();
                }
                // Invoke FeedNewDataToChart.
                _dispatcher.Invoke(_chartUpdate, System.Windows.Threading.DispatcherPriority.ContextIdle,
                    multiChannelData as object);
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        public void UpdateWavesFromTxt(string fn)
        {
            string allStr;
            smList = new List<StationModel>();
            using (StreamReader streamReader = new StreamReader(fn))
            {
                allStr = streamReader.ReadToEnd();
            }
            if (allStr.Length > 0)
            {
                string[] strLines = allStr.Trim().Split(new char[] { '\n' });
                List<string> strList = strLines.ToList();
                int cnt = strList.Count;
                int num = 0;
                string[] snStr = strLines[0].Trim().Split(',');
                string tmpName = snStr[0].Substring(14, 3);
                CurPoints = int.Parse(snStr[1].Trim().Split(' ')[0]);
                StationModel station = new StationModel();
                station.Name = tmpName;
                station.dz = new List<double>();
                station.dn = new List<double>();
                station.de = new List<double>();

                int channelFlag = 0;

                for (int i = 1; i < strLines.Length; i++)
                {
                    string row = strLines[i].Trim();
                    if (strLines[i].Contains("HA"))
                    {
                        string[] rowStr = strLines[i].Split(',');
                        string chnStr1 = rowStr[0].Substring(21, 3);
                        if (chnStr1 == "SHZ")
                        {
                            smList.Add(station);
                            station = new StationModel();
                            station.Name = rowStr[0].Substring(14, 3);
                            channelFlag = 0;//Z
                        }
                        else if (chnStr1 == "SHN")
                        {
                            channelFlag = 1;//N
                        }
                        else
                        {
                            channelFlag = 2;//E
                        }
                    }
                    else
                    {
                        switch (channelFlag)
                        {
                            case 0://Z
                                station.dz.Add(double.Parse(row));
                                break;
                            case 1://N
                                station.dn.Add(double.Parse(row));
                                break;
                            case 2://E
                                station.de.Add(double.Parse(row));
                                break;
                        }
                    }
                }
                smList.Add(station);
                smList.Reverse();
            }
        }
        public void MSeed2Asc(string filePath, string savePath)
        {
            using (Process compiler = new Process())
            {
                compiler.StartInfo.FileName = "mseed2ascii.exe";
                compiler.StartInfo.Arguments = filePath + " -o " + savePath;
                compiler.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                compiler.Start();
                compiler.WaitForExit();
            }
        }
        private void ApplicationClosingDispose(object sender, CancelEventArgs e)
        {
            if (LChartALL != null)
            {
                LChartALL.Dispose();
                LChartALL = null;
            }
        }
        public void Dispose()
        {
            gridChart.Children.Clear();

            if (LChartALL != null)
            {
                LChartALL.Dispose();
                LChartALL = null;
            }
        }
        public void SetWavesCombination()
        {
            switch (WavesCombination.Name)
            {
                case "平铺":
                    LChartCount = 1;
                    CreateGridChartPingPu();
                    break;
                case "叠加":
                    LChartCount = 1;
                    CreateGridChartDieJia();
                    break;
                case "分类":
                    LChartCount = 3;
                    CreateGridChartFenLei();
                    break;
            }
        }
        public void CreateGridChartPingPu()
        {
            if (LChartALL != null)
            {
                LChartALL = null;
            }

            LChartALL = new LightningChart();
            LChartALL.Title.Text = "事件波形";
            LChartALL.Title.Color = Colors.Black;
            LChartALL.Title.Shadow.DropColor = Colors.Transparent;
            LChartALL.Title.Shadow.ContrastColor = Colors.Transparent;
            LChartALL.Title.Font = new WpfFont("等线", 20);

            LChartALL.ViewXY.AxisLayout.YAxesLayout = YAxesLayout.Stacked;

            LChartALL.ViewXY.AxisLayout.SegmentsGap = 0;
            LChartALL.ViewXY.ZoomPanOptions.PanDirection = PanDirection.Horizontal;
            LChartALL.ViewXY.ZoomPanOptions.WheelZooming = WheelZooming.Horizontal;

            //背景颜色
            LChartALL.ViewXY.GraphBackground.Color = Colors.White;
            LChartALL.ViewXY.GraphBackground.GradientFill = GradientFill.Solid;
            LChartALL.ViewXY.GraphBackground.GradientColor = Colors.White;
            LChartALL.ChartBackground.GradientFill = GradientFill.Solid;
            LChartALL.ChartBackground.Color = Color.FromArgb(0, 0, 0, 0);

            GridChart = new Grid();
            GridChart.ColumnDefinitions.Add(new ColumnDefinition());
            GridChart.Name = "chartGrid";
            GridChart.Children.Add(LChartALL);

            this.ChildContent = GridChart;
        }
        public void CreateGridChartDieJia()
        {
            if (LChartALL != null)
            {
                LChartALL = null;
            }
            LChartALL = new LightningChart();
            LChartALL.Title.Text = "叠加";

            GridChart = new Grid();
            GridChart.ColumnDefinitions.Add(new ColumnDefinition());
            GridChart.Name = "chartGrid";
            GridChart.Children.Add(LChartALL);

            this.ChildContent = GridChart;
        }
        public void CreateGridChartFenLei()
        {
            LChartZ = new LightningChart();
            LChartALL.Title.Text = "Z";
            LChartZ.SetValue(Grid.ColumnProperty, 0);

            LChartE = new LightningChart();
            LChartALL.Title.Text = "E";
            LChartE.SetValue(Grid.ColumnProperty, 1);

            LChartN = new LightningChart();
            LChartALL.Title.Text = "N";
            LChartN.SetValue(Grid.ColumnProperty, 2);

            GridChart = new Grid();
            GridChart.ColumnDefinitions.Add(new ColumnDefinition());
            GridChart.ColumnDefinitions.Add(new ColumnDefinition());
            GridChart.ColumnDefinitions.Add(new ColumnDefinition());

            GridChart.Name = "chartGrid";
            GridChart.Children.Add(LChartZ);
            GridChart.Children.Add(LChartE);
            GridChart.Children.Add(LChartN);
            this.ChildContent = GridChart;
        }
        private void InitData()
        {
            LChartALL.ViewXY.YAxes = new AxisYCollection();
            LChartALL.ViewXY.YAxes.Clear();
            RegionNames.StationDic= RegionNames.CreateStationFromCSV(AppDomain.CurrentDomain.BaseDirectory + @"resources/N3102_staion_20230312.txt");
            LChartALL.ViewXY.YAxes.AddRange(_wavesModel.CreateYAxisPingPu(RegionNames.StationDic, LChartALL));
            for (int i = 0; i < LChartALL.ViewXY.YAxes.Count; i++)
            {
                LChartALL.ViewXY.YAxes[i].LabelsColor = Colors.Black;
                LChartALL.ViewXY.YAxes[i].AxisColor = Colors.Black;
                LChartALL.ViewXY.YAxes[i].GridStripColor = Colors.Black;
                LChartALL.ViewXY.YAxes[i].Title.Color = Colors.Black;
                LChartALL.ViewXY.YAxes[i].Title.Shadow.DropColor = Colors.Transparent;
                LChartALL.ViewXY.YAxes[i].Title.Shadow.ContrastColor = Colors.Transparent;
                LChartALL.ViewXY.YAxes[i].Title.Font = new WpfFont("Calibri", 12);
            }
            LChartALL.ViewXY.XAxes = new AxisXCollection();
            LChartALL.ViewXY.XAxes.Add(_wavesModel.GetAxisX(CurPoints / Sampling));
            LChartALL.ViewXY.XAxes[0].LabelsColor = Colors.Black;

            LChartALL.ViewXY.SampleDataSeries = new SampleDataSeriesCollection();
            LChartALL.ViewXY.SampleDataSeries.AddRange(
                _wavesModel.GetSampleDataSeriesPingPu(RegionNames.StationDic, LChartALL, LChartALL.ViewXY.XAxes[0],
                LChartALL.ViewXY.YAxes, _samplingFrequency));
            //string mseedPath = FileDataPath + "\\" + StartTime.Year.ToString("D2");
            //Console.WriteLine(mseedPath);
            //Start();
        }
        private void FeedNewDataToChartPingPu(double[][] data)
        {
            LChartALL.BeginUpdate();

            for (int channelIndex = 0; channelIndex < _channelCount; channelIndex++)
            {
                LChartALL.ViewXY.SampleDataSeries[channelIndex].AddSamples(data[channelIndex], true);
                //LChartALL.ViewXY.YAxes[channelIndex].Minimum = data[channelIndex].Min();
                //LChartALL.ViewXY.YAxes[channelIndex].Maximum = data[channelIndex].Max();
            }

            _previousX = (double)_samplesOutput / _samplingFrequency;

            LChartALL.ViewXY.XAxes[0].ScrollPosition = _previousX;
            LChartALL.EndUpdate();

        }

    }
    /// <summary>
    /// 波形组合
    /// </summary>
    public enum WavesCombinationEnum
    {
        平铺 = 0,
        叠加,
        分类
    }
    /// <summary>
    /// 波形类型
    /// </summary>
    public enum DataTypeEnum
    {
        原始数据 = 0,
        事件数据
    }
    /// <summary>
    /// 数据来源
    /// </summary>
    public enum DataSourcesEnum
    {
        文件 = 0,
        数据库
    }
    /// <summary>
    /// 显示模式
    /// </summary>
    public enum DisplayModeEnum
    {
        自动 = 0,
        手动
    }
    public enum ScollModeEnum
    {
        Scrolling = 0,
        Stepping
    }
}
