using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using CtrEditor.FuncionesBase;
using CtrEditor.Simulacion.Fluids.Components;
using nkast.Aether.Physics2D.Common;
using CommunityToolkit.Mvvm.ComponentModel;
using System.ComponentModel;

namespace CtrEditor.ObjetosSim
{
    /// <summary>
    /// Lógica para ucTuberiaFluido.xaml
    /// </summary>
    public partial class ucTuberiaFluido : UserControl, IDataContainer
    {
        public osBase? Datos { get; set; }
        public int zIndex_fromFrames { get; set; }
        
        public ucTuberiaFluido()
        {
            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 Highlight(bool State) { }
        
        public ZIndexEnum ZIndex_Base()
        {
            return ZIndexEnum.Estaticos;
        }
    }
    
    /// <summary>
    /// ViewModel para la tubería de fluidos
    /// </summary>
    public partial class osTuberiaFluido : osBase, IosBase
    {
        // Tubería en la simulación de fluidos
        private Tuberia _tuberia;
        
        // Referencia al sistema de fluidos
        private osSistemaFluidos _sistemaFluidos;
        
        // Propiedades visuales
        [ObservableProperty]
        [property: Description("Diámetro de la tubería en metros")]
        [property: Category("Dimensiones:")]
        private float diametro = 0.05f;
        
        partial void OnDiametroChanged(float value)
        {
            // Actualizar geometría si la tubería ya existe
            if (_tuberia != null)
            {
                // No es posible cambiar el diámetro directamente, recrear la tubería
                ReconstruirTuberia();
            }
        }
        
        [ObservableProperty]
        [property: Description("Diámetro interno para visualización del fluido")]
        [property: Category("Visual:")]
        private float diametroInterno;
        
        [ObservableProperty]
        [property: Description("Color de la tubería")]
        [property: Category("Visual:")]
        private System.Windows.Media.Color color = System.Windows.Media.Colors.Gray;
        
        [ObservableProperty]
        [property: Description("Color del fluido")]
        [property: Category("Visual:")]
        private System.Windows.Media.Color colorFluido = System.Windows.Media.Colors.CornflowerBlue;
        
        [ObservableProperty]
        [property: Description("Datos del path para dibujar la tubería")]
        [property: Category("Interno:")]
        private string pathData;
        
        [ObservableProperty]
        [property: Description("Densidad del fluido (0-1)")]
        [property: Category("Simulación:")]
        private double densidadFluido = 0.7;
        
        // Lista de puntos que forman la tubería
        private List<Vector2> _puntos = new List<Vector2>();
        
        // Nombre de la clase para identificación
        public static string NombreClase()
        {
            return "TuberiaFluido";
        }
        
        private string nombre = NombreClase();
        public override string Nombre
        {
            get => nombre;
            set => SetProperty(ref nombre, value);
        }
        
        /// <summary>
        /// Agrega un punto a la tubería
        /// </summary>
        public void AgregarPunto(float x, float y)
        {
            _puntos.Add(new Vector2(x, y));
            ActualizarPathData();
            
            // Si la tubería ya está creada, agregar el punto a la simulación
            if (_tuberia != null)
            {
                _tuberia.AgregarPunto(new Vector2(x, y));
            }
        }
        
        /// <summary>
        /// Actualiza la representación visual de la tubería
        /// </summary>
        private void ActualizarPathData()
        {
            if (_puntos.Count < 2) return;
            
            var converter = new MeterToPixelConverter();
            StringBuilder sb = new StringBuilder();
            
            // Iniciar el path
            sb.Append($"M {converter.Convert(_puntos[0].X, null, null, null)} {converter.Convert(_puntos[0].Y, null, null, null)} ");
            
            // Añadir los demás puntos
            for (int i = 1; i < _puntos.Count; i++)
            {
                sb.Append($"L {converter.Convert(_puntos[i].X, null, null, null)} {converter.Convert(_puntos[i].Y, null, null, null)} ");
            }
            
            PathData = sb.ToString();
        }
        
        /// <summary>
        /// Reconstruye la tubería en la simulación
        /// </summary>
        private void ReconstruirTuberia()
        {
            if (_sistemaFluidos != null)
            {
                // Eliminar la tubería existente
                if (_tuberia != null)
                {
                    _sistemaFluidos.EliminarComponente(_tuberia);
                }
                
                // Crear nueva tubería
                _tuberia = _sistemaFluidos.CrearTuberia(Diametro);
                
                // Agregar todos los puntos existentes
                foreach (var punto in _puntos)
                {
                    _tuberia.AgregarPunto(punto);
                }
            }
        }
        
        /// <summary>
        /// Constructor
        /// </summary>
        public osTuberiaFluido()
        {
            DiametroInterno = Diametro * 0.8f;
        }
        
        public override void OnMove(float LeftPixels, float TopPixels)
        {
            // Mover todos los puntos de la tubería
            if (_puntos.Count > 0)
            {
                Vector2 delta = new Vector2(Left - CanvasGetLeftinMeter(), Top - CanvasGetTopinMeter());
                
                for (int i = 0; i < _puntos.Count; i++)
                {
                    _puntos[i] += delta;
                }
                
                ActualizarPathData();
                ReconstruirTuberia();
            }
        }
        
        public override void ucLoaded()
        {
            base.ucLoaded();
            
            // Buscar el sistema de fluidos en la simulación
            if (_mainViewModel?.ObjetosSimulables != null)
            {
                foreach (var obj in _mainViewModel.ObjetosSimulables)
                {
                    if (obj is osSistemaFluidos sistemaFluidos)
                    {
                        _sistemaFluidos = sistemaFluidos;
                        break;
                    }
                }
            }
            
            // Si no hay puntos, agregar dos puntos iniciales
            if (_puntos.Count == 0)
            {
                _puntos.Add(new Vector2(Left, Top));
                _puntos.Add(new Vector2(Left + Ancho, Top));
                ActualizarPathData();
            }
            
            // Crear la tubería en la simulación
            ReconstruirTuberia();
        }
        
        public override void ucUnLoaded()
        {
            // Eliminar la tubería de la simulación
            if (_sistemaFluidos != null && _tuberia != null)
            {
                _sistemaFluidos.EliminarComponente(_tuberia);
                _tuberia = null;
            }
        }
        
        public override void UpdateControl(int elapsedMilliseconds)
        {
            // Actualizar la densidad del fluido basada en la simulación
            if (_sistemaFluidos != null && _sistemaFluidos._simFluidos != null && _puntos.Count > 0)
            {
                // Calcular el centro aproximado de la tubería
                Vector2 centro = Vector2.Zero;
                foreach (var punto in _puntos)
                {
                    centro += punto;
                }
                centro /= _puntos.Count;
                
                // Obtener densidad en esa posición
                DensidadFluido = _sistemaFluidos._simFluidos.ObtenerDensidadEnPosicion(centro);
            }
        }
    }
}
