using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Modbus.Device;
using Modbus;
using OxyPlot;
using OxyPlot.Axes;
using OxyPlot.Legends;
using OxyPlot.Series;
using System.Configuration;
using System.Net.Sockets;
using System.Windows.Interop;
using 口罩泄露定制款;

namespace LineChartDemo
{
    public partial class MainWindow : Window
    {
        private readonly string _lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
        #region 图表相关变量
        private PlotModel _plotModel;
        private LineSeries _exhaleSeries;
        private LineSeries _inhaleSeries;
        private List<DataPoint> _exhaleData = new List<DataPoint>();
        private List<DataPoint> _inhaleData = new List<DataPoint>();
        private DispatcherTimer _dataTimer;
        private double _timeCounter = 0;
        private const int MAX_DATA_POINTS = 30;  // 最多显示30个数据点
        private Function ma;
        private DataChange c = new DataChange();

        // Modbus通信
        private TcpClient _tcpClient;
        private IModbusMaster _modbusMaster;

        // 坐标轴引用
        private LinearAxis _xAxis;
        private LinearAxis _yAxis;

        // 性能优化相关
        private bool _isResizing = false;
        private readonly object _lockObj = new object();
        private CancellationTokenSource _resizeTokenSource;
        #endregion

        #region Modbus相关配置
        private readonly ushort _OutBreathAddress = 0x1398;    // D5016
        private readonly ushort _InBreathAddress = 0x1396;    // D5014
        #endregion

        public MainWindow()
        {
            InitializeComponent();
            RenderOptions.ProcessRenderMode = RenderMode.Default;
            InitializeModbusTcp();
            InitializePlot();
            InitializeEvents();
        }

        #region 窗口大小变化事件
        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            base.OnRenderSizeChanged(sizeInfo);

            if (!_isResizing)
            {
                _isResizing = true;
                _dataTimer?.Stop();
            }

            _resizeTokenSource?.Cancel();
            _resizeTokenSource = new CancellationTokenSource();
            var token = _resizeTokenSource.Token;

            Task.Delay(50, token).ContinueWith(_ =>
            {
                Dispatcher.Invoke(() =>
                {
                    if (!token.IsCancellationRequested)
                    {
                        _plotModel?.InvalidatePlot(true);
                        _isResizing = false;
                        if (StopBtn.IsEnabled)
                        {
                            _dataTimer?.Start();
                        }
                    }
                });
            }, token);
        }
        #endregion

        #region Modbus初始化
        private void InitializeModbusTcp()
        {
            try
            {
                string plcIp = ConfigurationManager.AppSettings["PLC2_IP"];
                int plcPort = int.Parse(ConfigurationManager.AppSettings["PLC2_Port"] ?? "502");

                _tcpClient = new TcpClient();
                var connectResult = _tcpClient.BeginConnect(plcIp, plcPort, null, null);
                bool success = connectResult.AsyncWaitHandle.WaitOne(3000);

                if (!success || !_tcpClient.Connected)
                    throw new Exception(_lang == "en-US" ? "PLC connect timeout" : "连接PLC超时，请检查IP和端口");

                _modbusMaster = ModbusIpMaster.CreateIp(_tcpClient);
                _modbusMaster.Transport.ReadTimeout = 1000;
                _modbusMaster.Transport.WriteTimeout = 1000;

                ma = new Function(_modbusMaster);

                StatusText.Text = _lang == "en-US" ? "Status: Modbus connected" : "状态：Modbus连接成功";
                StatusText.Foreground = new SolidColorBrush(Color.FromRgb(76, 175, 80));
            }
            catch (Exception ex)
            {
                ShowError(_lang == "en-US" ? $"Modbus init failed: {ex.Message}" : $"Modbus初始化失败: {ex.Message}");
                StatusText.Text = _lang == "en-US" ? "Status: Connect failed" : "状态：连接失败";
                StatusText.Foreground = new SolidColorBrush(Color.FromRgb(239, 83, 80));
            }
        }

        private void ShowError(string message) => MessageBox.Show(message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
        #endregion

        #region 图表初始化


        private void InitializePlot()
        {
            _plotModel = new PlotModel
            {
                Title = _lang == "en-US"
                    ? "Flow Monitoring (Latest 30 Points)"
                    : "呼气流量与吸气流量监测（最新30个数据）",
                TitleFontSize = 18,
                TitleFontWeight = OxyPlot.FontWeights.Bold,
                Background = OxyColors.White,
                PlotAreaBackground = OxyColor.FromRgb(250, 252, 255),
            };

            var legend = new Legend
            {
                LegendPlacement = LegendPlacement.Outside,
                LegendPosition = LegendPosition.TopRight,
                FontSize = 14
            };
            _plotModel.Legends.Add(legend);

            _exhaleSeries = new LineSeries
            {
                Title = _lang == "en-US" ? "Exhale Flow (L/min)" : "呼气流量 (L/min)",
                Color = OxyColor.FromRgb(239, 83, 80),
                StrokeThickness = 2,
                MarkerType = MarkerType.None,
                MarkerSize = 4
            };

            _inhaleSeries = new LineSeries
            {
                Title = _lang == "en-US" ? "Inhale Flow (L/min)" : "吸气流量 (L/min)",
                Color = OxyColor.FromRgb(66, 165, 245),
                StrokeThickness = 2,
                MarkerType = MarkerType.None,
                MarkerSize = 4
            };

            _plotModel.Series.Add(_exhaleSeries);
            _plotModel.Series.Add(_inhaleSeries);

            _xAxis = new LinearAxis
            {
                Position = AxisPosition.Bottom,
                Title = _lang == "en-US" ? "Time (s)" : "时间 (秒)",
                TitleFontSize = 14,
                AxislineColor = OxyColors.LightGray,
                MajorGridlineColor = OxyColor.FromRgb(220, 231, 243),
                MajorGridlineStyle = LineStyle.Solid,
                MinorGridlineStyle = LineStyle.None,
                FontSize = 12,
                Minimum = 0
            };

            _yAxis = new LinearAxis
            {
                Position = AxisPosition.Left,
                Title = _lang == "en-US" ? "Flow (L/min)" : "流量 (L/min)",
                TitleFontSize = 14,
                AxislineColor = OxyColors.LightGray,
                MajorGridlineColor = OxyColor.FromRgb(220, 231, 243),
                MajorGridlineStyle = LineStyle.Solid,
                MinorGridlineStyle = LineStyle.None,
                FontSize = 12,
                MajorStep = 5
            };

            _plotModel.Axes.Add(_xAxis);
            _plotModel.Axes.Add(_yAxis);

            PlotView.Model = _plotModel;
        }


        #endregion

        #region 事件与定时器初始化
        private void InitializeEvents()
        {
            _dataTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(500) };
            _dataTimer.Tick += async (s, e) => await UpdateData();

            StartBtn.Click += (s, e) =>
            {
                _dataTimer.Start();
                _ = UpdateData();
                StartBtn.IsEnabled = false;
                StopBtn.IsEnabled = true;

                StatusText.Text = _lang == "en-US" ? "Status: Monitoring" : "状态：正在监测";
                StatusText.Foreground = new SolidColorBrush(Color.FromRgb(76, 175, 80));

                _exhaleSeries.MarkerType = MarkerType.Circle;
                _inhaleSeries.MarkerType = MarkerType.Circle;
            };

            StopBtn.Click += (s, e) =>
            {
                _dataTimer.Stop();
                StartBtn.IsEnabled = true;
                StopBtn.IsEnabled = false;

                StatusText.Text = _lang == "en-US" ? "Status: Stopped" : "状态：已停止";
                StatusText.Foreground = new SolidColorBrush(Color.FromRgb(156, 39, 176));
            };

            ClearBtn.Click += (s, e) =>
            {
                lock (_lockObj)
                {
                    _exhaleData.Clear();
                    _inhaleData.Clear();
                    _exhaleSeries.Points.Clear();
                    _inhaleSeries.Points.Clear();
                    _timeCounter = 0;
                    AdjustYAxisRange();
                    AdjustXAxisRange();
                    _plotModel.InvalidatePlot(true);
                }
            };
        }
        #endregion

        #region 数据更新与处理（核心：限制20个数据点）
        private async Task UpdateData()
        {
            if (_isResizing) return;

            if (!IsModbusConnected())
            {
                StatusText.Text = "状态：Modbus已断开";
                StatusText.Foreground = new SolidColorBrush(Color.FromRgb(239, 83, 80));
                return;
            }

            try
            {
                var (exhaleValue, inhaleValue) = await Task.Run(() => ReadModbusData(),
                    CancellationToken.None);

                lock (_lockObj)
                {
                    // 添加新数据点
                    var exhalePoint = new DataPoint(_timeCounter, exhaleValue);
                    var inhalePoint = new DataPoint(_timeCounter, inhaleValue);
                    _exhaleData.Add(exhalePoint);
                    _inhaleData.Add(inhalePoint);

                    // 关键：只保留最新的30个数据点
                    if (_exhaleData.Count > MAX_DATA_POINTS)
                    {
                        // 移除最旧的数据点（超出20个的部分）
                        int removeCount = _exhaleData.Count - MAX_DATA_POINTS;
                        _exhaleData.RemoveRange(0, removeCount);
                        _inhaleData.RemoveRange(0, removeCount);
                    }

                    _timeCounter += 0.5;

                    // 更新折线数据
                    _exhaleSeries.Points.Clear();
                    _inhaleSeries.Points.Clear();
                    _exhaleData.ForEach(p => _exhaleSeries.Points.Add(p));
                    _inhaleData.ForEach(p => _inhaleSeries.Points.Add(p));

                    // 调整坐标轴范围（基于当前20个数据）
                    AdjustYAxisRange();
                    AdjustXAxisRange();
                }

                _plotModel.InvalidatePlot(false);
            }
            catch (Exception ex)
            {
                StatusText.Text = $"状态：数据错误 - {ex.Message}";
                StatusText.Foreground = new SolidColorBrush(Color.FromRgb(239, 83, 80));
            }
        }

        private (float exhale, float inhale) ReadModbusData()
        {
            try
            {
                ushort[] exhalationData = _modbusMaster?.ReadHoldingRegisters(0x01, _OutBreathAddress, 2);
                ushort[] inhalationData = _modbusMaster?.ReadHoldingRegisters(0x01, _InBreathAddress, 2);

                float exhaleValue = c.UshortToFloat(exhalationData[1], exhalationData[0]);
                float inhaleValue = c.UshortToFloat(inhalationData[1], inhalationData[0]);

                return ((float)Math.Round(exhaleValue, 4), (float)Math.Round(inhaleValue, 4));
            }
            catch (Exception ex)
            {
                throw new Exception($"Modbus读取错误：{ex.Message}");
            }
        }

        private void AdjustYAxisRange()
        {
            var allYValues = new List<double>();
            allYValues.AddRange(_exhaleData.Select(p => p.Y));
            allYValues.AddRange(_inhaleData.Select(p => p.Y));

            if (!allYValues.Any())
            {
                // 无数据时默认范围（预留一定空间，避免后续数据突然增大时轴范围不足）
                _yAxis.Minimum = 0;
                _yAxis.Maximum = 10; // 初始值设大一些，应对可能的大数值
                return;
            }

            double currentMin = allYValues.Min();
            double currentMax = allYValues.Max();

            // 计算当前数据的波动范围
            double dataRange = currentMax - currentMin;

            // 1. 底部留固定余量（避免数据贴底）
            double bottomPadding = Math.Max(0.5, dataRange * 0.1); // 取两者较大值，确保至少0.5
            double newMin = currentMin - bottomPadding;
            // 若数据全为正数，Y轴从0开始更合理（可选，根据业务场景）
            if (newMin < 0 && currentMin >= 0)
                newMin = 0;

            // 2. 顶部留动态余量（随数据增大自动扩展）
            double topPadding = Math.Max(1, dataRange * 0.2); // 顶部余量稍大，应对突发大值
            double newMax = currentMax + topPadding;

            // 3. 确保Y轴范围不会“收缩”（避免数据忽大忽小时轴频繁跳动）
            // 仅当新范围的上限大于当前轴上限时，才更新上限
            if (newMax > _yAxis.Maximum)
            {
                _yAxis.Maximum = newMax;
            }
            // 下限可根据当前数据动态收缩（但不小于0，若数据全为正）
            _yAxis.Minimum = newMin;

            // 强制设置轴的“弹性”，允许数据超出当前范围时自动扩展（OxyPlot特性）
            _yAxis.IsZoomEnabled = false; // 禁止用户手动缩放（避免干扰自动范围）
        }

        private void AdjustXAxisRange()
        {
            if (_exhaleData.Count == 0 && _inhaleData.Count == 0)
            {
                _xAxis.Maximum = 1;
                return;
            }

            // X轴范围基于最新20个数据的时间范围
            double maxX = Math.Max(
                _exhaleData.DefaultIfEmpty().Max(p => p.X),
                _inhaleData.DefaultIfEmpty().Max(p => p.X)
            );

            // 当数据满20个时，X轴范围固定为这20个数据的时间跨度
            if (_exhaleData.Count >= MAX_DATA_POINTS)
            {
                double minX = _exhaleData.Min(p => p.X);
                _xAxis.Minimum = minX;
                _xAxis.Maximum = maxX + 0.5;  // 右侧留一点余量
            }
            else
            {
                _xAxis.Minimum = 0;
                _xAxis.Maximum = maxX < 1 ? 1 : maxX * 1.1;
            }
        }

        private bool IsModbusConnected()
        {
            return _tcpClient != null && _tcpClient.Connected && _modbusMaster != null;
        }
        #endregion

        #region 窗口加载与资源释放
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                string imagePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources/sleep2.jpg");
                if (System.IO.File.Exists(imagePath))
                {
                    var bitmap = new BitmapImage();
                    bitmap.BeginInit();
                    bitmap.UriSource = new Uri(imagePath, UriKind.Absolute);
                    bitmap.DecodePixelWidth = (int)this.Width;
                    bitmap.CacheOption = BitmapCacheOption.OnLoad;
                    bitmap.EndInit();

                    Background = new ImageBrush
                    {
                        ImageSource = bitmap,
                        Stretch = Stretch.UniformToFill,
                        //CacheOption = BitmapCacheOption.OnLoad
                    };
                }
                else
                {
                    Console.WriteLine($"背景图片不存在: {imagePath}");
                }

                // 获取屏幕工作区（排除任务栏）
                var workingArea = SystemParameters.WorkArea;
                // 计算居中位置
                this.Left = workingArea.Left + (workingArea.Width - this.Width) / 2;
                this.Top = workingArea.Top + (workingArea.Height - this.Height) / 2;

            }
            catch (Exception ex)
            {
                Console.WriteLine($"加载背景失败: {ex.Message}");
                Background = Brushes.White;
            }
        }

        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            _dataTimer?.Stop();
            _tcpClient?.Close();
            _resizeTokenSource?.Dispose();
        }
        #endregion
    }
}
