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

namespace Ingvar.LiveWatch.Editor
{
    public class ToolbarGUI
    {
        public bool Search { get; set; }
        public bool Live
        {
            get => Watch.IsLive;
            set => Watch.IsLive = value;
        }
        public bool Collapse 
        {
            get => WatchStorageSO.instance.Collapse;
            set => WatchStorageSO.instance.Collapse = value;
        }

        public WatchStorage Watches
        {
            get => WatchStorageSO.instance.Watches;
            set
            {
                Watch.DestroyAll();
                WatchStorageSO.instance.Watches = value;
            }
        }
        
        public Rect WindowRect { get; set; }
        private Rect areaRect;
        private float xOffsetRight;
        private float xOffsetLeft;
        private GUIContent saveButtonContent;
        private GUIContent loadButtonContent;
        private GUIContent optionsButtonContent;
        private List<WatchVariable> variables = new();

        public void OnGUI(Rect areaRect)
        {
            this.areaRect = areaRect;
            GUI.Label(areaRect, string.Empty, EditorStyles.toolbar);

            xOffsetLeft = 0;
            
            var centerBlockWidth = Constants.ToolbarLiveButtonWidth + Constants.ToolbarCollapseButtonWidth + Constants.ToolbarClearButtonWidth;
            xOffsetLeft = areaRect.width/2 - centerBlockWidth/2;
            DoLiveButton(CropEdge.LeftLocal, ref xOffsetLeft);
            DoCollapseButton(CropEdge.LeftLocal, ref xOffsetLeft);
            DoClearButton(CropEdge.LeftLocal, ref xOffsetLeft);
            
            xOffsetRight = 0;
            DoOptionsButton(CropEdge.RightLocal, ref xOffsetRight);
            DoViewSettingsButton(CropEdge.RightLocal, ref xOffsetRight);
        }


        private void DoOptionsButton(CropEdge edge, ref float offset)
        {
            optionsButtonContent ??= EditorGUIUtility.TrIconContent("_Menu", "Extra options");
            var rect = areaRect.CropFromPositionWithSize(edge, offset, Constants.ToolbarOptionsButtonWidth);
            
            if (GUI.Button(rect, optionsButtonContent, EditorStyles.toolbarButton))
            {
                GenericMenu genericMenu = new GenericMenu();
                
                genericMenu.AddItem(new GUIContent(
                        "Preferences", "Go to Live Watch preferences"), 
                    false, 
                    new GenericMenu.MenuFunction(OpenPreferences));
                genericMenu.AddItem(new GUIContent(
                        "Collapse all rows", "Collapses all watched variables recursively"), 
                    false, 
                    new GenericMenu.MenuFunction(CollapseAll));
                genericMenu.AddItem(new GUIContent(
                        "Destroy all watches", "Directly calls Watch.DestroyAll() and removes all watched variables"), 
                    false, 
                    new GenericMenu.MenuFunction(Watch.DestroyAll));
                genericMenu.DropDown(rect);
            }
            
            offset += Constants.ToolbarOptionsButtonWidth;
            
            void OpenPreferences()
            {
                SettingsService.OpenUserPreferences("Preferences/Live Watch");
            }

            void CollapseAll()
            {
                Watches.GetAllChildRecursive(variables, WatchFilters.NoChilds, WatchFilters.None);

                foreach (var variable in variables)
                    variable.EditorMeta.IsExpanded = false;
            }
        }
        

        private void DoViewSettingsButton(CropEdge edge, ref float offset)
        {
            var rect = areaRect.CropFromPositionWithSize(edge, offset, Constants.ToolbarViewButtonWidth);
            var content = new GUIContent("View");
            
            if (GUI.Button(rect, content, EditorStyles.toolbarDropDown))
            {
                var buttonWorldRect = new Rect(rect.x + WindowRect.x, rect.yMax + WindowRect.y, rect.width, rect.height);
                CellSettingsDropdownWindow.Create(buttonWorldRect);
            }
            
            offset += Constants.ToolbarViewButtonWidth;
        }
        
        private void DoClearButton(CropEdge edge, ref float offset)
        {
            var rect = areaRect.CropFromPositionWithSize(edge, offset, Constants.ToolbarClearButtonWidth);
            var content = new GUIContent("Clear", "Clear all watch values");
            
            if (GUI.Button(rect, content, EditorStyles.toolbarButton))
            {
                Watch.ClearAll();
            }
            
            offset += Constants.ToolbarClearButtonWidth;
        }
        
        private void DoCollapseButton(CropEdge edge, ref float offset)
        {
            var rect = areaRect.CropFromPositionWithSize(edge, offset, Constants.ToolbarCollapseButtonWidth);
            var content = new GUIContent("Collapse", Collapse ? "Show columns without unique values" : "Hide columns without unique values");
            
            Collapse = GUI.Toggle(rect, Collapse, content, EditorStyles.toolbarButton);
            
            offset += Constants.ToolbarCollapseButtonWidth;
        }

        private void DoLiveButton(CropEdge edge, ref float offset)
        {
            var rect = areaRect.CropFromPositionWithSize(edge, offset, Constants.ToolbarLiveButtonWidth);
            var content = new GUIContent("Live", Live ? "Watches are recording. Click to pause" : "Watches are not recording. Click to unpause");
            
            Live = GUI.Toggle(rect, Live, content, EditorStyles.toolbarButton);
            
            offset += Constants.ToolbarLiveButtonWidth;
        }
    }
}