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

public class TargetUIController : MonoBehaviour
{
    // Controller to control the UI of the target,
    // select target type, select prefeb to set or sth.

    [SerializeField] private GameObject targetControllerObj;
    [SerializeField] private GameObject mouseSelectorObj;
    [SerializeField] private GameObject environmentUIObj;

    [SerializeField] private float levelButtonHeight = 30;

    [Header("PrimaryButton")]
    [SerializeField] private Button clearGameButton;

    [SerializeField] private Button setEnemyButton;
    [SerializeField] private Button setAttackButton;
    [SerializeField] private Button setGotoButton;
    [SerializeField] private Button setFreeButton;
    [SerializeField] private Button setStayButton;

    [Header("LevelPanel")]
    [SerializeField] private GameObject gotoLevelPanel;

    [SerializeField] private GameObject attackLevelPanel;
    [SerializeField] private float levelPanelAnimeTime = 0.2f;

    private MouseInMap mouseInMapCon;
    private EnvironmentUIControl envUICon;
    private TargetController targetCon;
    private MessageBoxController messageBoxController;
    private ButtonActivateColorChanger buttonColorChanger;

    public enum PrimaryButtonType
    { Goto, Attack, Free }

    public delegate void PointerInOutUIEventDelegate(Button button, GameObject panel, BaseEventData eventData);

    private void Start()
    {
        targetCon = targetControllerObj.GetComponent<TargetController>();
        mouseInMapCon = mouseSelectorObj.GetComponent<MouseInMap>();
        envUICon = environmentUIObj.GetComponent<EnvironmentUIControl>();
        messageBoxController = GetComponent<MessageBoxController>();
        buttonColorChanger = GetComponent<ButtonActivateColorChanger>();

        gotoLevelPanel.GetComponent<LevelPanel>().InitLevelPanel(
            targetCon.gotoLevelNum,
            setGotoButton,
            levelButtonHeight);
        attackLevelPanel.GetComponent<LevelPanel>().InitLevelPanel(
            targetCon.attackLevelNum,
            setAttackButton,
            levelButtonHeight);
        AddLevelButtonToColorChanger(gotoLevelPanel);
        AddLevelButtonToColorChanger(attackLevelPanel);
        AddPointerEnterButtonTrigger(setGotoButton, gotoLevelPanel, PointerEnterButtonAction);
        AddPointerEnterButtonTrigger(setAttackButton, attackLevelPanel, PointerEnterButtonAction);
        AddPointerExitButtonTrigger(setGotoButton, gotoLevelPanel, PointerExitButtonAction);
        AddPointerExitButtonTrigger(setAttackButton, attackLevelPanel, PointerExitButtonAction);
        AddPointerExitLevelPanelTrigger(setGotoButton, gotoLevelPanel, PointerExitLevelPanelAction);
        AddPointerExitLevelPanelTrigger(setAttackButton, attackLevelPanel, PointerExitLevelPanelAction);
        buttonColorChanger.InitializeAllButtonColor();
        ClearGamePressed();
    }

    public void LevelButtonPressed(PrimaryButtonType primaryButtonType, int level = 0)
    {
        switch (primaryButtonType)
        {
            case PrimaryButtonType.Goto:
                SetGotoPressed(level);
                break;

            case PrimaryButtonType.Attack:
                SetAttackPressed(level);
                break;

            default:
                messageBoxController.PushMessage(new List<string> { "TargetUIController.LevelButtonPressed:", "Button Type Wrong, not level included button" },
                    new List<string> { messageBoxController.errorColor });
                break;
        }
    }

    // Clear Game Button Pressed, delete all enemies and targets
    public void ClearGamePressed()
    {
        // Clear all enemies and targets. set gamemode to Stay mode
        targetCon.PlayTargetChange(Targets.Stay);
        mouseInMapCon.ChangeMouseMode(MouseInMap.MouseMode.Default);
        // disable setStayButton and enable other buttons
        buttonColorChanger.ChangeInteractableColor(clearGameButton, true);
        buttonColorChanger.ChangeInteractableColor(setEnemyButton, true);
        buttonColorChanger.ChangeInteractableColor(setAttackButton, true);
        buttonColorChanger.ChangeInteractableColor(setGotoButton, true);
        buttonColorChanger.ChangeInteractableColor(setFreeButton, true);
        buttonColorChanger.ChangeInteractableColor(setStayButton, false);
        targetCon.PlayModeInitialize();
    }

    // Set Free Button Pressed, change Target mode to free mode
    public void SetFreePressed()
    {
        mouseInMapCon.ChangeMouseMode(MouseInMap.MouseMode.Default);
        targetCon.PlayTargetChange(Targets.Free);
        buttonColorChanger.ChangeInteractableColor(setStayButton, true);
        buttonColorChanger.ChangeInteractableColor(setAttackButton, true);
        buttonColorChanger.ChangeInteractableColor(setGotoButton, true);
        buttonColorChanger.ChangeInteractableColor(setFreeButton, false);
    }

    // Set Stay Button Pressed, change Target mode to stay mode
    public void SetStayPressed()
    {
        mouseInMapCon.ChangeMouseMode(MouseInMap.MouseMode.Default);
        targetCon.PlayTargetChange(Targets.Stay);
        buttonColorChanger.ChangeInteractableColor(setStayButton, false);
        buttonColorChanger.ChangeInteractableColor(setAttackButton, true);
        buttonColorChanger.ChangeInteractableColor(setGotoButton, true);
        buttonColorChanger.ChangeInteractableColor(setFreeButton, true);
    }

    // Set Enemy Button Pressed, change mouse mode to EnemySetMode
    public void SetEnemyPressed()
    {
        mouseInMapCon.ChangeMouseMode(MouseInMap.MouseMode.EnemySet);
    }

    // Set Goto Button Pressed, change mouse mode to GotoSetMode
    private void SetGotoPressed(int level)
    {
        mouseInMapCon.ChangeMouseMode(MouseInMap.MouseMode.GotoSet, level);
        buttonColorChanger.ChangeInteractableColor(clearGameButton, true);
        buttonColorChanger.ChangeInteractableColor(setEnemyButton, true);
        buttonColorChanger.ChangeInteractableColor(setStayButton, true);
        buttonColorChanger.ChangeInteractableColor(setAttackButton, true);
        buttonColorChanger.ChangeInteractableColor(setGotoButton, true);
        buttonColorChanger.ChangeInteractableColor(setFreeButton, true);
    }

    // Set Attack Button Pressed, change mouse mode to AttackSetMode
    private void SetAttackPressed(int level)
    {
        mouseInMapCon.ChangeMouseMode(MouseInMap.MouseMode.AttackSet, level);
        buttonColorChanger.ChangeInteractableColor(clearGameButton, true);
        buttonColorChanger.ChangeInteractableColor(setEnemyButton, true);
        buttonColorChanger.ChangeInteractableColor(setStayButton, true);
        buttonColorChanger.ChangeInteractableColor(setAttackButton, true);
        buttonColorChanger.ChangeInteractableColor(setGotoButton, true);
        buttonColorChanger.ChangeInteractableColor(setFreeButton, true);
    }

    /// <summary>
    /// Adds level buttons from a level panel to the color changer, making them got interactable color.
    /// </summary>
    /// <param name="levelPanel">The level panel object containing the level buttons.</param>
    private void AddLevelButtonToColorChanger(GameObject levelPanel)
    {
        foreach (Button btn in levelPanel.GetComponent<LevelPanel>().LevelButtonList)
        {
            buttonColorChanger.AddButtonToColorChangerButtonList(btn, true);
        }
    }

    /// <summary>
    /// sign up pointer enter event for button
    /// </summary>
    /// <param name="triggerButton">target button</param>
    /// <param name="panel">target panel</param>
    /// <param name="inAction">enter event trigered action</param>
    private void AddPointerEnterButtonTrigger(Button triggerButton, GameObject panel, PointerInOutUIEventDelegate inAction)
    {
        EventTrigger.Entry inEntry = new EventTrigger.Entry();
        inEntry.eventID = EventTriggerType.PointerEnter;
        inEntry.callback.AddListener((eventData) => inAction(triggerButton, panel, eventData));
        triggerButton.GetComponent<EventTrigger>().triggers.Add(inEntry);
    }

    /// <summary>
    /// sign up pointer exit event for button
    /// </summary>
    /// <param name="triggerButton">target button</param>
    /// <param name="panel">target panel</param>
    /// <param name="inAction">exit event trigered action</param>
    private void AddPointerExitButtonTrigger(Button triggerButton, GameObject panel, PointerInOutUIEventDelegate outAction)
    {
        EventTrigger.Entry outEntry = new EventTrigger.Entry();
        outEntry.eventID = EventTriggerType.PointerExit;
        outEntry.callback.AddListener((eventData) => outAction(triggerButton, panel, eventData));
        triggerButton.GetComponent<EventTrigger>().triggers.Add(outEntry);
    }

    /// <summary>
    /// sign up pointer exit event for panel
    /// </summary>
    /// <param name="triggerButton">target button</param>
    /// <param name="panel">target panel</param>
    /// <param name="inAction">exit event trigered action</param>
    private void AddPointerExitLevelPanelTrigger(Button triggerButton, GameObject panel, PointerInOutUIEventDelegate outAction)
    {
        EventTrigger.Entry entry = new EventTrigger.Entry();
        entry.eventID = EventTriggerType.PointerExit;
        entry.callback.AddListener((eventData) => outAction(triggerButton, panel, eventData));
        panel.GetComponent<EventTrigger>().triggers.Add(entry);
    }

    /// <summary>
    /// pointer enter event action for button
    /// </summary>
    /// <param name="button">target button</param>
    /// <param name="panel">target panel</param>
    /// <param name="baseEventData">EventTrigger Parameter</param>
    private void PointerEnterButtonAction(Button button, GameObject panel, BaseEventData baseEventData)
    {
        panel.GetComponent<LevelPanel>().ExpandLevelPanel(levelPanelAnimeTime);
    }

    /// <summary>
    /// pointer exit event action for button
    /// </summary>
    /// <param name="button">target button</param>
    /// <param name="panel">target panel</param>
    /// <param name="baseEventData">EventTrigger Parameter</param>
    private void PointerExitButtonAction(Button button, GameObject panel, BaseEventData baseEventData)
    {
        bool pointerInPanel = RectTransformUtility.RectangleContainsScreenPoint(panel.GetComponent<RectTransform>(), Input.mousePosition);
        if (!pointerInPanel)
        {
            panel.GetComponent<LevelPanel>().FoldLevelPanel(levelPanelAnimeTime);
        }
    }

    /// <summary>
    /// pointer enter event action for level panel
    /// </summary>
    /// <param name="button">target button</param>
    /// <param name="panel">target panel</param>
    /// <param name="baseEventData">EventTrigger Parameter</param>
    private void PointerExitLevelPanelAction(Button button, GameObject panel, BaseEventData baseEventData)
    {
        bool pointerInButton = RectTransformUtility.RectangleContainsScreenPoint(button.GetComponent<RectTransform>(), Input.mousePosition);
        if (!pointerInButton)
        {
            panel.GetComponent<LevelPanel>().FoldLevelPanel(levelPanelAnimeTime);
        }
    }
}