using Aspose.Cells;
using log4net;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using SciColorMaps.Portable;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using Txgy.EWS.Client.Common.Helpers;
using Txgy.EWS.Client.FocalMechanism.Core;
using Txgy.EWS.Client.FocalMechanism.Model;
using Txgy.EWS.Client.Models;
using Txgy.Microseismic.BaseLib.Models;
using WW.Cad.Base;
using FmGrid = Txgy.EWS.Client.FocalMechanism.Model.FmGrid;
using FMStation = Txgy.EWS.Client.FocalMechanism.Model.FMStation;

namespace Txgy.EWS.Client.Common
{
    public class GlobalConfig
    {
        public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;
        public static bool IsDesign = false;
       

        public static DateTime DStartTime = new DateTime(2023, 2, 3, 0, 0, 0);
        public static int DRefreshInterval = 1;
        /// <summary>
        /// 设备整体灵敏度
        /// </summary>
        public const double KW = 833760427.0;
        /// <summary>
        /// 波形截取长度(点数)
        /// </summary>
        public const int WaveCutLen = 1000;
        public static string timeFormatStr = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFF";
        public static ProjectConfigModel ProjectConfig { get; set; }
        public static FocalMechanism.Model.FmGrid fmGrid { get; set; }
        public static int StationCount;
        public static double BaseX, BaseY,BaseZ;
        public static List<string> DwgLayersDisplay = new List<string>();
        public static double MidML = -2;
        //public static List<Color> eventDepthColor = new List<Color>();        

        public static bool IsRealtime;
        public static string UseResultTable;
        public static string UseWaveDataTable;
        public static string UseFocalMechanismTable;
        public static string DataTypeString;
        public static string EventIDColName;
        public static DateTime DailyReportStartTime = new DateTime();
        public static double DailyReportPlanOffX = 0;
        public static double DailyReportPlanOffY = 0;
        public static Color[] eventDepthColor;
        public static string ColorPalette = "plasma";
        public static int ColorCountDefault = 256;
        public static double eventDSize = 1;

        public static ProcessCore fmCore;
        public static Factory fmFactory;
        private static ObservableCollection<CadLayerModel> cadLayerConfigs = new ObservableCollection<CadLayerModel>();

        public static ObservableCollection<CadLayerModel> CadLayerConfigs
        {
            get { return cadLayerConfigs; }
            set
            {
                cadLayerConfigs = value;
                StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs("CadLayerConfigs"));
            }
        }
     
        private static int _loadDataTimeLenMins = 720;
        private static double _dataLookbackHours = 12;
        public static double DataLookbackHours
        {
            get { return _dataLookbackHours; }
            set
            {
                if (value <= 0)
                {
                    throw new InvalidOperationException("数据回看时长必须大于 0。");
                }

                _dataLookbackHours = value;
                _loadDataTimeLenMins = (int)Math.Round(value * 60.0);
                _dataCacheTimeLenMins = _loadDataTimeLenMins;
                StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs("DataLookbackHours"));
                StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs("LoadDataTimeLenMins"));
                StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs("DataCacheTimeLenMins"));
                BusinessConfigManager.UpdateDataLookbackHours(value);
            }
        }
        //程序启动时，数据加载时间
        public static int LoadDataTimeLenMins
        {
            get { return _loadDataTimeLenMins; }
            set { 
                DataLookbackHours = value / 60.0;
            }
        }
        private static int _dataCacheTimeLenMins = 720;

        //程序中数据缓存的时长
        public static int DataCacheTimeLenMins
        {
            get { return _dataCacheTimeLenMins; }
            set { 
                DataLookbackHours = value / 60.0;
            }
        }

        public static void InitializeRuntimeSettings(RuntimeSettings runtime)
        {
            IsDesign = runtime.IsDesign;
            _dataLookbackHours = runtime.DataLookbackHours;
            _loadDataTimeLenMins = runtime.LoadDataTimeLenMins;
            _dataCacheTimeLenMins = runtime.DataCacheTimeLenMins;
            StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs("DataLookbackHours"));
            StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs("LoadDataTimeLenMins"));
            StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs("DataCacheTimeLenMins"));
        }

        public static void ApplyBusinessConfig(BusinessConfig config)
        {
            InitializeRuntimeSettings(config.Runtime);
            SystemNameCN = config.Branding.SystemNameCn;
            SystemNameEN = config.Branding.SystemNameEn;
            CommpanyName = config.Branding.CommpanyName;
            WorkAreaName = config.Branding.WorkAreaName;
            SystemShortName = config.Branding.SystemShortName;
            IsRealtime = config.Runtime.IsRealtime;
            BaseX = config.Coordinates.BaseX;
            BaseY = config.Coordinates.BaseY;
            BaseZ = config.Coordinates.BaseZ;
            DailyReportStartTime = DateTime.Parse(config.Report.DailyReportStartTime);
            DailyReportPlanOffX = config.Report.DailyReportPlanOffsetX;
            DailyReportPlanOffY = config.Report.DailyReportPlanOffsetY;
            ApplyTableSettings(config);
        }

        private static void ApplyTableSettings(BusinessConfig config)
        {
            if (IsRealtime)
            {
                UseResultTable = config.Database.Tables.RealtimeResultTable;
                UseFocalMechanismTable = config.Database.Tables.RealtimeFocalmechanismTable;
                UseWaveDataTable = config.Database.Tables.RealtimeWaveDataTable;
                DataTypeString = "A";
                EventIDColName = "RTEventID";
            }
            else
            {
                UseResultTable = config.Database.Tables.PostResultTable;
                UseFocalMechanismTable = config.Database.Tables.PostFocalmechanismTable;
                UseWaveDataTable = config.Database.Tables.PostWaveDataTable;
                DataTypeString = "B";
                EventIDColName = "PostEventID";
            }
        }

        private static bool _isInitializing=false;
        public static bool IsInitializing
        {
            get { return _isInitializing; }
            set
            {
                _isInitializing = value;
                StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs("IsInitializing"));
            }
        }
        private static double _initializingCounter = 0.0;
        public static double InitializingCounter
        {
            get { return _initializingCounter; }
            set
            {
                _initializingCounter = value;
                StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs("InitializingCounter"));
            }
        }
        private static string _systemNameCN;
        public static string SystemNameCN
        {
            get { return _systemNameCN; }
            set
            {
                _systemNameCN = value;
                StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs("SystemNameCN"));
            }
        }
        private static string _systemNameEN;

        public static string SystemNameEN
        {
            get { return _systemNameEN; }
            set
            {
                _systemNameEN = value;
                StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs("SystemNameEN"));
            }
        }
        
        private static string _commpanyName;
        
        public static string CommpanyName
        {
            get { return _commpanyName; }
            set
            {
                _commpanyName = value;
                StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs("CommpanyName"));
            }
        }
        private static string _workAreaName;

        public static string WorkAreaName
        {
            get { return _workAreaName; }
            set
            {
                _workAreaName = value;
                StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs("WorkAreaName"));
            }
        }
        private static string _systemShortName;

        public static string SystemShortName
        {
            get { return _systemShortName; }
            set
            {
                _systemShortName = value;
                StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs("SystemShortName"));
            }
        }
        public static void ReadConfig()
        {
            var config = BusinessConfigManager.Current;
            ApplyBusinessConfig(config);
            string jsonText;
            //读取工区配置文件
            using (System.IO.StreamReader sr = new System.IO.StreamReader(AppDomain.CurrentDomain.BaseDirectory +
                config.Paths.WorkAreaFilePath))
            {
                jsonText = sr.ReadToEnd();
            }
            ProjectConfig = JsonConvert.DeserializeObject<ProjectConfigModel>(jsonText);

            //初始化波形数据、Json文件路径
            InitializationPath();

            //从ProjectConfig中读取EMin,NMin作为X,Y基址
            BaseX = 0;
            BaseY = 0;
            //BaseX = ProjectConfig.WorkArea.EMin;
            //BaseY = ProjectConfig.WorkArea.NMin;
            BaseZ= config.Coordinates.BaseZ;

            //读取Dwg图层配置文件
            string jsonFile = AppDomain.CurrentDomain.BaseDirectory +
                config.Paths.DwgJsonSetting;
            var jlist = CadLayerModel.CreateFromJson(jsonFile);
            GlobalConfig.CadLayerConfigs = new ObservableCollection<CadLayerModel>(jlist);
            foreach (var item in GlobalConfig.CadLayerConfigs)
            {
                item.SetColor();
            }

            //读取报表事件分级配置文件
            string eventLevelFile= AppDomain.CurrentDomain.BaseDirectory +
                config.Paths.ReportEventLevelSetting;
            var elList = ReportEventLevel.CreateFromJson(eventLevelFile);
            GlobalData.ReportEventLevelList= new ObservableCollection<ReportEventLevel>(elList);

            //日报起始时间
            string drTime = config.Report.DailyReportStartTime;
            
            DailyReportStartTime = DateTime.Parse(drTime);
            //MessageBox.Show($"配置文件中的日报时间：{drTime}\t参数：{DailyReportStartTime.ToShortTimeString()}");
            //Console.WriteLine(DailyReportStartTime.ToString());
            //日报表平面图横向偏移
            DailyReportPlanOffX = config.Report.DailyReportPlanOffsetX;

            //日报表平面图纵向偏移
            DailyReportPlanOffY = config.Report.DailyReportPlanOffsetY;
            //Console.WriteLine(DailyReportStartTime.ToString());
            //设置实时监测数据配置文件
            ApplyTableSettings(config);
            
            ProjectConfig.CadFileName = AppDomain.CurrentDomain.BaseDirectory +
                config.Paths.CadDwgFilePath;

            ProjectConfig.StationDic = CreateStationFromCSV(AppDomain.CurrentDomain.BaseDirectory +
                config.Paths.StationsCsvFilePath);
            //台站数量
            StationCount = ProjectConfig.StationDic.Count;

            //创建深度颜色数组
            var colorMap = new ColorMap(ColorPalette, colorCount: ColorCountDefault);
            //var cmap3 = new MirrorColorMap(cmap2);
            eventDepthColor = colorMap.Colors().Select((color) => color.ToMediaColor()).ToArray();

            //配置震源机制参数
            FocalMechanism.Model.FmGrid fmGrid = CreateFmGrid(GlobalConfig.ProjectConfig.WorkArea.EMax - GlobalConfig.ProjectConfig.WorkArea.EMin,
                GlobalConfig.ProjectConfig.WorkArea.NMax - GlobalConfig.ProjectConfig.WorkArea.NMin, GlobalConfig.ProjectConfig.StationDic);
            GlobalConfig.fmCore = new ProcessCore(fmGrid);
            GlobalConfig.fmFactory = new Factory(fmGrid);
        }
        public static void InitializationPath()
        {
            var config = BusinessConfigManager.Current;
            ProjectConfig.MseedFilePath = config.Paths.WavesMseedFilePath;
            ProjectConfig.TxtFilePath= config.Paths.WavesTxtFilePath;
            if (!Directory.Exists(ProjectConfig.MseedFilePath))
            {
                Directory.CreateDirectory(ProjectConfig.MseedFilePath);
            }

            if (File.Exists(ProjectConfig.TxtFilePath))
            {
                // Console.WriteLine(File.GetAttributes(ProjectConfig.CacheFilePath).ToString());
                File.SetAttributes(ProjectConfig.TxtFilePath, FileAttributes.Hidden);
            }
            else
            {
                Directory.CreateDirectory(ProjectConfig.TxtFilePath);
                File.SetAttributes(ProjectConfig.TxtFilePath, FileAttributes.Hidden);
            }
        }
        public static void SaveConfig()
        {

        }
        public static Dictionary<string, StationModel> CreateStationFromCSV(string fn)
        {
            Dictionary<string, StationModel> stations = new Dictionary<string, StationModel>();
            Aspose.Cells.TxtLoadOptions lo = new TxtLoadOptions();
            lo.Encoding = Encoding.Default;//设置编码方式
            Workbook workbook = new Workbook(fn, lo);

            //配置读取文件的类型（CSV）
            workbook.FileFormat = FileFormatType.CSV;//可在此配置Excel文件类型
            Worksheet worksheet = workbook.Worksheets[0];//默认第一个Sheet页

            Cells cells = worksheet.Cells;

            //读取到DataTable中            
            DataTable dt = cells.ExportDataTableAsString(0, 0, cells.MaxDataRow + 1, cells.MaxColumn + 1, true);
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                DataRow row = dt.Rows[i];
                StationModel model = new StationModel();
                model.Name = row[1].ToString();
                model.E = double.Parse(row[2].ToString());
                model.N = double.Parse(row[3].ToString());
                model.Z = double.Parse(row[4].ToString());
                model.Sens = double.Parse(row[5].ToString());
                model.BeginUseTime = DateTime.Parse(row[6].ToString());
                model.StopUseTime = DateTime.Parse(row[7].ToString());
                stations.Add(model.Name, model);
            }
            //释放资源         
            workbook = null;
            worksheet = null;
            return stations;
        }

        public static FmGrid CreateFmGrid(ProjectConfigModel projectConfigModel)
        {
            FmGrid fg = new FmGrid();
            fg.xmax = projectConfigModel.WorkArea.EMax - projectConfigModel.WorkArea.EMin;
            fg.ymax = projectConfigModel.WorkArea.NMax - projectConfigModel.WorkArea.NMin;
            fg.xmin = 0;
            fg.ymin = 0;
            fg.StationCount = projectConfigModel.StationDic.Count;
            fg.StationList = new List<FMStation>();
            int sc = 0;
            foreach (var item in projectConfigModel.StationDic)
            {
                fg.StationList.Add(new FMStation(sc, item.Key, item.Value.E - projectConfigModel.WorkArea.EMin,
                    item.Value.N - projectConfigModel.WorkArea.NMin));
                fg.StationList.Add(new FMStation(sc, item.Key, item.Value.E, item.Value.N));
                sc++;
            }
            fg.initZeroCenter();
            fg.computeDistance();
            return fg;
        }
        public static List<string> ReadDwgLayerDisplay()
        {
            List<string> lds= new List<string>();
            var dwgSettings = BusinessConfigManager.GetRequiredPath(BusinessConfigManager.Current.Paths.DwgSettings, "paths.dwgSettings");
            string filePath = AppDomain.CurrentDomain.BaseDirectory + 
                dwgSettings;
            string[] rows;
            using (StreamReader sr=new StreamReader(filePath))
            {
                rows = sr.ReadToEnd().Trim().Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
            }
            for (int i = 1; i < rows.Length; i++)
            {
                lds.Add(rows[i].Trim('\r'));
            }
            return lds;
        }

        public static FocalMechanism.Model.FmGrid CreateFmGrid(double XMax, double YMax, Dictionary<string, StationModel> StationDic)
        {
            FocalMechanism.Model.FmGrid fmGrid = new FocalMechanism.Model.FmGrid();
            fmGrid.xmin = 0;
            fmGrid.xmax = XMax;
            fmGrid.ymin = 0;
            fmGrid.ymax = YMax;
            fmGrid.StationCount = StationDic.Count;
            fmGrid.StationList = new List<FocalMechanism.Model.FMStation>();
            int sc = 0;
            foreach (var item in StationDic)
            {
                fmGrid.StationList.Add(new FocalMechanism.Model.FMStation(sc, item.Key, item.Value.E - GlobalConfig.ProjectConfig.WorkArea.EMin,
                    item.Value.N - GlobalConfig.ProjectConfig.WorkArea.NMin));
                sc++;
            }
            fmGrid.initZeroCenter();
            fmGrid.computeDistance();

            return fmGrid;            
        }
        public static class LogObject
        {
            public static ILog Log(string LoggerName)
            {   //log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
                return LogManager.GetLogger(LoggerName);
            }
        }
        public static void WriteLog(string exp = null, string loggerName = "InfoLogger")
        {
            //新建的一个静态类
            LogObject.Log(loggerName).Info(exp);
            LogObject.Log(loggerName).Error(exp);
        }
        public static Point3D AbsoluteCoord2RelativeCoord(GridItemEventResult pp)
        {
            Point3D pd = new Point3D();
            pd.X = (double)(pp.X - BaseX);
            pd.Y = (double)(pp.Y - BaseY);
            pd.Z = (double)((BaseZ-pp.Z));
            return pd;
        }
    }
    public static class ColorUtils
    {
        public static Color ToMediaColor(this byte[] rgb)
        {
            return Color.FromRgb(rgb[0], rgb[1], rgb[2]);
        }
    }
}
