/*
<copyright file="BGDBUiToolkitElementsSearcher.cs" company="BansheeGz">
    Copyright (c) 2018-2021 All Rights Reserved
</copyright>
*/


using System;
using System.Collections.Generic;
using UnityEditor.Searcher;
using UnityEngine;
using UnityEngine.UIElements;

namespace BansheeGz.BGDatabase.Editor
{
    public static class BGDBUiToolkitElementsSearcher
    {
        public static void Open(BGDBUiToolkitBindersWindow editorWindow, Action<VisualElement> selected, Vector2? offset = null)
        {
            var items = GetItems(editorWindow.Toolkit.Doc);
            var database = new SearcherDatabase(items);
            var searcher = new Searcher(database);
            var rect = new Rect(editorWindow.position.position + (offset ?? Event.current.mousePosition), new Vector2(600, 500));
            SearcherWindow.Show(editorWindow, searcher, item =>
            {
                if (item == null) return false;
                selected(((BGSearcherItem)item).Element);
                return true;
            }, null, rect);
        }

        public static List<SearcherItem> GetItems(UIDocument doc)
        {
            var result = new List<SearcherItem>();
            if (doc.rootVisualElement == null) return result;
            var firstLevelChildren = doc.rootVisualElement.Children();
            if (firstLevelChildren == null)  return result;
            foreach (var child in firstLevelChildren) result.Add(Gather(child));
            return result;
        }

        private static SearcherItem Gather(VisualElement element)
        {
            var result = new BGSearcherItem(element);

            var stack = new Stack<Tuple<BGSearcherItem, VisualElement>>();
            stack.Push(Tuple.Create(result, element));
            while (stack.Count > 0)
            {
                var (searcherItem, visualElement) = stack.Pop();
                var children = visualElement.Children();
                foreach (var child in children)
                {
                    var childItem = new BGSearcherItem(child);
                    searcherItem.AddChild(childItem);
                    stack.Push(Tuple.Create(childItem, child));
                }
            }

            return result;
        }

        private class BGSearcherItem : SearcherItem
        {
            private readonly VisualElement element;

            public VisualElement Element => element;

            public BGSearcherItem(VisualElement element) : base(string.IsNullOrEmpty(element.name) ? element.GetType().Name + "[No name]" : element.name) => this.element = element;
        }
    }
}