
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using System.Windows.Shapes;
using LibS7Adv;
using System.Runtime.Intrinsics;
using CtrEditor.FuncionesBase;
using System.ComponentModel;

namespace CtrEditor.ObjetosSim
{
    /// <summary>
    /// Interaction logic for ucTrace3.xaml
    /// </summary>
    public partial class osTrace3 : osBase, IosBase
    {
        public static string NombreCategoria() => "Traces";
        private List<float> _series1 = new List<float>();
        private List<float> _series2 = new List<float>();
        private List<float> _series3 = new List<float>();

        // Otros datos y métodos relevantes para la simulación

        public static string NombreClase()
        {
            return "Trazador de 3 Señales";
        }
        private string nombre = NombreClase();

        [property: Category("Identificación")]
        [property: Description("Nombre identificativo del objeto")]
        [property: Name("Nombre")]
        public override string Nombre
        {
            get => nombre;
            set => SetProperty(ref nombre, value);
        }

        [ObservableProperty]
        [property: Category("Apariencia")]
        [property: Description("Color de la serie 1")]
        [property: Name("Color Serie 1")]
        private Brush color_Serie_1;

        [ObservableProperty]
        [property: Category("Apariencia")]
        [property: Description("Color de la serie 2")]
        [property: Name("Color Serie 2")]
        private Brush color_Serie_2;

        [ObservableProperty]
        [property: Category("Apariencia")]
        [property: Description("Color de la serie 3")]
        [property: Name("Color Serie 3")]
        private Brush color_Serie_3;

        [ObservableProperty]
        [property: Category("Configuración")]
        [property: Description("Alto del trazador")]
        [property: Name("Alto")]
        float alto;

        [ObservableProperty]
        [property: Category("Configuración")]
        [property: Description("Ancho del trazador")]
        [property: Name("Ancho")]
        float ancho;

        [ObservableProperty]
        [property: Category("Configuración")]
        [property: Description("Serie 1 es tipo booleana")]
        [property: Name("Serie 1 Bool")]
        bool serie1_Tipo_Bool;

        [ObservableProperty]
        [property: Category("Enlace PLC")]
        [property: Description("Tag PLC para serie 1")]
        [property: Name("Tag Serie 1")]
        string tag_Serie1;

        [ObservableProperty]
        [property: Category("Configuración")]
        [property: Description("Serie 2 es tipo booleana")]
        [property: Name("Serie 2 Bool")]
        bool serie2_Tipo_Bool;

        [ObservableProperty]
        [property: Category("Enlace PLC")]
        [property: Description("Tag PLC para serie 2")]
        [property: Name("Tag Serie 2")]
        string tag_Serie2;

        [ObservableProperty]
        [property: Category("Configuración")]
        [property: Description("Serie 3 es tipo booleana")]
        [property: Name("Serie 3 Bool")]
        bool serie3_Tipo_Bool;

        [ObservableProperty]
        [property: Category("Enlace PLC")]
        [property: Description("Tag PLC para serie 3")]
        [property: Name("Tag Serie 3")]
        string tag_Serie3;

        [ObservableProperty]
        [property: Category("Identificación")]
        [property: Description("Título del trazador")]
        [property: Name("Título")]
        string titulo;

        [ObservableProperty]
        string descripcion_Serie_1;
        [ObservableProperty]
        string descripcion_Serie_2;
        [ObservableProperty]
        string descripcion_Serie_3;

        [ObservableProperty]
        float min_Serie_1;
        [ObservableProperty]
        float max_Serie_1;
        [ObservableProperty]
        float min_Serie_2;
        [ObservableProperty]
        float max_Serie_2;
        [ObservableProperty]
        float min_Serie_3;
        [ObservableProperty]
        float max_Serie_3;

        [ObservableProperty]
        float y_offset_1;
        [ObservableProperty]
        float y_offset_2;
        [ObservableProperty]
        float y_offset_3;


        [ObservableProperty]
        [property: Category("Configuración")]
        [property: Description("Máximo número de elementos a mostrar")]
        [property: Name("Max Elementos")]
        float max_Cantidad_Elementos;

        public osTrace3()
        {
            Alto = 3;
            Ancho = 5;
            Titulo = "Datos";
            Max_Cantidad_Elementos = 10;
            Color_Serie_1 = Brushes.Black;
            Color_Serie_2 = Brushes.Red;
            Color_Serie_3 = Brushes.Blue;
            Max_Serie_1 = 2;
            Max_Serie_2 = 2;
            Max_Serie_3 = 2;
            Serie1_Tipo_Bool = true;
            Serie2_Tipo_Bool = true;
            Serie3_Tipo_Bool = true;

        }

        public override void UpdatePLCPrimerCiclo()
        {
            // Escribimos el valor actual al iniciar la conexion
        }
        public override void UpdatePLC(PLCViewModel plc, int elapsedMilliseconds)
        {
            float v1, v2, v3;

            base.UpdatePLC(plc, elapsedMilliseconds);

            if (Serie1_Tipo_Bool)
                v1 = LeerBitTag(Tag_Serie1) ? 0 : 1;
            else
                v1 = LeerWordTag(Tag_Serie1);

            if (Serie2_Tipo_Bool)
                v2 = LeerBitTag(Tag_Serie2) ? 0 : 1;
            else
                v2 = LeerWordTag(Tag_Serie2);

            if (Serie3_Tipo_Bool)
                v3 = LeerBitTag(Tag_Serie3) ? 0 : 1;
            else
                v3 = LeerWordTag(Tag_Serie3);

            AddData(v1, v2, v3);
        }
        public override void ucLoaded()
        {
            // El UserControl ya se ha cargado y podemos obtener las coordenadas para 
            // crear el objeto de simulacion
            base.ucLoaded();

        }

        public void AddData(float series1Value, float series2Value, float series3Value)
        {
            if (_series1.Count >= Max_Cantidad_Elementos)
            {
                _series1.RemoveAt(0);
                _series2.RemoveAt(0);
                _series3.RemoveAt(0);
            }

            _series1.Add(series1Value);
            _series2.Add(series2Value);
            _series3.Add(series3Value);

            DrawChart();
        }

        private void DrawChart()
        {
            if (VisualRepresentation != null)
                if (VisualRepresentation is ucTrace3 uc)
                {
                    uc.ChartCanvas.Children.Clear();

                    DrawSeries(uc.ChartCanvas, _series1, Brushes.Red, Min_Serie_1, Max_Serie_1, Y_offset_1);
                    DrawSeries(uc.ChartCanvas, _series2, Brushes.Green, Min_Serie_2, Max_Serie_2, Y_offset_2);
                    DrawSeries(uc.ChartCanvas, _series3, Brushes.Blue, Min_Serie_3, Max_Serie_3, Y_offset_3);
                }

        }


        private void DrawSeries(Canvas ChartCanvas, List<float> series, Brush color, float minY, float maxY, float yoffset)
        {
            if (series.Count < 2) return;

            foreach (var value in series)
            {
                if (value < minY) minY = value;
                if (value > maxY) maxY = value;
            }
            if (minY == maxY) return;

            float canvasHeight = (float)ChartCanvas.ActualHeight;
            float canvasWidth = (float)ChartCanvas.ActualWidth;
            float scaleX = canvasWidth / Max_Cantidad_Elementos;
            float scaleY = canvasHeight / (maxY - minY + yoffset);

            int startIndex = 0;
            float lastX = 0;
            float lastY = canvasHeight - (series[startIndex] - minY + yoffset) * scaleY;

            while (startIndex < series.Count - 1)
            {
                // Buscar el próximo cambio en la serie
                int endIndex = startIndex + 1;
                while (endIndex < series.Count && series[endIndex] == series[startIndex])
                {
                    endIndex++;
                }

                // Dibujar la línea horizontal desde startIndex hasta endIndex - 1
                float x1 = lastX;
                float y1 = lastY;
                float x2 = (endIndex - 1) * scaleX;
                float y2 = y1;

                var horizontalLine = new Line
                {
                    Stroke = color,
                    StrokeThickness = 0.4,
                    X1 = x1,
                    Y1 = y1,
                    X2 = x2,
                    Y2 = y2
                };

                ChartCanvas.Children.Add(horizontalLine);

                // Dibujar la línea vertical en endIndex - 1 si no es el último punto
                if (endIndex < series.Count)
                {
                    float xVertical = x2;
                    float yVerticalStart = y2;
                    float yVerticalEnd = canvasHeight - (series[endIndex] - minY + yoffset) * scaleY;

                    var verticalLine = new Line
                    {
                        Stroke = color,
                        StrokeThickness = 0.4,
                        X1 = xVertical,
                        Y1 = yVerticalStart,
                        X2 = xVertical,
                        Y2 = yVerticalEnd
                    };

                    ChartCanvas.Children.Add(verticalLine);

                    // Actualizar la última posición dibujada
                    lastX = xVertical;
                    lastY = yVerticalEnd;
                }
                else
                {
                    // Actualizar la última posición dibujada para la última línea horizontal
                    lastX = x2;
                    lastY = y2;
                }

                // Actualizar startIndex
                startIndex = endIndex;
            }
        }


    }

    public partial class ucTrace3 : UserControl, IDataContainer
    {
        public osBase? Datos { get; set; }
        public int zIndex_fromFrames { get; set; }

        public ucTrace3()
        {
            InitializeComponent();
            this.Loaded += OnLoaded;
            this.Unloaded += OnUnloaded;
        }
        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            Datos?.ucLoaded();
        }
        private void OnUnloaded(object sender, RoutedEventArgs e)
        {
            Datos?.ucUnLoaded();
        }
        public void Resize(float width, float height)
        {
            if (Datos is osTrace3 datos)
            {
                datos.Ancho += PixelToMeter.Instance.calc.PixelsToMeters(width);
                datos.Alto += PixelToMeter.Instance.calc.PixelsToMeters(height);
            }
        }
        public void Move(float LeftPixels, float TopPixels)
        {
            if (Datos != null)
            {
                Datos.Left = PixelToMeter.Instance.calc.PixelsToMeters(LeftPixels);
                Datos.Top = PixelToMeter.Instance.calc.PixelsToMeters(TopPixels);
            }
        }
        public float Angle() { return 0; }
        public void Rotate(float Angle) { }
        public void Highlight(bool State) { }
        public ZIndexEnum ZIndex_Base()
        {
            return ZIndexEnum.Trace;
        }

    }
}
