using System;

using UnityEditor;
using UnityEngine;

namespace Unity.PlasticSCM.Editor.UI
{
    internal class TabButton
    {
        internal bool DrawTabButton(
            string buttonText,
            bool wasActive,
            float width)
        {
            bool isCloseButtonClicked;

            return DrawClosableTabButton(
                buttonText,
                wasActive,
                false,
                width,
                null,
                out isCloseButtonClicked);
        }

        internal bool DrawClosableTabButton(
            string buttonText,
            bool wasActive,
            bool isClosable,
            float width,
            Action repaintAction,
            out bool isCloseButtonClicked)
        {
            isCloseButtonClicked = false;

            GUIContent buttonContent = new GUIContent(buttonText);

            GUIStyle buttonStyle = UnityStyles.PlasticWindow.TabButton;

            Rect toggleRect = GUILayoutUtility.GetRect(
                buttonContent, buttonStyle,
                GUILayout.Width(width));

            if (isClosable && Event.current.type == EventType.MouseMove)
            {
                if (mCloseButtonRect.Contains(Event.current.mousePosition))
                {
                    SetCloseButtonState(
                        CloseButtonState.Hovered,
                        repaintAction);
                }
                else
                {
                    SetCloseButtonState(
                        CloseButtonState.Normal,
                        repaintAction);
                }
            }

            if (isClosable && Event.current.type == EventType.MouseDown)
            {
                if (mCloseButtonRect.Contains(Event.current.mousePosition))
                {
                    SetCloseButtonState(
                        CloseButtonState.Clicked,
                        repaintAction);
                    Event.current.Use();
                }
            }

            if (isClosable && Event.current.type == EventType.MouseUp)
            {
                if (mCloseButtonRect.Contains(Event.current.mousePosition))
                {
                    Event.current.Use();
                    isCloseButtonClicked = true;
                }

                if (IsTabClickWithMiddleButton(toggleRect, Event.current))
                {
                    Event.current.Use();
                    isCloseButtonClicked = true;
                }

                SetCloseButtonState(
                    CloseButtonState.Normal,
                    repaintAction);
            }

            bool isActive = GUI.Toggle(
                toggleRect, wasActive, buttonText, buttonStyle);

            if (isClosable && toggleRect.height > 1)
            {
                mCloseButtonRect = DrawCloseButton(
                    toggleRect,
                    mCloseButtonState);
            }

            if (wasActive)
            {
                DrawUnderline(toggleRect);
            }

            return isActive;
        }

        static Rect DrawCloseButton(
            Rect toggleRect,
            CloseButtonState state)
        {
            int closeButtonSize = 15;

            GUIContent closeImage = new GUIContent(GetCloseImage(state));

            Rect closeTabRect = new Rect(
                toggleRect.xMax - closeButtonSize - 1,
                toggleRect.y + (toggleRect.height / 2 - closeButtonSize / 2),
                closeButtonSize,
                closeButtonSize);

            GUI.Button(closeTabRect, closeImage, EditorStyles.label);

            return new Rect(
                closeTabRect.x - 1,
                closeTabRect.y - 1,
                closeTabRect.width + 2,
                closeTabRect.height + 2);
        }

        static void DrawUnderline(Rect toggleRect)
        {
            GUIStyle activeTabStyle =
                UnityStyles.PlasticWindow.ActiveTabUnderline;

            Rect underlineRect = new Rect(
                toggleRect.x,
                toggleRect.yMax - (activeTabStyle.fixedHeight / 2),
                toggleRect.width,
                activeTabStyle.fixedHeight);

            GUI.Label(underlineRect, string.Empty, activeTabStyle);
        }

        static bool IsTabClickWithMiddleButton(Rect toggleRect, Event currentEvent)
        {
            if (currentEvent.button != 2)
                return false;

            return toggleRect.height > 1 &&
                   toggleRect.Contains(Event.current.mousePosition);
        }

        static Texture GetCloseImage(CloseButtonState state)
        {
            if (state == CloseButtonState.Hovered)
                return Images.GetHoveredCloseIcon();

            if (state == CloseButtonState.Clicked)
                return Images.GetClickedCloseIcon();

            return Images.GetCloseIcon();
        }

        void SetCloseButtonState(
            CloseButtonState newState,
            Action repaintAction)
        {
            if (mCloseButtonState == newState)
                return;

            mCloseButtonState = newState;

            if (repaintAction != null)
                repaintAction();
        }

        Rect mCloseButtonRect;
        CloseButtonState mCloseButtonState;

        enum CloseButtonState
        {
            Normal,
            Clicked,
            Hovered,
        }
    }
}