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

public class UIUpdater : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        if (UsernameLabel != null)
        {
            UsernameLabel.text = PlayerStats.Username;
        }
    }

    public Canvas UICanvas = null;
    public GameObject TargetReticule = null;
    public GameObject BarkskinActiveIndicator = null;
    public TextMeshProUGUI UsernameLabel = null;

    private void PositionUIObjectOnWorldObject(GameObject uiObject, GameObject worldObject, string hardpointName)
    {
        Transform hardpoint = worldObject.transform.Find(hardpointName);

        //first you need the RectTransform component of your canvas
        RectTransform CanvasRect = UICanvas.GetComponent<RectTransform>();

        //then you calculate the position of the UI element
        //0,0 for the canvas is at the center of the screen, whereas WorldToViewPortPoint treats the lower left corner as 0,0. Because of this, you need to subtract the height / width of the canvas * 0.5 to get the correct position.

        Vector2 ViewportPosition = Camera.main.WorldToViewportPoint(hardpoint.position);
        Vector2 WorldObject_ScreenPosition = new Vector2(
        ((ViewportPosition.x * CanvasRect.sizeDelta.x) - (CanvasRect.sizeDelta.x * 0.5f)),
        ((ViewportPosition.y * CanvasRect.sizeDelta.y) - (CanvasRect.sizeDelta.y * 0.5f)));

        //now you can set the position of the ui element
        uiObject.GetComponent<RectTransform>().anchoredPosition = WorldObject_ScreenPosition;
    }

    // Update is called once per frame
    void Update()
    {
        CardInstance[] cardInstances = FindObjectsOfType<CardInstance>();
        foreach(CardInstance ci in cardInstances)
        {
            if (ci.Dirty)
            {
                // Update all the attached UI objects
                Transform t = ci.transform;
                t.Find("CardName").GetComponent<TextMeshPro>().text = ci.CardTemplate.CardName;
                t.Find("CardText").GetComponent<TextMeshPro>().text = ci.CardTemplate.CardText;
                t.Find("CardImage").GetComponent<MeshRenderer>().material = Resources.Load<Material>(ci.CardTemplate.CardImage);
                t.Find("EnergyImage1").GetComponent<MeshRenderer>().enabled = ci.CardTemplate.ManaCost >= 1;
                t.Find("EnergyImage2").GetComponent<MeshRenderer>().enabled = ci.CardTemplate.ManaCost >= 2;
                t.Find("EnergyImage3").GetComponent<MeshRenderer>().enabled = ci.CardTemplate.ManaCost >= 3;
                t.Find("EnergyImage4").GetComponent<MeshRenderer>().enabled = ci.CardTemplate.ManaCost >= 4;
                t.Find("EnergyImage5").GetComponent<MeshRenderer>().enabled = ci.CardTemplate.ManaCost >= 5;

                ci.Dirty = false;
            }


            // Check if we need to move towards our target world position
            Vector3 toVector = ci.TargetWorldPosition - ci.transform.position;
            if (toVector.sqrMagnitude > Mathf.Epsilon)
            {
                if (toVector.magnitude < ci.CardVelocity * Time.deltaTime)
                {
                    // Teleport to destination
                    ci.transform.position = ci.TargetWorldPosition;
                }
                else
                {
                    toVector.Normalize();
                    ci.transform.position += toVector * ci.CardVelocity * Time.deltaTime;
                }
            }

            // Check if we need to do any rotation
            float angleDiff = Quaternion.Angle(ci.TargetRotation, ci.transform.rotation);

            if (angleDiff > Mathf.Epsilon)
            {
                ci.transform.rotation = Quaternion.RotateTowards(ci.transform.rotation, ci.TargetRotation, ci.MaxRotation * Time.deltaTime);
            }


            if (ci.BeingHovered)
                ci.gameObject.transform.localScale = new Vector3(1.0f, 1.0f, 1.0f);
            else
                ci.gameObject.transform.localScale = Vector3.one;
        }



        // Healthbars
        HealthbarBinding[] healthBindings = FindObjectsOfType<HealthbarBinding>();
        
        foreach (HealthbarBinding hb in healthBindings)
        {
            if (hb.Target.Health < Mathf.Epsilon)
            {
                Object.Destroy(hb.gameObject);
            }

            // Update the value on the healthbar binding
            if (hb.FirstTime)
            {
                hb.FirstTime = false;
                hb.GetComponent<Slider>().value = hb.Target.Health / hb.Target.MaxHealth; ;
            }
            else
            {
                float current = hb.GetComponent<Slider>().value;
                float target = (float)hb.Target.Health / (float)hb.Target.MaxHealth;

                float Percentage = Mathf.Min(1.0f, Time.deltaTime / 0.3f);

                if (Mathf.Abs(current - target) < 0.001f)
                {
                    hb.GetComponent<Slider>().value = target;
                }
                else
                {
                    float delta = target - current;
                    float movement = delta * Percentage;
                    hb.GetComponent<Slider>().value = current + movement;
                }
            }

            hb.HealthText.text = hb.Target.Health.ToString("0") + " / " + hb.Target.MaxHealth.ToString("0");

            // Set the position of the healthbar
            if (hb.MovePositionToBoundTarget)
                PositionUIObjectOnWorldObject(hb.gameObject, hb.Target.gameObject, "HP_Healthbar");
        }

        // Energy bars
        // EnergyBindings
        EnergyBinding[] EnergyBindings = FindObjectsOfType<EnergyBinding>();

        foreach (EnergyBinding eb in EnergyBindings)
        {
            // Update the value on the energybar binding
            if (eb.FirstTime)
            {
                eb.FirstTime = false;
                eb.GetComponent<Slider>().value = (float)eb.EnergyTarget.Energy / (float)eb.EnergyTarget.MaxEnergy;
            }
            else
            {
                float current = eb.GetComponent<Slider>().value;
                float target = (float)eb.EnergyTarget.Energy / (float)eb.EnergyTarget.MaxEnergy;

                float Percentage = Mathf.Min(1.0f, Time.deltaTime / 0.3f);

                if (Mathf.Abs(current-target) < 0.001f)
                {
                    eb.GetComponent<Slider>().value = target;
                }
                else
                {
                    float delta = target - current;
                    float movement = delta * Percentage;
                    eb.GetComponent<Slider>().value = current + movement;
                }
            }



            // Update the text
            eb.EnergyText.text = eb.EnergyTarget.Energy.ToString("0") + " / " + eb.EnergyTarget.MaxEnergy.ToString("0");
        }

        // Swing Timers
        SwingTimerBinding[] swingBindings = FindObjectsOfType<SwingTimerBinding>();
        foreach(SwingTimerBinding stb in swingBindings)
        {

            PositionUIObjectOnWorldObject(stb.gameObject, stb.SwingTimer.gameObject, "HP_SwingTimer");

            if (stb.SwingTimer.DirtyUI == true)
            {
                stb.SwingText.text = stb.SwingTimer.TurnsRemaining.ToString();
                stb.GetComponent<Animator>().SetTrigger("Pulse");


                stb.SwingTimer.DirtyUI = false;
            }

        }

        // Update the Target Reticule on the GodHand
        if (TargetReticule != null)
        {
            if (GetComponent<GodHand>().GetCurrentTarget() == null)
                TargetReticule.GetComponent<Image>().enabled = false;
            else
            {
                TargetReticule.GetComponent<Image>().enabled = true;
                PositionUIObjectOnWorldObject(TargetReticule, GetComponent<GodHand>().GetCurrentTarget().gameObject, "HP_Reticule");
            }
        }

        if (BarkskinActiveIndicator != null)
        {
            BarkskinActiveIndicator.GetComponent<Image>().enabled = GetComponent<Choreographer>().PlayerEntity.GetComponent<HealthComponent>().BarkskinActive;
        }
    }
}
