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

/// <summary>
/// Component which controls how a LogicElement is displayed in the UI;
/// </summary>
public class LogicElementUI : Dragable
{
    #region Inspector Fields
    [SerializeField]
    [Tooltip("Logic Block this will display")]
    protected LogicBlock LogicElement;
    #endregion Inspector Fields

    #region ReadOnly Variables
    /// <summary>
    /// RectTransform of LogicElementUI
    /// </summary>
    public RectTransform rectTransform { get { return transform as RectTransform; } }
    public LogicBlock logicElement { get { return LogicElement; } }
    #endregion ReadOnly Variables

    #region Private Variables
    //Text Mesh pro to display Name
    protected TextMeshProUGUI nameText;

    //background image to color;
    protected Image background;

    protected LogicElementHolder currentHolder;

    private List<LogicElementHolder> lastHover = new List<LogicElementHolder>();
    #endregion Private Variables


    #region Unity Functions
    private void Start()
    {
        UpdateUI();
    }
    #endregion Unity Functions

    #region Class Implementation
    /// <summary>
    /// Updates the UI to match the LogicElemnts name and color
    /// </summary>
    public virtual void UpdateUI()
    {
        //Make sure we have the UI components
        if (nameText == null)
            nameText = GetComponentInChildren<TextMeshProUGUI>();

        if (background == null)
            background = GetComponentInChildren<Image>();

        //Set UI
        if (LogicElement != null)
        {
            //If name null use file name
            nameText.text = LogicElement.DisplayName;
            background.color = LogicElement.Color;
        }
    }

    public virtual void Initialise(LogicBlock LogicElement, LogicElementHolder Holder,bool copy)
    {
        if (copy)
            this.LogicElement = LogicElement.Clone();
        else
            this.LogicElement = LogicElement;
        currentHolder = Holder;
    }
    #endregion Class Implementation


    #region Drag Implementation

    public override void OnBeginDrag(PointerEventData eventData)
    {
        base.OnBeginDrag(eventData);

        if (currentHolder != null)
            currentHolder.OnRemove(this);

    }

    public override void OnDrag(PointerEventData data)
    {
        base.OnDrag(data);

        //Get all overlapping holders
        List<LogicElementHolder> currentHover = LogicElementHolder.OverlappingElements(transform as RectTransform).ToList();

        DebugExtensions.DrawRect(rectTransform, Color.blue);

        LogicElementHolder.DebugDrawAll(Color.red);

        //Call OnHoverStart() for each holder which wasn't in the last update
        currentHover.Except(lastHover).ForEach(p => p.OnHoverStart(this));

        //Call OnHover() for each overlapping holder
        currentHover.ForEach(p => p.OnHover(this));

        //Call OnHoverEnd() for each element not overlapping but was last update
        lastHover.Except(currentHover).ForEach(p => p.OnHoverEnd(this));

        //Save all overlapping elements this update
        lastHover = currentHover;
    }

    public override void OnEndDrag(PointerEventData eventData)
    {
        base.OnEndDrag(eventData);

        //Call OnHoverStop to each element we are hovering over
        lastHover.ForEach(p => p.OnHoverEnd(this));


        //order the UIHolders by priority and get the first which will accept this
        lastHover = lastHover.OrderByDescending(p => p.Priority).ToList();
        
        lastHover.ForEach(p => Debug.Log(p.gameObject.name));
        LogicElementHolder holderToAdd = lastHover.FirstOrDefault(p => p.canHold(LogicElement));

        //If we are still hovering over anything add this to it
        //Else add it back to where it came from
        if (holderToAdd != default)
        {
            holderToAdd.OnAdd(this);
            currentHolder = holderToAdd;
        }
        else
            currentHolder.OnAdd(this);

    }

    protected override void OnDoubleClick()
    {
        base.OnDoubleClick();
        currentHolder.OnDoubleClick(this);
    }
    #endregion Drag Implementaion

}
