using Newtonsoft.Json;
using Prism.Commands;
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Services.Dialogs;
using StartServerWPF.Models;
using StartServerWPF.Modules.Main.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;

namespace StartServerWPF.Modules.Main.ViewModels
{
    public class DataProcessViewModel : BindableBase
    {
        public DataProcessViewModel(MainViewModel mainViewModel, SystemConfigModel configModel, WorkareaModel  workareaModel, WorkareasModelArray workareasModelArray)
        {
            this._mainViewModel = mainViewModel;
            this._systemConfig = configModel;
            this._workareaModel = workareaModel;
            this._workareasModelArray = workareasModelArray;
        }
        private string _title = "应用列表";
        public string Title => _title;

        private readonly MainViewModel _mainViewModel;
        private SystemConfigModel _systemConfig;
        private readonly WorkareaModel _workareaModel;
        private readonly WorkareasModelArray _workareasModelArray;
        private string _dataPath;
        public string DataPath
        {
            get => _dataPath;
            set { SetProperty(ref _dataPath, value); }
        }

        private string _savePath;
        public string SavePath
        {
            get => _savePath;
            set { SetProperty(ref _savePath, value); }
        }

        private DateTime _startSelectedDate;
        public DateTime StartSelectedDate
        {
            get => _startSelectedDate;
            set { SetProperty(ref _startSelectedDate, value); }
        }

        private DateTime _endSelectedDate;
        public DateTime EndSelectedDate
        {
            get => _endSelectedDate;
            set { SetProperty(ref _endSelectedDate, value); }
        }
     
        private int _wareaSelectedIndex;
        public int WareaSelectedIndex
        {
            get => _wareaSelectedIndex;
            set
            {
                if(value >= 0)
                {
                    string path = string.Empty;
                    try
                    {
                        var model = _workareasModelArray.workarea[value];
                        path = Path.Combine(model.filepath, "datapro.json");
                        string jsonStr = File.ReadAllText(path);
                        var datas = JsonConvert.DeserializeObject<List<DataProModel>>(jsonStr);
                        NameSource = new ObservableCollection<DataProModel>();
                        datas.ForEach(d => { NameSource.Add(d); });
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("加载配置失败，"+path);
                    }

                }
                SetProperty(ref _wareaSelectedIndex, value);
            }
        }
        private ObservableCollection<string> _workareaNameSource;
        public ObservableCollection<string> WorkareaNameSource
        {
            get => _workareaNameSource;
            set { SetProperty(ref _workareaNameSource, value); }
        }

        private ObservableCollection<DataProModel> _nameSource=new ObservableCollection<DataProModel>();
        public ObservableCollection<DataProModel> NameSource
        {
            get => _nameSource;
            set { SetProperty(ref _nameSource, value); }
        }
        private int _dataSelectedIndex;
        public int DataSelectedIndex
        {
            get => _dataSelectedIndex;
            set
            {
                if (value >= 0)
                {
                    var item = NameSource[value];
                    StartSelectedDate = item.StartTime;
                    EndSelectedDate = item.EndTime;
                    DataPath = item.DataPath;
                    SavePath = item.ResultPath;
                }
                SetProperty(ref _dataSelectedIndex, value);
            }
        }

        private ObservableCollection<MsEventModel> _apmsEventSource = new ObservableCollection<MsEventModel>();
        public ObservableCollection<MsEventModel> ApmsEventSource
        {
            get => _apmsEventSource;
            set => SetProperty(ref _apmsEventSource, value);
        }
     
        private ObservableCollection<ProcessingInformationModel> _processSliceSource = new ObservableCollection<ProcessingInformationModel>();
        public ObservableCollection<ProcessingInformationModel> ProcessSliceSource
        {
            get => _processSliceSource;
            set => SetProperty(ref _processSliceSource, value);
        }

        private bool _IsBusy = true;
        public bool IsBusy
        {
            get => _IsBusy;
            set { SetProperty(ref _IsBusy, value); }
        }

        public DelegateCommand LoadedCommand => new(() =>
        {
            StartSelectedDate = DateTime.Now;
            EndSelectedDate = DateTime.Now;
            WorkareaNameSource = new ObservableCollection<string>();
            _workareasModelArray.workarea.Select(n => n.workareaname).ToList().ForEach(a => WorkareaNameSource.Add(a));
            WareaSelectedIndex = _workareasModelArray.selectIndex;
           
            var model = _workareasModelArray.workarea[WareaSelectedIndex];
            string jsonStr=  File.ReadAllText(Path.Combine(model.filepath, "datapro.json"));
            var datas= JsonConvert.DeserializeObject<List<DataProModel>>(jsonStr);
            NameSource = new ObservableCollection<DataProModel>();
            datas.ForEach(d => { NameSource.Add(d); });
            DataSelectedIndex = 0;
        });

        public DelegateCommand AddItemCommand => new(() =>
        {
            int count = NameSource.Count()+1;
            NameSource.Add(new DataProModel
            {
                Name = DateTime.Now.ToString("d") +" "+ count.ToString("D2"),
                DataPath = "",
                ResultPath = "",
                StartTime = DateTime.Now,
                EndTime = DateTime.Now
            });
            DataSelectedIndex = NameSource.Count()-1;
        });

        public DelegateCommand DeleteCommand => new(() =>
        {
            if (MessageBox.Show("确认删除？", "警告", MessageBoxButton.OKCancel,
                                MessageBoxImage.Exclamation) == MessageBoxResult.OK)
            {
                NameSource.RemoveAt(DataSelectedIndex);
                DataSelectedIndex = 0;
            };
        });
        public DelegateCommand SaveCommand => new(() =>
        {
            var item = NameSource[DataSelectedIndex];
            item.DataPath = DataPath;
            item.ResultPath = SavePath;
            item.StartTime = StartSelectedDate;
            item.EndTime=EndSelectedDate;
            string jsonStr = JsonConvert.SerializeObject(NameSource, Formatting.Indented);
            var model = _workareasModelArray.workarea[WareaSelectedIndex];
            File.WriteAllText(Path.Combine(model.filepath, "datapro.json"), jsonStr);

            //dataProtools 配置更新
            string temJson = JsonConvert.SerializeObject(_workareaModel);
            var area = JsonConvert.DeserializeObject<WorkareaModel>(temJson); 
            ApmsModel tools = area.apmModel;
            tools.savepath = SavePath;
            tools.station = Path.GetFullPath(Path.Combine(area.savepath, area.apmModel.station)).Replace("\\", "/");
            tools.ttime[0].ttime2d = Path.GetFullPath(Path.Combine(area.savepath, area.apmModel.ttime[0].ttime2d)).Replace("\\", "/");
            JsonParser.WriteSystemConfigFile(Path.Combine(_systemConfig.dataProTools.ProPath, "apms.json"), tools);
        });

        public DelegateCommand<object> SelectFileCommand => new((obj) =>
        {
            string para = obj.ToString();
            System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog();
            //  fbd.SelectedPath = MainModel.DataSavePath;
            fbd.ShowNewFolderButton = true;
            if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string path = fbd.SelectedPath.Replace("\\", "/");
                if (para == "SavePath")
                {
                    SavePath = path;
                }
                else if (para == "DataPath")
                {
                    DataPath = path;
                }

            }
        });


        public ICommand StartCommand
        {
            get => new DelegateCommand(() =>
            {

                // 数据校验（关键字段不能为空、年龄做数字区间的校验、做UserName的唯一检查（自定义特性检查）
                if (string.IsNullOrEmpty(DataPath) || string.IsNullOrEmpty(SavePath))
                {
                    MessageBox.Show("内容不能为空", "提示", MessageBoxButton.OK);
                    return;
                }
                var time = (EndSelectedDate.AddSeconds(-EndSelectedDate.Second) - StartSelectedDate.AddSeconds(-StartSelectedDate.Second));
                if (time.TotalMinutes < 1)
                {
                    MessageBox.Show("结束时间必需大于开始时间", "提示", MessageBoxButton.OK);
                    return;
                }
                DateTime dateTime = StartSelectedDate;
                string temPath = Path.GetPathRoot(_workareaModel.savepath) + "temPath";
                //清除临时文件
                if (Directory.Exists(temPath))
                {
                    Directory.Delete(temPath, true);
                }
                Directory.CreateDirectory(temPath);              
                Task.Run(() =>
                {
                    IsBusy = false;
                    while ((EndSelectedDate - dateTime).TotalMinutes >= 1)
                    {
                        string path = Path.GetFullPath($"{DataPath}\\{dateTime.Month.ToString().PadLeft(2, '0')}\\{dateTime.Day.ToString().PadLeft(2, '0')}\\{dateTime.Hour.ToString().PadLeft(2, '0')}\\{dateTime.Minute.ToString().PadLeft(2, '0')}");
                        dateTime = dateTime.AddMinutes(1);
                        if (!Directory.Exists(path))
                        {
                            continue;
                        }
                        var mseedFiles = new DirectoryInfo(path).EnumerateFiles("*.mseed");
                        //  var mseedFiles = files.Where(i => i.Extension == ".mseed");
                        Parallel.ForEach(mseedFiles, (item) =>
                        {
                            Debug.WriteLine($"***************path:{path},{item.FullName}");
                            File.Copy(item.FullName, Path.Combine(temPath, item.Name), true);
                        });
                    }

                    ProcessInfo process = _systemConfig.dataProTools;
                    int index = process.ProParams.IndexOf("-wave");
                    string str = process.ProParams.Substring(0, index) + "-wave";
                    process.ProParams = $"{str} {temPath}";

                    var mfile = new DirectoryInfo(temPath).EnumerateFiles("*.mseed");
                    if (mfile.Any())
                    {
                        isStart = true;
                        if (fileDic.Count != 0) fileDic.Clear();
                        this.StartProcess(process);
                    }
                    else
                    {
                        IsBusy=true;
                        Application.Current.Dispatcher.InvokeAsync(() =>
                        {
                            AddItems(ProcessSliceSource, new ProcessingInformationModel { ProcessMes = "没有需要处理的文件", MonitorTime = DateTime.Now.ToString() });
                        }, DispatcherPriority.ApplicationIdle);
                    }
                });
            });
        }

        private bool CMDStartProcess(ProcessInfo proInfo)
        {
            //* Create your Process
            Process process = new Process();
            process.Exited += Process_Exited;
            process.EnableRaisingEvents = true;
            process.StartInfo.FileName = Path.GetFullPath(proInfo.ProPath + proInfo.ProName + ".exe");
            process.StartInfo.WorkingDirectory = Path.GetFullPath(proInfo.ProPath);
            process.StartInfo.Arguments = proInfo.ProParams;
            Debug.WriteLine($"*******name:{process.StartInfo.FileName}, arguments:{process.StartInfo.Arguments}*********");
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardError = true;

            process.StartInfo.CreateNoWindow = true;
            //* Set your output and error (asynchronous) handlers
            process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
            process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);

            //* Start process and handlers
            bool res = process.Start();
            process.BeginOutputReadLine();
            process.BeginErrorReadLine();
            return res;
        }

        private  void AddItems<T>(ObservableCollection<T> list, T t1)
        {
            if (list == null)
            {
                return;
            }
            list.Insert(0,t1);
            if (list.Count > 30)
            {
                T item = list[0];
                list.RemoveAt(0);
            }
        }
        Dictionary<string, string> fileDic=new Dictionary<string, string>();
        bool isStart = false;
        void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
        {
            Debug.WriteLine("output*************:{0},{1}", sendingProcess.ToString(), outLine.Data);
            if (string.IsNullOrEmpty(outLine.Data)) return;

            var pro = sendingProcess as Process;
            if (pro != null && pro.MainModule.ModuleName.Contains(_systemConfig.dataProTools.ProName))
            {
                string mes = outLine.Data;
                if (outLine.Data.Contains("run time cost="))
                {
                    int index = mes.IndexOf('[');
                    string str = mes.Substring(index + 1).Replace("]", "");
                    mes = $"处理完成，共耗时{str}";
                }
                else if (outLine.Data.Contains("read HA"))
                {
                    int index = mes.IndexOf("read ");
                    string str = mes.Substring(index + 8).Substring(index, 3);

                    fileDic[str] = outLine.Data;             
                    return;
                }
                else if(isStart && outLine.Data.Contains("ProcessSlice: "))
                {
                    isStart = false;
                    Application.Current.Dispatcher.InvokeAsync(() =>
                    {
                        AddItems(ProcessSliceSource, new ProcessingInformationModel { ProcessMes = $"共载入{fileDic.Keys.Count}组台站数据", MonitorTime = DateTime.Now.ToString() });
                        AddItems(ProcessSliceSource, new ProcessingInformationModel { ProcessMes = "开始处理", MonitorTime = DateTime.Now.ToString() });
                    }, DispatcherPriority.ApplicationIdle);
                }
                Application.Current.Dispatcher.InvokeAsync(() =>
                {
                    AddItems(ProcessSliceSource, new ProcessingInformationModel { ProcessMes =mes, MonitorTime = DateTime.Now.ToString() });
                }, DispatcherPriority.ApplicationIdle);
            }
        }

        private void Process_Exited(object? sender, EventArgs e)
        {
            Debug.WriteLine($"****数据处理程序退出，{e.ToString()}******************");
            IsBusy = true;
            //处理完成后删除临时文件
            //string temPath = Path.GetPathRoot(_workareaModel.savepath) + "temPath";
            //if (Directory.Exists(temPath))
            //{
            //    Directory.Delete(temPath, true);
            //}
            //解析处理后的事件文件
            var fileName = Directory.GetFiles(SavePath, "*.index", SearchOption.AllDirectories);
            List<string> lines = new List<string>();
            foreach (var file in fileName)
            {
                string[] text = File.ReadAllLines(file);
                var data = text.Where(p => StartSelectedDate <= Convert.ToDateTime(p.Split(" ")[0])
                             && EndSelectedDate >= Convert.ToDateTime(p.Split(" ")[0]));
                lines.AddRange(data);
            }
            Application.Current.Dispatcher.BeginInvoke(() =>
            {
                foreach (var item in lines)
                {
                    ApmsEventSource.Add(new MsEventModel(item));
                }
            });
        }


        /// <summary>
        /// 启动进程
        /// </summary>
        /// <param name="proInfo"></param>
        /// <returns>进程启动返回值</returns>
        public int StartProcess(ProcessInfo proInfo)
        {
            bool res = CMDStartProcess(proInfo);
            int seInd = res ? 0 : 37;
            return seInd;
        }
        /// <summary>
        /// 结束进程
        /// </summary>
        /// <param name="processInfo"></param>
        /// <returns>0=成功;1=未找到进程;-1=失败</returns>
        public int KillProcess(ProcessInfo processInfo)
        {
            int ri = 0;
            if (processInfo != null)
            {
                if (processInfo.ProName != null)
                {
                    try
                    {
                        Process[] localByName = Process.GetProcessesByName(processInfo.ProName);
                        if (localByName.Length == 0)
                        {
                            ri = 1;
                            return ri;
                        }
                        foreach (var item in localByName)
                        {
                            Console.WriteLine(item.Id);
                            item.Kill();
                        }
                        return ri;
                    }
                    catch (Exception)
                    {
                        return -1;
                    }
                }
                else
                {
                    return 0;
                }
            }
            else
            {
                return 0;
            }
        }

    }
}
