using CtrEditor.ObjetosSim;
using LibS7Adv;
using Newtonsoft.Json;
using System.Collections.ObjectModel;
using System.Windows;
using CtrEditor.Simulacion;
using System.IO;

namespace CtrEditor.Serialization
{
    public class StateSerializer
    {
        private readonly DatosDeTrabajo _datosDeTrabajo;
        private readonly MainViewModel _mainViewModel;
        private readonly SimulationManagerFP _simulationManager;

        public StateSerializer(MainViewModel mainViewModel, DatosDeTrabajo datosDeTrabajo, SimulationManagerFP simulationManager)
        {
            _mainViewModel = mainViewModel;
            _datosDeTrabajo = datosDeTrabajo;
            _simulationManager = simulationManager;
        }

        public void SaveState(string selectedImage)
        {
            if (selectedImage != null)
            {
                _mainViewModel.StopSimulation();
                _mainViewModel.DisconnectPLC();

                var objetosSimulables = new ObservableCollection<osBase>();
                var objetosSimulablesAllPages = new ObservableCollection<osBase>();

                foreach (var obj in _mainViewModel.ObjetosSimulables)
                {
                    obj.SalvarDatosNoSerializables();
                    if (!obj.Enable_On_All_Pages)
                        objetosSimulables.Add(obj);
                    else
                        objetosSimulablesAllPages.Add(obj);
                }

                // Save current page objects
                var dataToSerialize = new SimulationData
                {
                    ObjetosSimulables = objetosSimulables,
                    UnitConverter = PixelToMeter.Instance.calc,
                    PLC_ConnectionData = _mainViewModel.PLCViewModel
                };

                var path = _datosDeTrabajo.ObtenerPathImagenConExtension(selectedImage, ".json");
                if (path != null)
                    SerializeAndSave(dataToSerialize, path);

                // Save all pages objects
                path = _datosDeTrabajo.ObtenerPathAllPages(".json");
                if (path != null)
                    SerializeAndSave(objetosSimulablesAllPages, path);

                // Restore original properties
                foreach (var obj in _mainViewModel.ObjetosSimulables)
                    obj.RestaurarDatosNoSerializables();
            }
        }

        public void LoadState(string selectedImage)
        {
            try
            {
                _mainViewModel.StopSimulation();
                _mainViewModel.DisconnectPLC();
                _mainViewModel.ObjetosSimulables.Clear();
                _simulationManager.Clear();

                if (selectedImage != null)
                {
                    var settings = GetJsonSerializerSettings();
                    LoadCurrentPageState(selectedImage, settings);
                    LoadAllPagesState(settings);

                    // Create UserControls for all loaded objects
                    foreach (var objetoSimulable in _mainViewModel.ObjetosSimulables)
                    {
                        if (objetoSimulable != null)
                        {
                            objetoSimulable.CheckData();
                            _mainViewModel.CrearUserControlDesdeObjetoSimulable(objetoSimulable);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error loading state: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void LoadCurrentPageState(string selectedImage, JsonSerializerSettings settings)
        {
            string jsonPath = _datosDeTrabajo.ObtenerPathImagenConExtension(selectedImage, ".json");
            if (File.Exists(jsonPath))
            {
                string jsonString = File.ReadAllText(jsonPath);
                var simulationData = JsonConvert.DeserializeObject<SimulationData>(jsonString, settings);
                if (simulationData != null)
                {
                    if (simulationData.ObjetosSimulables is not null)
                        _mainViewModel.ObjetosSimulables = simulationData.ObjetosSimulables;

                    if (simulationData.PLC_ConnectionData is not null)
                        _mainViewModel.PLCViewModel = simulationData.PLC_ConnectionData;
                    else
                        _mainViewModel.PLCViewModel = new PLCViewModel();

                    PixelToMeter.Instance.calc = simulationData.UnitConverter;
                }
            }
        }

        private void LoadAllPagesState(JsonSerializerSettings settings)
        {
            string jsonPath = _datosDeTrabajo.ObtenerPathAllPages(".json");
            if (File.Exists(jsonPath))
            {
                string jsonString = File.ReadAllText(jsonPath);
                var objetosSimulablesAllPages = JsonConvert.DeserializeObject<ObservableCollection<osBase>>(jsonString, settings);
                if (objetosSimulablesAllPages != null)
                {
                    foreach (var obj in objetosSimulablesAllPages)
                        _mainViewModel.ObjetosSimulables.Add(obj);
                }
            }
        }

        private void SerializeAndSave(object objectToSerialize, string path)
        {
            // Create backup if file exists
            if (File.Exists(path))
            {
                var backupPath = Path.ChangeExtension(path, ".bak");
                File.Copy(path, backupPath, true);
            }

            var settings = GetJsonSerializerSettings();
            var serializedData = JsonConvert.SerializeObject(objectToSerialize, settings);
            File.WriteAllText(path, serializedData);
        }

        private JsonSerializerSettings GetJsonSerializerSettings()
        {
            return new JsonSerializerSettings
            {
                Formatting = Formatting.Indented,
                NullValueHandling = NullValueHandling.Ignore,
                TypeNameHandling = TypeNameHandling.Auto,
                ObjectCreationHandling = ObjectCreationHandling.Replace,
                ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
            };
        }
    }
}

