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

namespace Editor.GON.StageEditor
{
    public sealed class StagePalettePanel : VisualElement
    {
        private readonly StageEditorState state;
        private readonly List<StagePaletteEntry> entries;

        public StagePalettePanel(StageEditorState state, List<StagePaletteEntry> entries)
        {
            this.state = state;
            this.entries = entries;

            style.flexDirection = FlexDirection.Column;
            style.minHeight = 110;
            style.maxHeight = 170;
            style.paddingLeft = 8;
            style.paddingRight = 8;
            style.paddingTop = 6;
            style.paddingBottom = 6;
            style.borderTopWidth = 1;
            style.borderTopColor = new Color(1f, 1f, 1f, 0.12f);

            state.Changed += Rebuild;
            Rebuild();
        }

        private void Rebuild()
        {
            Clear();

            var row = new VisualElement
            {
                style =
                {
                    flexDirection = FlexDirection.Row,
                    alignItems = Align.Center
                }
            };
            Add(row);

            var title = new Label("Palette")
            {
                style =
                {
                    unityFontStyleAndWeight = FontStyle.Bold,
                    marginRight = 12
                }
            };
            row.Add(title);

            AddLayerButton(row, StageLogicalLayer.Structural);
            AddLayerButton(row, StageLogicalLayer.Design);
            AddLayerButton(row, StageLogicalLayer.Camera);
            AddLayerButton(row, StageLogicalLayer.Markers);

            var hint = new Label("LMB selects objects. Empty space paints/places selected palette item. RMB/MMB pans.")
                {
                    style =
                    {
                        opacity = 0.65f,
                        marginLeft = 12
                    }
                };
            row.Add(hint);

            var scroll = new ScrollView(ScrollViewMode.Horizontal)
            {
                style =
                {
                    flexGrow = 1f,
                    marginTop = 8
                }
            };
            Add(scroll);

            var itemRow = new VisualElement
            {
                style =
                {
                    flexDirection = FlexDirection.Row
                }
            };
            scroll.Add(itemRow);

            foreach (var entry in entries)
            {
                if (entry.layer != state.activeLayer)
                {
                    continue;
                }
                
                var button = new Button(delegate { state.SetPaletteEntry(entry); })
                {
                    text = entry.displayName,
                    style =
                    {
                        minWidth = 120,
                        height = 48,
                        marginRight = 6,
                        unityTextAlign = TextAnchor.MiddleCenter
                    }
                };

                if (state.activePaletteEntry == entry)
                {
                    button.style.borderBottomWidth = 3;
                    button.style.borderBottomColor = StageEditorColors.SelectionStroke;
                }

                itemRow.Add(button);
            }
        }

        private void AddLayerButton(VisualElement row, StageLogicalLayer layer)
        {
            
            var button = new Button(delegate
            {
                state.SetActiveLayer(layer);

                if (state.activePaletteEntry == null || state.activePaletteEntry.layer != layer)
                {
                    var first = FindFirstEntryForLayer(layer);
                    if (first != null)
                    {
                        state.SetPaletteEntry(first);
                    }
                }
            })
            {
                text = layer.ToString(),
                style =
                {
                    marginRight = 4
                }
            };

            if (state.activeLayer == layer)
            {
                button.style.borderBottomWidth = 3;
                button.style.borderBottomColor = StageEditorColors.SelectionStroke;
            }
            row.Add(button);
        }

        private StagePaletteEntry FindFirstEntryForLayer(StageLogicalLayer layer)
        {
            foreach (var stagePaletteEntry in entries)
            {
                if (stagePaletteEntry.layer == layer)
                {
                    return stagePaletteEntry;
                }
            }

            return null;
        }
    }
}
