using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using System;
using UnityEngine.UI;

public class UIDialog : MonoBehaviour
{
    [SerializeField]
    private string dialogTitle;

    [SerializeField]
    private TextMeshProUGUI dialogTitleHandle;
    [SerializeField]
    private RectTransform contentHandle;

    /// TABS
    [SerializeField]
    private float tabWidth = 50f;
    [SerializeField]
    private float tabHeight = 16f;
    // List of dialog tabs
    private List<GameObject> dialogTabs;

    /// ENTRIES
    private List<UISelectableEntry> entries;

    private float entryHeight = 20f;
    private float entryIndentWidth= 10f;

    private List<UISelectableEntry> cleanupPool;


    private bool isOpen;

    


    // Start is called before the first frame update
    public virtual void Start()
    {
        dialogTitleHandle.text = dialogTitle;
        dialogTitleHandle.font = UIManager.Instance.Font;
        isOpen = gameObject.activeSelf;
        dialogTabs = new List<GameObject>();
        entries = new List<UISelectableEntry>();
        cleanupPool = new List<UISelectableEntry>();
    }

    internal RectTransform GetContentHandle()
    {
        return contentHandle;
    }

    public bool IsOpen()
    {
        return isOpen;
    }

    protected virtual void OnEnable() { isOpen = true; }
    protected virtual void OnDisable() { isOpen = false; }

    public float GetTabWidth() { return tabWidth; }
    public float GetTabHeight() { return tabHeight; }

    /// <summary>
    /// Returns the height of the dialog title bar
    /// </summary>
    public float GetTitleBarHeight() { return dialogTitleHandle.rectTransform.sizeDelta.y;  }

    /// <summary>
    /// Adds a new tab to the dialog, when clicked it will call the given callback
    /// </summary>
    public void AddDialogTab(string tabName, Action onClick)
    {
        dialogTabs.Add(AddTabButton(tabName, onClick));
    }

    /// <summary>
    /// Add the tab button to the right of the existing tabs
    /// </summary>
    private GameObject AddTabButton(string tabName, Action onClick)
    {
        GameObject tabButton = new GameObject("TabButton", typeof(RectTransform));
        tabButton.transform.SetParent(transform); // worldPositionStays ?
        // RectTransform anchors to the right of the content handle
        RectTransform rTransform = tabButton.GetComponent<RectTransform>();
        rTransform.anchorMin = new Vector2(0, 1);
        rTransform.anchorMax = new Vector2(0, 1);
        rTransform.pivot = new Vector2(0, 1);
        rTransform.sizeDelta = new Vector2(tabWidth, tabHeight);
        // Count tabs * tabSize to get the position from the left
        rTransform.anchoredPosition = new Vector2(tabWidth * dialogTabs.Count, -(GetTitleBarHeight()));

        // Add the onClick callback to the button
        Button button = tabButton.AddComponent<Button>();
        button.onClick.AddListener(() => onClick());
        // Add the image to the button and link it to the tab
        button.targetGraphic = tabButton.AddComponent<Image>();
        
        AddTabText(tabName, tabButton);
        return tabButton;
    }

    /// <summary>
    /// Add text as a child of the tab's button object
    /// </summary>
    private void AddTabText(string tabName, GameObject tabButton)
    {
        GameObject tabText = new GameObject("TabText", typeof(RectTransform));
        tabText.transform.SetParent(tabButton.transform);
        // RectTransform anchors to the center of the button
        RectTransform textRectTransform = tabText.GetComponent<RectTransform>();
        textRectTransform.anchorMin = new Vector2(0.5f, 0.5f);
        textRectTransform.anchorMax = new Vector2(0.5f, 0.5f);
        textRectTransform.pivot = new Vector2(0.5f, 0.5f);
        textRectTransform.sizeDelta = new Vector2(tabWidth, tabHeight);
        // Text position
        textRectTransform.anchoredPosition = new Vector2(0, 0);

        TextMeshProUGUI buttonText = tabText.AddComponent<TextMeshProUGUI>();
        buttonText.text = tabName;
        buttonText.font = UIManager.Instance.Font;
        buttonText.fontSize = 12;
        buttonText.color = Color.black;
        buttonText.alignment = TextAlignmentOptions.Center;
        buttonText.verticalAlignment = VerticalAlignmentOptions.Middle;
    }

    public virtual UISelectableEntry CreateSelectableEntry()
    {
        // Create a new entry object with content handle as parent
        GameObject go = Instantiate(Resources.Load<GameObject>("Prefabs/EmptyObject"), contentHandle);
        go.name = "UISelectableEntry";
        UISelectableEntry entry = go.AddComponent<UISelectableEntry>();
        entry.SetParent(this);
        // add to cleanup pool so we can clear later in clear dialog entries
        cleanupPool.Add(entry);
        return entry;
    }

    public void ClearDialogEntries()
    {
        if (cleanupPool == null)
            return;
        foreach (UISelectableEntry entry in cleanupPool)
        {
            GameObject.Destroy(entry.gameObject);
        }
        cleanupPool.Clear();
        if (entries != null)
            entries.Clear();
    }

    /// <summary>
    /// Clears, sets, and prints the dialog entries in the order they were added
    /// </summary>
    public virtual void SetDialogEntries(List<UISelectableEntry> entries)
    {
        this.entries = entries;
        // calculate total height of the content
        float heightHead = -1*GetTabHeight();
        int count = 0;
        foreach (UISelectableEntry entry in this.entries)
        {
            (heightHead, count) = RecursiveContentPrint(entry, 1, heightHead, count);
        }
        contentHandle.sizeDelta = new Vector2(contentHandle.sizeDelta.x, count * entryHeight + Mathf.Abs(heightHead));
    }


    public virtual void SetDialogEntries(UISelectableEntry entry)
    {
        SetDialogEntries(new List<UISelectableEntry>() { entry });
    }


    private (float, int) RecursiveContentPrint(UISelectableEntry entry, int depth, float heightHead, int count)
    {
        RectTransform rTransform = entry.GetComponent<RectTransform>();
        rTransform.anchorMin = new Vector2(0, 1);
        rTransform.anchorMax = new Vector2(1, 1);
        rTransform.pivot = new Vector2(0.5f, 1f);

        rTransform.anchoredPosition = new Vector2(0, heightHead); // positioning from top
        rTransform.sizeDelta = new Vector2(0, entryHeight);
        float padding = 5f;
        rTransform.SetRight(padding);
        rTransform.SetLeft(padding);
        // actually indent the text
        entry.GetTextTransform().anchoredPosition = new Vector2(entryIndentWidth * depth, 0);
        heightHead -= entryHeight;
        count++;
        // Print the children
        if (entry.GetChildEntries() != null)
        {
            foreach (UISelectableEntry child in entry.GetChildEntries())
            {
                (heightHead, count) = RecursiveContentPrint(child, depth + 1, heightHead, count);
            }
        }
        return (heightHead, count);
    }



    // Update is called once per frame
    void Update()
    {
        
    }
}