using System.Collections.Generic;
using AssetBank.Editor.DockableWindow;
using UnityEditor;
using UnityEngine;

namespace AssetBank.Settings
{
    internal class ProjectExporterSettingsProvider : SettingsProvider
    {
        private SerializedObject m_Settings;
        private SerializedProperty m_FoldersToIgnore;
        private SerializedProperty m_FileExtensionsToIgnore;
        private SerializedProperty m_UnityTypesToIgnore;
        private SerializedProperty m_ConvertToNewSchema;
        private SerializedProperty m_OptimiseExport;
        private SerializedProperty m_CategoriesToOptimise;
        private SerializedProperty m_SafeComponents;
        private SerializedProperty m_HardcodedComponents;
        private SerializedProperty m_OverrideHardcodedDefaults;

        const string k_SettingsPath = "Project/Project AssetDatabase";

        public ProjectExporterSettingsProvider(string path, SettingsScope scope = SettingsScope.Project)
            : base(path, scope) {}

        public override void OnActivate(string searchContext, UnityEngine.UIElements.VisualElement rootElement)
        {
            m_Settings = ProjectExporterSettings.GetSerializedSettings();
            m_FoldersToIgnore = m_Settings.FindProperty("m_FoldersToIgnore");
            m_FileExtensionsToIgnore = m_Settings.FindProperty("m_FileExtensionsToIgnore");
            m_UnityTypesToIgnore = m_Settings.FindProperty("m_UnityTypesToIgnore");
            m_ConvertToNewSchema = m_Settings.FindProperty("m_ConvertToNewSchema");
            m_OptimiseExport = m_Settings.FindProperty("m_OptimiseExport");
            m_CategoriesToOptimise = m_Settings.FindProperty("m_CategoriesToOptimise");
            m_SafeComponents = m_Settings.FindProperty("m_SafeComponents");
            m_HardcodedComponents = m_Settings.FindProperty("m_HardcodedComponents");
            m_OverrideHardcodedDefaults = m_Settings.FindProperty("m_OverrideHardcodedDefaults");
        }

        public override void OnGUI(string searchContext)
        {
            if (m_Settings == null || m_Settings.targetObject == null)
            {
                EditorGUILayout.HelpBox("Settings asset not found. It will be created automatically.", MessageType.Info);
                m_Settings = ProjectExporterSettings.GetSerializedSettings();
                return;
            }
            
            m_Settings.Update();

            EditorGUILayout.PropertyField(m_FoldersToIgnore, new GUIContent("Folders to Ignore"), true);
            EditorGUILayout.PropertyField(m_FileExtensionsToIgnore, new GUIContent("File Extensions to Ignore"), true);
            EditorGUILayout.PropertyField(m_UnityTypesToIgnore, new GUIContent("Unity Types to Ignore"), true);
            
            EditorGUILayout.Space();
            
            EditorGUILayout.LabelField("JSON Processing", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(m_ConvertToNewSchema, new GUIContent("Convert to Hierarchical Schema", "Converts the final JSON to the new, structured format."));
            EditorGUILayout.PropertyField(m_OptimiseExport, new GUIContent("Optimise Export (Trim Data)", "Runs the initial data trimming process based on the rules below."));
            if(m_OptimiseExport.boolValue)
            {
                DrawCategoriesToOptimise();
                EditorGUILayout.Space();

                EditorGUILayout.LabelField("Hardcoded Rules", EditorStyles.boldLabel);
                EditorGUILayout.PropertyField(m_OverrideHardcodedDefaults, new GUIContent("Override Defaults", "Check this to ignore the hardcoded safety rules and use only the 'Safe Components' list below. Warning: This can break scene hierarchy if not configured correctly."));
                
                EditorGUI.BeginDisabledGroup(true);
                EditorGUILayout.PropertyField(m_HardcodedComponents, new GUIContent("Hardcoded Safe Components (Read-Only)"), true);
                EditorGUI.EndDisabledGroup();
                
                EditorGUILayout.Space();

                EditorGUILayout.LabelField("User-Defined Rules", EditorStyles.boldLabel);
                EditorGUILayout.PropertyField(m_SafeComponents, new GUIContent("Safe Components"), true);
            }

            if (m_Settings.hasModifiedProperties)
            {
                m_Settings.ApplyModifiedProperties();
            }
        }

        private void DrawCategoriesToOptimise()
        {
            EditorGUILayout.LabelField("Categories to Optimise", EditorStyles.boldLabel);
            
            EditorGUI.indentLevel++;
            
            var categories = new List<string>();
            for (int i = 0; i < m_CategoriesToOptimise.arraySize; i++)
            {
                categories.Add(m_CategoriesToOptimise.GetArrayElementAtIndex(i).stringValue);
            }

            foreach (var availableCategory in ProjectExporterCategories.All)
            {
                var isEnabled = categories.Contains(availableCategory);
                var newIsEnabled = EditorGUILayout.Toggle(availableCategory, isEnabled);

                if (newIsEnabled && !isEnabled)
                {
                    // Add to list
                    var index = m_CategoriesToOptimise.arraySize;
                    m_CategoriesToOptimise.InsertArrayElementAtIndex(index);
                    m_CategoriesToOptimise.GetArrayElementAtIndex(index).stringValue = availableCategory;
                }
                else if (!newIsEnabled && isEnabled)
                {
                    // Remove from list
                    for (int i = 0; i < m_CategoriesToOptimise.arraySize; i++)
                    {
                        if (m_CategoriesToOptimise.GetArrayElementAtIndex(i).stringValue == availableCategory)
                        {
                            m_CategoriesToOptimise.DeleteArrayElementAtIndex(i);
                            break;
                        }
                    }
                }
            }
            EditorGUI.indentLevel--;
        }

        [SettingsProvider]
        public static SettingsProvider CreateSettingsProvider()
        {
            var provider = new ProjectExporterSettingsProvider(k_SettingsPath, SettingsScope.Project)
            {
                keywords = GetSearchKeywordsFromGUIContentProperties<Styles>()
            };
            return provider;
        }

        private class Styles
        {
            public static GUIContent foldersToIgnore = new GUIContent("Folders to Ignore");
            public static GUIContent fileExtensionsToIgnore = new GUIContent("File Extensions to Ignore");
            public static GUIContent unityTypesToIgnore = new GUIContent("Unity Types to Ignore");
            public static GUIContent optimiseExport = new GUIContent("Optimise Export");
            public static GUIContent safeComponents = new GUIContent("Safe Components");
        }
    }
}
