using System;
using System.Diagnostics;
using System.Windows.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CtrEditor.Simulacion.Fluids;
using nkast.Aether.Physics2D.Common;
using CtrEditor.ObjetosSim;

namespace CtrEditor
{
    /// <summary>
    /// ViewModel para controlar la simulación de fluidos de forma independiente
    /// </summary>
    public partial class SimulationFluidsViewModel : ObservableObject
    {
        private MainViewModel _mainViewModel;
        private readonly DispatcherTimer _timerSimulacionFluidos;
        private Stopwatch _stopwatch;
        private double _lastUpdateTime;
        
        // Propiedades observables
        [ObservableProperty]
        private bool isFluidSimulationRunning;
        
        [ObservableProperty]
        private float fps;
        
        [ObservableProperty]
        private int particulasCount;
        
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="mainViewModel">Referencia al ViewModel principal</param>
        public SimulationFluidsViewModel(MainViewModel mainViewModel)
        {
            _mainViewModel = mainViewModel;
            
            // Inicializar timer para simulación de fluidos
            _timerSimulacionFluidos = new DispatcherTimer();
            _timerSimulacionFluidos.Interval = TimeSpan.FromMilliseconds(16); // ~60fps
            _timerSimulacionFluidos.Tick += OnTickSimulacionFluidos;
            
            _stopwatch = new Stopwatch();
            _stopwatch.Start();
        }
        
        /// <summary>
        /// Inicia la simulación de fluidos
        /// </summary>
        public void StartFluidSimulation()
        {
            if (IsFluidSimulationRunning)
                return;
                
            IsFluidSimulationRunning = true;
            
            // Notificar a todos los objetos que usan fluidos que inicie su simulación
            foreach (var objetoSimulable in _mainViewModel.ObjetosSimulables)
            {
                if (objetoSimulable is osSistemaFluidos sistemaFluidos)
                {
                    sistemaFluidos.UpdateGeometryStart();
                }
            }
            
            _lastUpdateTime = _stopwatch.Elapsed.TotalMilliseconds;
            _timerSimulacionFluidos.Start();
        }
        
        /// <summary>
        /// Detiene la simulación de fluidos
        /// </summary>
        public void StopFluidSimulation()
        {
            if (!IsFluidSimulationRunning)
                return;
                
            IsFluidSimulationRunning = false;
            _timerSimulacionFluidos.Stop();
            
            // Notificar a todos los objetos que usan fluidos que detenga su simulación
            foreach (var objetoSimulable in _mainViewModel.ObjetosSimulables)
            {
                if (objetoSimulable is osSistemaFluidos sistemaFluidos)
                {
                    sistemaFluidos.SimulationStop();
                }
            }
        }
        
        /// <summary>
        /// Evento que se dispara cada tick de la simulación de fluidos
        /// </summary>
        private void OnTickSimulacionFluidos(object sender, EventArgs e)
        {
            // Calcular delta time
            double currentTime = _stopwatch.Elapsed.TotalMilliseconds;
            float deltaTime = (float)(currentTime - _lastUpdateTime) / 1000.0f; // convertir a segundos
            _lastUpdateTime = currentTime;
            
            int totalParticleCount = 0;
            
            // Actualizar todos los sistemas de fluidos
            foreach (var objetoSimulable in _mainViewModel.ObjetosSimulables)
            {
                if (objetoSimulable is osSistemaFluidos sistemaFluidos && sistemaFluidos.Show_On_This_Page)
                {
                    // Actualizar la simulación con el deltaTime calculado
                    if (sistemaFluidos._simFluidos != null)
                    {
                        sistemaFluidos._simFluidos.Actualizar(deltaTime);
                        totalParticleCount += sistemaFluidos._simFluidos.ParticlesCount;
                    }
                    
                    // Actualizar controles visuales
                    sistemaFluidos.UpdateControl((int)(deltaTime * 1000));
                }
            }
            
            // Actualizar estadísticas
            Fps = 1.0f / Math.Max(deltaTime, 0.001f);
            ParticulasCount = totalParticleCount;
        }
    }
}
