using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

public class ItemDatabase : EditorWindow {

    private Sprite defaultItemIcon;
    private static List<Item> databaseItems = new List<Item>();

    private static List<PlacedObjectTypeSO> buildableItems = new List<PlacedObjectTypeSO>();
    private static List<UIMenuItem> menuItems = new List<UIMenuItem>();

    private VisualElement itemsTab;
    private static VisualTreeAsset m_ItemRowTemplate;
    private ListView itemListView;
    private float itemHeight = 40;

    private ScrollView detailSection;
    private VisualElement largeDisplayIcon;
    private Item activeItem;
    private VisualTreeAsset BuildableObjectButtonTemplate;
    private VisualTreeAsset MenuItemTemplate;

    [MenuItem("WUG/Item Database")]
    public static void Init() {
        ItemDatabase wnd = GetWindow<ItemDatabase>();
        wnd.titleContent = new GUIContent("Item Database");

        Vector2 size = new Vector2(800, 475);
        wnd.minSize = size;
        wnd.maxSize = size;
    }

    public void CreateGUI() {
        var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/WUG/Editor/ItemDatabase.uxml");
        VisualElement rootFromUXML = visualTree.Instantiate();
        rootVisualElement.Add(rootFromUXML);

        var styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/WUG/Editor/ItemDatabase.uss");
        rootVisualElement.styleSheets.Add(styleSheet);

        defaultItemIcon = (Sprite)AssetDatabase.LoadAssetAtPath("Assets/WUG/Sprites/UnknownIcon.png", typeof(Sprite));
        m_ItemRowTemplate = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Scripts/UI/ItemDatabase/ItemRowTemplate.uxml");

        BuildableObjectButtonTemplate = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Scripts/UI/ItemDatabase/BuildableObjectTemplate.uxml");
        MenuItemTemplate = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Scripts/UI/ItemDatabase/MenuItemTemplate.uxml");

        LoadAllItems();
        LoadAllBuildableItems();

        GenerateMenuItems();
        itemsTab = rootVisualElement.Q<VisualElement>("ItemsTab");
        GenerateListView();

        detailSection = rootVisualElement.Q<ScrollView>("ScrollView_Details");
        detailSection.style.visibility = Visibility.Hidden;
        largeDisplayIcon = detailSection.Q<VisualElement>("Icon");

        rootVisualElement.Q<Button>("Btn_AddItem").clicked += AddItem_OnClick;

        detailSection.Q<TextField>("ItemName").RegisterValueChangedCallback(evt => {
            activeItem.FriendlyName = evt.newValue;
            itemListView.Rebuild();
        });

        detailSection.Q<ObjectField>("IconPicker").RegisterValueChangedCallback(evt => {
            Sprite newSprite = evt.newValue as Sprite;
            activeItem.Icon = newSprite == null ? defaultItemIcon : newSprite;
            largeDisplayIcon.style.backgroundImage = newSprite == null ? defaultItemIcon.texture : newSprite.texture;

            itemListView.Rebuild();

            rootVisualElement.Q<Button>("Btn_DeleteItem").clicked += DeleteItem_OnClick;
        });
    }

    private void DeleteItem_OnClick() {
        // Get the path of the fie and delete it through AssetDatabase
        string path = AssetDatabase.GetAssetPath(activeItem);
        AssetDatabase.DeleteAsset(path);

        databaseItems.Remove(activeItem);
        itemListView.Rebuild();

        detailSection.style.visibility = Visibility.Hidden;
    }

    private void AddItem_OnClick() {
        // Create an instance of the scriptable object and set the default parameters
        Item newItem = CreateInstance<Item>();
        newItem.FriendlyName = $"New Item";
        newItem.Icon = defaultItemIcon;

        // Create an asset, using the unique ID for the name
        AssetDatabase.CreateAsset(newItem, $"Assets/Data/{newItem.ID}.asset");

        // Add it to the item list
        databaseItems.Add(newItem);

        // Refresh the listView so everyting is redrawn again
        itemListView.Rebuild();
        itemListView.style.height = databaseItems.Count * itemHeight;
    }

    private void GenerateListView() {
        Func<VisualElement> makeItem = () => m_ItemRowTemplate.CloneTree();

        Action<VisualElement, int> bindItem = (e, i) => {
            e.Q<VisualElement>("Icon").style.backgroundImage = databaseItems[i] == null ? defaultItemIcon.texture :
            databaseItems[i].Icon.texture;
            e.Q<Label>("Name").text = databaseItems[i].FriendlyName;
        };

        itemListView = new ListView(databaseItems, 35, makeItem, bindItem);
        itemListView.selectionType = SelectionType.Single;
        // itemListView.style.height = databaseItems.Count * itemHeight;
        itemsTab.Add(itemListView);

        itemListView.onSelectionChange += ListView_onSelectionChange;
    }

    private void GenerateMenuItems() {
        Func<VisualElement> menuItem = () => MenuItemTemplate.CloneTree();

        Action<VisualElement, int> bindItem = (e, i) => {
            e.Q<Button>("MenuButton").text = menuItems[i].MenuText;
        };
    }

    private void GenerateBuildableObjectsList() {
        Func<VisualElement> makeItem = () => BuildableObjectButtonTemplate.CloneTree();

        Action<VisualElement, int> bindItem = (e, i) => {
            e.Q<Button>("BuildButton").text = buildableItems[i].ButtonText;
        };
    }

    private void LoadAllItems() {
        databaseItems.Clear();

        string[] allPaths = Directory.GetFiles("Assets/Data", "*.asset", SearchOption.AllDirectories);
        foreach (string path in allPaths) {
            string cleanedPath = path.Replace("\\", "/");
            databaseItems.Add((Item)AssetDatabase.LoadAssetAtPath(cleanedPath, typeof(Item)));
        }
    }

    private void LoadAllBuildableItems() {
        buildableItems.Clear();

        string[] allMenuPaths = Directory.GetFiles("Assets/Data/UI/Menus", "*.assets", SearchOption.AllDirectories);
        string[] allBuildablePaths = Directory.GetFiles("Assets/Data/Buildables", "*.assets", SearchOption.AllDirectories);

        foreach (string path in allMenuPaths) {
            string cleanedPath = path.Replace("\\", "/");
            menuItems.Add((UIMenuItem)AssetDatabase.LoadAssetAtPath(cleanedPath, typeof(UIMenuItem)));
        }

        foreach (string path in allBuildablePaths) {
            string cleanedPath = path.Replace("\\", "/");
            buildableItems.Add((PlacedObjectTypeSO)AssetDatabase.LoadAssetAtPath(cleanedPath, typeof(PlacedObjectTypeSO)));
        }
    }

    private void ListView_onSelectionChange(IEnumerable<object> selectedItems) {
        activeItem = (Item)selectedItems.First();

        SerializedObject so = new SerializedObject(activeItem);
        detailSection.Bind(so);
        if (activeItem.Icon != null) {
            largeDisplayIcon.style.backgroundImage = activeItem.Icon.texture;
        }
        detailSection.style.visibility = Visibility.Visible;
    }
}
