using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HeadLookController : MonoBehaviour {
  [Header("Bone assignments")]
  public Transform root;
  public Transform head;

  [Header("Settings")]
  public float angleLimit = 50f;
  public float rotationDamping = 3f;

  public Transform LookTarget { get; set; } = null;
  private Quaternion previous;

  private void Start() {
    previous = head.rotation;
  }

  private void LateUpdate() {
    var targetRotation = GetTargetRotation();

    // Slerp smoothly towards the goal rotation.
    var newRotation = Quaternion.Slerp(previous, targetRotation, Time.deltaTime * rotationDamping);
    previous = newRotation;
    head.rotation = previous = newRotation;
  }

  private Quaternion GetTargetRotation() {
    Quaternion defaultRotation = head.rotation;

    // If we aren't aware of any target, just look forward.
    if (LookTarget == null) {
      return defaultRotation;
    }

    // Get the desired look vector and the angle between our root forward.
    var rootForward = root.forward;
    var direction = LookTarget.position - head.position;
    float angle = Vector3.Angle(direction, rootForward);

    // Get the ideal rotation if the look was unconstrained.
    var fullRotation = Quaternion.LookRotation(direction, Vector3.up);

    // If the angle is greater than our limit, get a rotation that is in the
    // direction of fullRotation but is clamped to our limit.
    if (angle > angleLimit) {
      return Quaternion.Slerp(defaultRotation, fullRotation, angleLimit / angle);
    }
    return fullRotation;
  }
}
