using Microsoft.Win32;
using ScottPlot;
using ScottPlot.Plottables;
using ScottPlot.WPF;
using SWRIS.Dtos;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace SWRIS.Controls
{
    /// <summary>
    /// 动态折线图用户控件（基于 ScottPlot.WPF 的高性能版本）
    /// </summary>
    public partial class RecordLineChart : UserControl
    {
        private readonly Color[] _colors = new Color[] {
            new Color("#70a1d7"), new Color("#a1de93"),
            new Color("#f7f48b"), new Color("#f47c7c"),
            new Color("#c264fe"), new Color("#00fff5"),
            new Color("#f8b195"), new Color("#7a08fa") };

        private const double MAXDAMAGE = 128; // 最大损伤值
        private SignalXY[] _sensorSignals;
        private SignalXY _mergeSignal;
        private Scatter[] _makerScatters;
        private AxisLimits _axisLimit;
        public RecordLineChart()
        {
            InitializeComponent();
            InitializePlot();
        }
        private void InitializePlot()
        {
            WpfPlot.Menu?.Clear();

            WpfPlot.Menu.Add("保存图片", pt =>
            {
                OpenSaveImageDialog(pt);
            });
            WpfPlot.Menu.Add("重置视图", pt =>
            {
                WpfPlot.Plot.Axes.SetLimits(_axisLimit);
                WpfPlot.Refresh();
            });
            var plot = WpfPlot.Plot;
            plot.Clear();
            plot.DataBackground.Color = Colors.Transparent;
            plot.FigureBackground.Color = Colors.Transparent;
            plot.Grid.MajorLineColor = new Color(59, 59, 123).WithOpacity(0.6);
            plot.Grid.XAxis.TickLabelStyle.ForeColor = new Color(151, 166, 212);
            plot.Grid.YAxis.TickLabelStyle.ForeColor = new Color(151, 166, 212);
            plot.Grid.XAxis.FrameLineStyle.Color = new Color(53, 53, 112);
            plot.Grid.XAxis.FrameLineStyle.Width = 3;
            plot.Grid.YAxis.FrameLineStyle.Color = new Color(53, 53, 112);
            plot.Grid.YAxis.FrameLineStyle.Width = 3;
            plot.Grid.XAxis.MajorTickStyle.Color = new Color(53, 53, 112);
            plot.Grid.XAxis.MajorTickStyle.Width = 1;
            plot.Grid.YAxis.MajorTickStyle.Color = new Color(53, 53, 112);
            plot.Grid.YAxis.MajorTickStyle.Width = 1;
            plot.Grid.YAxis.MinorTickStyle.Color = new Color(53, 53, 112);
            plot.Grid.XAxis.MinorTickStyle.Color = new Color(53, 53, 112);
            plot.Axes.Hairline(false);
        }

        public void AddDataPoints((double[] Positions, ushort[,] Damages) dataPoints, List<DamageDto> alertDamages)
        {
            if (dataPoints.Damages == null || dataPoints.Positions == null)
            {
                return;
            }
            int sensorCount = dataPoints.Damages.GetLength(0);
            int sampleCount = dataPoints.Damages.GetLength(1);
            double startPoint = dataPoints.Positions.First();
            double endPoint = dataPoints.Positions.Last();

            _sensorSignals = new SignalXY[sensorCount];
            double[] mergeData = new double[sampleCount];

            // 先计算所有传感器的合并数据
            for (int j = 0; j < sampleCount; j++)
            {
                double sum = 0;
                for (int i = 0; i < sensorCount; i++)
                {
                    sum += dataPoints.Damages[i, j];
                }
                mergeData[j] = sum / sensorCount;  // 计算平均值
            }

            AddMaker(dataPoints.Positions, mergeData, alertDamages);

            // 然后处理每个传感器的数据
            for (int i = 0; i < sensorCount; i++)
            {
                ushort[] sensorData = new ushort[sampleCount];
                for (int j = 0; j < sampleCount; j++)
                {
                    sensorData[j] = dataPoints.Damages[i, j];
                }
                var signalPlot = WpfPlot.Plot.Add.SignalXY(dataPoints.Positions, sensorData);
                signalPlot.LineWidth = 1;
                signalPlot.Color = _colors[i];
                signalPlot.IsVisible = false;
                _sensorSignals[i] = signalPlot;
            }

            _mergeSignal = WpfPlot.Plot.Add.SignalXY(dataPoints.Positions, mergeData);
            _mergeSignal.LineWidth = 2;
            _mergeSignal.Color = new Color("#9664F3");

            //差值
            double offset = (endPoint - startPoint) * 0.1;
            _axisLimit = new AxisLimits(startPoint - offset, endPoint + offset, 0, MAXDAMAGE);
            WpfPlot.Plot.Axes.SetLimits(_axisLimit);
            WpfPlot.Refresh();
        }

        public void SignalPlotVisible(int id, bool isVisible)
        {
            if (id > _sensorSignals.Length) return;

            if (id == 0)
            {
                _mergeSignal.IsVisible = isVisible;
                foreach (var maker in _makerScatters)
                {
                    maker.IsVisible = isVisible;
                }
            }
            else
            {
                _sensorSignals[id - 1].IsVisible = isVisible;
            }
            WpfPlot.Refresh();
        }
        private void AddMaker(double[] dataPoints, double[] mergeData, List<DamageDto> alertDamages)
        {
            int markerCount = alertDamages.Count;
            _makerScatters = new Scatter[markerCount];
            for (int i = 0; i < markerCount; i++)
            {
                int index = FindNearestIndex(dataPoints, alertDamages[i].DamagePoint);
                if (index < 0 || index >= dataPoints.Length)
                    continue;
                var marker = WpfPlot.Plot.Add.Scatter(dataPoints[index], mergeData[index]);
                marker.LineWidth = 0;  // 不显示连线
                marker.MarkerSize = 10;
                marker.MarkerShape = MarkerShape.OpenCircle;
                marker.MarkerLineWidth = 2;
                switch (alertDamages[i].DamageLevel)
                {
                    case Enums.DamageLevel.Mild:
                        marker.Color = Color.FromHex("#00FF78");
                        break;
                    case Enums.DamageLevel.Light:
                        marker.Color = Color.FromHex("#FFF000");
                        break;
                    case Enums.DamageLevel.Moderate:
                        marker.Color = Color.FromHex("#FF9400");
                        break;
                    case Enums.DamageLevel.Severe:
                        marker.Color = Color.FromHex("#FF6C00");
                        break;
                    case Enums.DamageLevel.Critical:
                        marker.Color = Color.FromHex("#FF0000");
                        break;
                    case Enums.DamageLevel.ExceededLimit:
                        marker.Color = Color.FromHex("#FF008A");
                        break;
                }
                _makerScatters[i] = marker;
            }
        }
        private int FindNearestIndex(double[] positions, double target)
        {
            if (positions == null || positions.Length == 0)
                return -1;

            int index = Array.BinarySearch(positions, target);

            // 如果找到精确匹配
            if (index >= 0)
                return index;

            // 如果没找到，BinarySearch 返回下一个更大元素的补码
            int largerIndex = ~index;

            // 处理边界情况
            if (largerIndex == 0)
                return 0;

            if (largerIndex == positions.Length)
                return positions.Length - 1;

            // 比较左右两个元素哪个更接近
            double diffLeft = Math.Abs(positions[largerIndex - 1] - target);
            double diffRight = Math.Abs(positions[largerIndex] - target);

            return diffLeft < diffRight ? largerIndex - 1 : largerIndex;
        }
        public void OpenSaveImageDialog(Plot plot)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog
            {
                Filter = "PNG Files (*.png)|*.png|JPEG Files (*.jpg, *.jpeg)|*.jpg;*.jpeg|BMP Files (*.bmp)|*.bmp|WebP Files (*.webp)|*.webp|SVG Files (*.svg)|*.svg|All files (*.*)|*.*"
            };
            bool? flag = saveFileDialog.ShowDialog();
            if (flag.HasValue && flag == true && !string.IsNullOrEmpty(saveFileDialog.FileName))
            {
                ImageFormat format;
                try
                {
                    format = ImageFormats.FromFilename(saveFileDialog.FileName);
                }
                catch (ArgumentException)
                {
                    MessageBox.Show("Unsupported image file format", "ERROR", MessageBoxButton.OK, MessageBoxImage.Hand);
                    return;
                }

                try
                {
                    PixelSize size = plot.RenderManager.LastRender.FigureRect.Size;
                    plot.Save(saveFileDialog.FileName, (int)size.Width, (int)size.Height, format);
                }
                catch (Exception)
                {
                    MessageBox.Show("Image save failed", "ERROR", MessageBoxButton.OK, MessageBoxImage.Hand);
                }
            }
        }
        
    }
}