using System;
using Unity.Behavior;
using UnityEngine;
using Action = Unity.Behavior.Action;
using Unity.Properties;

[Serializable, GeneratePropertyBag]
[NodeDescription(
    name: "Turn to Look At",
    description: "Rotates the Transform to look at the Target.",
    story: "[Transform] looks at [Target] at [RotatePerCircle]",
    category: "Action/Transform",
    id: "42801028b3ac405f8b279425f23a3092")]
internal partial class TurnToLookAtAction : Action
{
    [SerializeReference] public BlackboardVariable<Transform> Transform;
    [SerializeReference] public BlackboardVariable<Transform> Target;
    [Tooltip("The rotate speed perform per circle, multi by Time.deltaTime for turn per tick")]
    [SerializeReference] public BlackboardVariable<float> RotatePerCircle = new BlackboardVariable<float>(180f);
    [Tooltip("True: the node process the LookAt every update with status Running." +
        "\nFalse: the node process the LookAt only once. Keep circling around to complete the turn.")]
    [SerializeReference] public BlackboardVariable<bool> WaitForComplete = new BlackboardVariable<bool>(true);
    [SerializeReference] public BlackboardVariable<bool> LimitToYAxis = new BlackboardVariable<bool>(false);

    protected override Status OnStart()
    {
        if (Transform.Value == null || Target.Value == null)
        {
            LogFailure($"Missing Transform or Target.");
            return Status.Failure;
        }
        ProcessLookAt();
        return WaitForComplete.Value ? Status.Running : Status.Success;
    }

    protected override Status OnUpdate()
    {
        if (WaitForComplete.Value)
        {
            return ProcessLookAt();
        }
        return Status.Success;
    }

    Status ProcessLookAt()
    {
        Vector3 targetPosition = Target.Value.position;

        if (LimitToYAxis.Value)
        {
            targetPosition.y = Transform.Value.position.y;
        }

        Vector3 currentTransform = Transform.Value.position;
        Quaternion currentLook = Quaternion.LookRotation(LimitToYAxis.Value ? Vector3.Scale(Transform.Value.forward, new Vector3(1f, 0f, 1f)).normalized : Transform.Value.forward);

        Quaternion targetLook = Quaternion.LookRotation(targetPosition - currentTransform);

        Quaternion newRotation = Quaternion.RotateTowards(currentLook, targetLook, RotatePerCircle.Value * Time.deltaTime);

        if (Quaternion.Angle(newRotation, Transform.Value.rotation) > 1f)
        {
            Transform.Value.rotation = Quaternion.RotateTowards(currentLook, targetLook, RotatePerCircle.Value * Time.deltaTime);
            return Status.Running;
        }
        else
            return Status.Success;
    }
}
