using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// Top banner with three buttons (1=Live View, 2=Inverse Kinematics, 3=Programmed Movements).
/// Each button enables the corresponding view GameObject and disables the other two.
/// View-specific logic should be attached under those GameObjects; when disabled, it is suspended.
/// </summary>
public class ViewBannerUI : MonoBehaviour
{
    private const string ViewsParentName = "Views";
    private const string LiveViewName = "LiveView";
    private const string InverseKinematicsViewName = "InverseKinematicsView";
    private const string ProgrammedMovementsViewName = "ProgrammedMovementsView";

    [Header("Layout")]
    [SerializeField] private float bannerHeight = 48f;
    [SerializeField] private float buttonPadding = 6f;

    [Header("Colors")]
    [SerializeField] private Color bannerBackground = Color.black;
    [SerializeField] private Color buttonDefault = Color.white;
    [SerializeField] private Color buttonSelected = new Color(177f / 255f, 1f, 199f / 255f, 1f); // #B1FFC7
    [SerializeField] private Color buttonTextColor = Color.black;

    private GameObject _liveViewRoot;
    private GameObject _inverseKinematicsViewRoot;
    private GameObject _programmedMovementsViewRoot;
    private RectTransform _bannerRoot;
    private Image[] _buttonImages = new Image[3];
    // Labels without "View": Live, Inverse Kinematics, Programmed Movements
    private static readonly string[] Labels = { "Live", "Inverse Kinematics", "Programmed Movements" };

    private void Awake()
    {
        if (!ResolveViewRoots())
            return;

        // Use this GameObject as the banner (must be under Canvas with RectTransform + Image).
        _bannerRoot = GetComponent<RectTransform>();
        if (_bannerRoot == null)
        {
            Debug.LogError("[ViewBannerUI] ViewBanner must have a RectTransform (e.g. under Canvas).");
            return;
        }

        var bannerImage = GetComponent<Image>();
        if (bannerImage != null)
            bannerImage.color = new Color(0f, 0f, 0f, 1f); // solid black, full opacity

        // Default to Live View on startup.
        SetActiveView(ViewMode.LiveView);

        for (int i = 0; i < 3; i++)
        {
            ViewMode mode = (ViewMode)i;
            _buttonImages[i] = CreateViewButton(_bannerRoot, i, Labels[i], () => OnViewButtonClicked(mode));
        }
        RefreshButtonVisuals();
    }

    /// <summary>
    /// Resolves the three view root GameObjects that must already exist in the scene hierarchy:
    /// Views/LiveView, Views/InverseKinematicsView, Views/ProgrammedMovementsView.
    /// Returns false and logs a clear error if anything is missing.
    /// </summary>
    private bool ResolveViewRoots()
    {
        Transform viewsParent = GameObject.Find(ViewsParentName)?.transform;
        if (viewsParent == null)
        {
            Debug.LogError(
                $"[ViewBannerUI] Missing '{ViewsParentName}' GameObject. " +
                $"Please create it in the scene with children '{LiveViewName}', '{InverseKinematicsViewName}', '{ProgrammedMovementsViewName}'."
            );
            return false;
        }

        _liveViewRoot = viewsParent.Find(LiveViewName)?.gameObject;
        _inverseKinematicsViewRoot = viewsParent.Find(InverseKinematicsViewName)?.gameObject;
        _programmedMovementsViewRoot = viewsParent.Find(ProgrammedMovementsViewName)?.gameObject;

        if (_liveViewRoot == null || _inverseKinematicsViewRoot == null || _programmedMovementsViewRoot == null)
        {
            Debug.LogError(
                $"[ViewBannerUI] Missing one or more view roots under '{ViewsParentName}'. " +
                $"Expected children named '{LiveViewName}', '{InverseKinematicsViewName}', '{ProgrammedMovementsViewName}'."
            );
            return false;
        }

        return true;
    }

    private void OnViewButtonClicked(ViewMode mode)
    {
        SetActiveView(mode);
        RefreshButtonVisuals();
    }

    /// <summary>
    /// Enables the view GameObject for the given mode and disables the other two.
    /// </summary>
    public void SetActiveView(ViewMode mode)
    {
        _liveViewRoot.SetActive(mode == ViewMode.LiveView);
        _inverseKinematicsViewRoot.SetActive(mode == ViewMode.InverseKinematics);
        _programmedMovementsViewRoot.SetActive(mode == ViewMode.ProgrammedMovements);
    }

    private void RefreshButtonVisuals()
    {
        bool liveActive = _liveViewRoot != null && _liveViewRoot.activeSelf;
        bool ikActive = _inverseKinematicsViewRoot != null && _inverseKinematicsViewRoot.activeSelf;
        bool pmActive = _programmedMovementsViewRoot != null && _programmedMovementsViewRoot.activeSelf;

        if (_buttonImages[0] != null) _buttonImages[0].color = liveActive ? buttonSelected : buttonDefault;
        if (_buttonImages[1] != null) _buttonImages[1].color = ikActive ? buttonSelected : buttonDefault;
        if (_buttonImages[2] != null) _buttonImages[2].color = pmActive ? buttonSelected : buttonDefault;
    }

    private Image CreateViewButton(RectTransform parent, int index, string label, UnityEngine.Events.UnityAction onClick)
    {
        var go = new GameObject($"ViewButton_{label}");
        go.transform.SetParent(parent, false);

        var rect = go.AddComponent<RectTransform>();
        // Buttons at 1/6 width each, centered as a group (1/4 margin each side)
        float sixth = 1f / 6f;
        float startX = 0.25f; // left margin so block is centered
        rect.anchorMin = new Vector2(startX + index * sixth, 0f);
        rect.anchorMax = new Vector2(startX + (index + 1) * sixth, 1f);
        rect.pivot = new Vector2(0.5f, 0.5f);
        rect.anchoredPosition = Vector2.zero;
        rect.sizeDelta = Vector2.zero;
        rect.offsetMin = new Vector2(buttonPadding, buttonPadding);
        rect.offsetMax = new Vector2(-buttonPadding, -buttonPadding);

        var image = go.AddComponent<Image>();
        image.color = buttonDefault;
        image.raycastTarget = true;
        image.sprite = UIRoundedSprite.GetRoundedRectSprite();
        image.type = Image.Type.Simple;

        var button = go.AddComponent<Button>();
        button.targetGraphic = image;
        // Use white for all states so Unity doesn't tint the button blue when selected/highlighted
        var colors = button.colors;
        colors.normalColor = Color.white;
        colors.highlightedColor = Color.white;
        colors.pressedColor = Color.white;
        colors.selectedColor = Color.white;
        colors.disabledColor = new Color(1f, 1f, 1f, 0.5f);
        button.colors = colors;
        button.onClick.AddListener(onClick);

        var textGo = new GameObject("Text");
        textGo.transform.SetParent(go.transform, false);
        var textRect = textGo.AddComponent<RectTransform>();
        textRect.anchorMin = Vector2.zero;
        textRect.anchorMax = Vector2.one;
        textRect.offsetMin = new Vector2(6, 4);
        textRect.offsetMax = new Vector2(-6, -4);

        var txt = textGo.AddComponent<Text>();
        txt.font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
        txt.text = label;
        txt.fontSize = 18;
        txt.fontStyle = FontStyle.Bold;
        txt.alignment = TextAnchor.MiddleCenter;
        txt.color = buttonTextColor;
        txt.horizontalOverflow = HorizontalWrapMode.Wrap;

        return image;
    }

}
