using Pursuit.Util;
using UnityEngine;

namespace Pursuit.HUD
{
    public class OnScreenIndicator : MonoBehaviour
    {
        private Transform target;

        public void Attach(Transform target)
        {
            this.target = target;
        }

        public virtual void Tick()
        {
            Camera cam = Camera.main;

            if (!cam) return;

            Vector3 forward = cam.transform.forward;
            Vector3 dir = target.position - cam.transform.position;
            dir = dir.normalized;

            forward = Vector3.ProjectOnPlane(forward, cam.transform.up);
            dir = Vector3.ProjectOnPlane(dir, cam.transform.up);

            float rawAngle = Vector3.Angle(dir, forward);
            float angle = Vector3.SignedAngle(dir, forward, cam.transform.up);

            float theta = -Mathf.PI / 2 + Mathf.Deg2Rad * angle;

            theta = Mathf.Repeat(theta, Mathf.PI * 2) - Mathf.PI;

            transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);

            Vector3 onScreenPosition = cam.WorldToScreenPoint(target.position);

            onScreenPosition -= transform.up * 100;

            if (onScreenPosition.x < 0 || onScreenPosition.x > Screen.width || onScreenPosition.y < 0 ||
                onScreenPosition.y > Screen.height)
            {
                float rectAngle = -Mathf.Atan2(onScreenPosition.y - Screen.height / 2f,
                    onScreenPosition.x - Screen.width / 2f);
                rectAngle += Mathf.PI;
                onScreenPosition = MathUtil.AngleOnRectangle(rectAngle, new Vector2(Screen.width, Screen.height));
            }

            Vector2 edgePoint = MathUtil.AngleOnEllipse(theta, new Vector2(Screen.width, Screen.height));
            edgePoint += new Vector2(Screen.width / 2f, Screen.height / 2f);
            edgePoint = Vector2.MoveTowards(edgePoint, new Vector2(Screen.width / 2f, Screen.height / 2f), 50);

            float t = Mathf.InverseLerp(75, 85, rawAngle);
            Vector3 finalPosition = Vector3.Lerp(onScreenPosition, edgePoint, t);

            transform.position = finalPosition;
        }
    }
}