using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using CtrEditor.FuncionesBase;
using CtrEditor.Simulacion.Fluids;
using CtrEditor.Simulacion.Fluids.Components;
using nkast.Aether.Physics2D.Common;
using Color = System.Windows.Media.Color;
using Siemens.Simatic.Simulation.Runtime;
using LibS7Adv;

namespace CtrEditor.ObjetosSim
{
    /// <summary>
    /// ViewModel para el sistema de fluidos
    /// </summary>
    public partial class osSistemaFluidos : osBase, IosBase
    {
        // Referencia a la simulación de fluidos
        public SimulacionFluidos _simFluidos;
        
        // Tamaño del área de simulación
        [ObservableProperty]
        [property: Description("Ancho del área de simulación en metros")]
        [property: Category("Simulación:")]
        private float anchoSimulacion = 10.0f;
        
        [ObservableProperty]
        [property: Description("Alto del área de simulación en metros")]
        [property: Category("Simulación:")]
        private float altoSimulacion = 10.0f;
        
        // Propiedades del fluido
        [ObservableProperty]
        [property: Description("Tamaño visual de las partículas")]
        [property: Category("Visual:")]
        private float tamañoParticula = 0.01f;
        
        [ObservableProperty]
        [property: Description("Color del fluido")]
        [property: Category("Visual:")]
        private Color colorFluido = Colors.CornflowerBlue;
        
        [ObservableProperty]
        [property: Description("Opacidad de las partículas")]
        [property: Category("Visual:")]
        private double opacidadParticulas = 0.7;
        
        // Propiedades de gravedad
        [ObservableProperty]
        [property: Description("Gravedad en X (m/s²)")]
        [property: Category("Física:")]
        private float gravedadX = 0.0f;
        
        [ObservableProperty]
        [property: Description("Gravedad en Y (m/s²)")]
        [property: Category("Física:")]
        private float gravedadY = 9.8f;
        
        partial void OnGravedadXChanged(float value)
        {
            ActualizarGravedad();
        }
        
        partial void OnGravedadYChanged(float value)
        {
            ActualizarGravedad();
        }
        
        // Estadísticas de la simulación
        [ObservableProperty]
        [property: Description("Número de partículas")]
        [property: Category("Estadísticas:")]
        private int numeroParticulas;
        
        [ObservableProperty]
        [property: Description("Rendimiento en FPS")]
        [property: Category("Estadísticas:")]
        private double fps;

        // Referencia a componentes (solo para la función Add)
        private List<IContenedorFluido> _contenedores = new List<IContenedorFluido>();
        
        // Nombre de la clase para identificación
        public static string NombreClase()
        {
            return "SistemaFluidos";
        }
        
        private string nombre = NombreClase();
        public override string Nombre
        {
            get => nombre;
            set => SetProperty(ref nombre, value);
        }
        
        // Métodos para interactuar con la simulación
        
        /// <summary>
        /// Agrega partículas en un punto específico
        /// </summary>
        public void AgregarParticula(Vector2 posicion)
        {
            _simFluidos?.AgregarParticula(posicion);
        }
        
        /// <summary>
        /// Agrega múltiples partículas en un área
        /// </summary>
        public void AgregarParticulasEnArea(Vector2 centro, float ancho, float alto, int cantidad)
        {
            _simFluidos?.AgregarParticulasEnArea(centro, ancho, alto, cantidad);
        }
        
        /// <summary>
        /// Crea un nuevo tanque y lo agrega a la simulación
        /// </summary>
        public Tanque CrearTanque(Vector2 posicion, float ancho, float alto)
        {
            if (_simFluidos == null) return null;
            
            Tanque tanque = new Tanque(posicion, ancho, alto, (int)(AnchoSimulacion * 100));
            _simFluidos.AgregarContenedor(tanque);
            _contenedores.Add(tanque);
            return tanque;
        }
        
        /// <summary>
        /// Crea una nueva tubería
        /// </summary>
        public Tuberia CrearTuberia(float diametro)
        {
            if (_simFluidos == null) return null;
            
            Tuberia tuberia = new Tuberia(diametro, (int)(AnchoSimulacion * 100));
            _simFluidos.AgregarContenedor(tuberia);
            _contenedores.Add(tuberia);
            return tuberia;
        }
        
        /// <summary>
        /// Crea una nueva válvula
        /// </summary>
        public Valvula CrearValvula(Vector2 posicion, float diametro, float apertura = 1.0f)
        {
            if (_simFluidos == null) return null;
            
            Valvula valvula = new Valvula(posicion, diametro, apertura, (int)(AnchoSimulacion * 100));
            _simFluidos.AgregarContenedor(valvula);
            _contenedores.Add(valvula);
            return valvula;
        }
        
        /// <summary>
        /// Elimina un componente de la simulación
        /// </summary>
        public void EliminarComponente(IContenedorFluido componente)
        {
            if (_simFluidos == null || componente == null) return;
            
            _simFluidos.RemoverContenedor(componente);
            _contenedores.Remove(componente);
        }
        
        /// <summary>
        /// Limpia todas las partículas de la simulación
        /// </summary>
        public void LimpiarParticulas()
        {
            _simFluidos?.LimpiarParticulas();
        }
        
        /// <summary>
        /// Actualiza el vector de gravedad según las propiedades
        /// </summary>
        private void ActualizarGravedad()
        {
            if (_simFluidos != null)
            {
                _simFluidos.AjustarGravedad(new Vector2(GravedadX, GravedadY));
            }
        }
        
        /// <summary>
        /// Constructor de la clase
        /// </summary>
        public osSistemaFluidos()
        {
            // Inicializar propiedades básicas
            Ancho = 1.0f;
            Alto = 1.0f;
        }
        
        // Métodos sobrescritos de osBase
        
        public override void UpdateGeometryStart()
        {
            // Crear la simulación de fluidos si es necesario
            if (_simFluidos == null)
            {
                _simFluidos = new SimulacionFluidos(
                    AnchoSimulacion, 
                    AltoSimulacion, 
                    10000, // Máximo de partículas
                    new Vector2(GravedadX, GravedadY)
                );
            }
        }
        
        public override void UpdateGeometryStep()
        {
            // No es necesario actualizar en cada paso
        }
        
        public override void UpdateControl(int elapsedMilliseconds)
        {
            // Actualizar estadísticas
            if (_simFluidos != null)
            {
                NumeroParticulas = _simFluidos.ParticlesCount;
            }
        }
        
        /// <summary>
        /// Llamado cuando se inicia la simulación de fluidos
        /// </summary>
        public void OnFluidSimulationStart()
        {
            // Crear la simulación de fluidos si es necesario
            UpdateGeometryStart();
        }
        
        /// <summary>
        /// Llamado cuando se detiene la simulación de fluidos
        /// </summary>
        public void OnFluidSimulationStop()
        {
            // Detener recursos si es necesario
            SimulationStop();
        }
        
        /// <summary>
        /// Actualiza la simulación de fluidos
        /// </summary>
        public void UpdateFluidSimulation(float deltaTime)
        {
            // Actualizar la simulación con el delta time
            if (_simFluidos != null)
            {
                _simFluidos.Actualizar(deltaTime);
                
                // Actualizar el control visual
                UpdateControl((int)(deltaTime * 1000));
            }
        }
        
        public override void SimulationStop()
        {
            // Limpiar recursos si es necesario cuando se detiene la simulación
        }
        
        public override void ucLoaded()
        {
            base.ucLoaded();
            
            // Inicializar la simulación de fluidos si es necesario
            UpdateGeometryStart();
        }
        
        public override void ucUnLoaded()
        {
            // Limpiar recursos
            _simFluidos = null;
            _contenedores.Clear();
        }
        
        // Implementación para las conexiones con PLC
        
        [ObservableProperty]
        [property: Description("Tag de lectura/escritura del nivel del Tanque 1")]
        [property: Category("PLC:")]
        private string tagNivelTanque1;
        
        [ObservableProperty]
        [property: Description("Tag de lectura/escritura de la apertura de la Válvula 1")]
        [property: Category("PLC:")]
        private string tagAperturaValvula1;
        
        // Referencia a componentes típicos para integración con PLC
        private Tanque _tanque1;
        private Valvula _valvula1;
        
        public override void UpdatePLC(PLCViewModel plc, int elapsedMilliseconds)
        {
            // Ejemplo de integración con PLC para la válvula
            if (_valvula1 != null && !string.IsNullOrEmpty(TagAperturaValvula1))
            {
                float aperturaValvula = LeerWordTagScaled(TagAperturaValvula1) / 100.0f;
                _valvula1.Apertura = Math.Clamp(aperturaValvula, 0, 1);
            }
            
            // Ejemplo de escritura del nivel del tanque al PLC
            if (_tanque1 != null && !string.IsNullOrEmpty(TagNivelTanque1))
            {
                float nivelTanque = 0; // Implementar cálculo real del nivel
                EscribirWordTagScaled(TagNivelTanque1, nivelTanque * 100, 0, 100, 0, 27648);
            }
        }
    }
}
