using Newtonsoft.Json;
using System.Windows.Controls;
using CtrEditor.Simulacion;
using System.Reflection;

using System.Windows.Data;
using System.Windows;
using System.Windows.Media;
using CtrEditor.ObjetosSim.UserControls;
using System.Collections;
using System.Windows.Input;
using System.Windows.Shapes;
using Xceed.Wpf.Toolkit.PropertyGrid;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using Xceed.Wpf.Toolkit;
using Xceed.Wpf.Toolkit.PropertyGrid.Editors;
using CtrEditor.ObjetosSim.Extraccion_Datos;

namespace CtrEditor.ObjetosSim
{
    public static class UserControlFactory
    {
        public static UserControl? GetControlForType(Type tipoObjeto)
        {
            // Obtener el nombre del tipo de objeto
            string typeName = tipoObjeto.Name;

            // Cambiar las primeras dos letras de 'os' a 'uc'
            if (typeName.StartsWith("os"))
            {
                string newTypeName = "uc" + typeName.Substring(2);

                // Obtener el ensamblado donde se encuentra el tipo UserControl
                Assembly assembly = Assembly.GetExecutingAssembly();

                // Buscar el tipo en los ensamblados cargados
                Type? controlType = AppDomain.CurrentDomain.GetAssemblies()
                    .SelectMany(a => a.GetTypes())
                    .FirstOrDefault(t => t.Name == newTypeName);

                if (controlType != null && typeof(UserControl).IsAssignableFrom(controlType))
                {
                    // Crear una instancia del tipo encontrado
                    return (UserControl?)Activator.CreateInstance(controlType);
                }
            }

            return null;
        }

        public static osBase? GetInstanceForType(Type tipoObjeto)
        {
            // Verifica si el tipo pasado es un subtipo de osBase
            if (!typeof(osBase).IsAssignableFrom(tipoObjeto))
            {
                throw new ArgumentException("El tipo pasado no es un subtipo de osBase", nameof(tipoObjeto));
            }

            // Crear una instancia del tipo especificado
            osBase obj = (osBase?)Activator.CreateInstance(tipoObjeto);
            obj.InicializaNuevoObjeto();
            return obj;
        }

        public static osBase? CreateInstanceAndPopulate(Type tipoObjeto, string jsonString)
        {
            osBase? instance = GetInstanceForType(tipoObjeto);
            if (instance != null)
            {
                // Deserializa los datos desde jsonString y popula la instancia
                JsonConvert.PopulateObject(jsonString, instance);
            }
            return instance;
        }

        public static void AssignDatos(UserControl userControl, osBase datos, SimulationManagerFP simulationManager)
        {
            if (userControl is IDataContainer dataContainer)
            {
                dataContainer.Datos = datos;
                userControl.DataContext = datos;
                datos.VisualRepresentation = userControl;
                datos.simulationManager = simulationManager;
            }
        }

        public static void LimpiarPropiedadesosDatos(PropertyGrid propertyGrid)
        {
            // Clear previous properties
            propertyGrid.SelectedObject = null;
            propertyGrid.PropertyDefinitions.Clear();
        }


        public static void CargarPropiedadesosDatos(object selectedObject, PropertyGrid propertyGrid)
        {
            // Clear previous properties
            propertyGrid.SelectedObject = null;
            propertyGrid.PropertyDefinitions.Clear();

            // Add properties dynamically based on attributes
            var properties = TypeDescriptor.GetProperties(selectedObject)
                                            .Cast<PropertyDescriptor>()
                                            .Where(prop => !prop.Attributes.OfType<HiddenAttribute>().Any()).OrderBy(prop => prop.Name);

            foreach (var property in properties)
            {
                var displayNameAttr = property.Attributes.OfType<DisplayNameAttribute>().FirstOrDefault();
                var propertyDefinition = new PropertyDefinition
                {
                    TargetProperties = new[] { property.Name }
                };

                if (!property.Name.EndsWith("_oculto"))
                {
                    if (displayNameAttr != null)
                    {
                        propertyDefinition.DisplayName = displayNameAttr.DisplayName;
                    }
                    else
                    {
                        propertyDefinition.DisplayName = property.Name.Replace("_", " ");
                    }
                    if (property.PropertyType == typeof(double) || property.PropertyType == typeof(float) || property.PropertyType == typeof(string) || property.PropertyType == typeof(int) ||
                        property.PropertyType == typeof(bool) || property.PropertyType == typeof(osBase) ||
                        property.PropertyType == typeof(osVMmotorSim) || property.PropertyType == typeof(osBuscarCoincidencias) || property.PropertyType == typeof(Color) )
                    {
                        propertyGrid.PropertyDefinitions.Add(propertyDefinition);
                    }
                }
            }

            propertyGrid.SelectedObject = selectedObject;
        }

    }
}

