using System;
using UnityEngine;

public class CrossHair : MonoBehaviour
{
    /// <summary>
    /// 瞄准器，基于其位置发射射线，射线的hitpoint转屏幕坐标，该坐标即准心坐标
    /// </summary>
    public Transform aimTransform;
    /// <summary>
    /// 是否限制瞄准器在屏幕范围内
    /// </summary>
    public bool limitAimInScrren;

    private RectTransform _rectTransform;
    private RectTransform _canvasRectTransform;

    void Awake()
    {
        _rectTransform = GetComponent<RectTransform>();
        _canvasRectTransform = GetComponentInParent<Canvas>().GetComponent<RectTransform>();
    }

    void Start()
    {
        InitForLimitBound();
    }

    void LateUpdate()
    {
        if (limitAimInScrren) aimTransform.eulerAngles = LimitAngles(aimTransform.eulerAngles);
        UpdateCrossHairPosition();
    }

    void UpdateCrossHairPosition()
    {
        Ray ray = new Ray(aimTransform.position, aimTransform.forward);
        RaycastHit hitInfo;
        Vector3 hitPoint;
        if (Physics.Raycast(ray, out hitInfo, 100)) hitPoint = hitInfo.point;
        else hitPoint = aimTransform.position + aimTransform.forward * 100f;
        Vector2 viewPoint = Camera.main.WorldToViewportPoint(hitPoint);
        _rectTransform.localPosition = (viewPoint - Vector2.one * 0.5f) * _canvasRectTransform.rect.size;
    }

    #region 限制其显示范围不超出屏幕
    private float _screenWidthHalf;
    private float _screenHeightHalf;
    private float _screenNormal;
    private float _rangeRotateY;
    private float _rangeRotateX;
    /// <summary>
    /// 标记是否出界（-1：未出界；0：左边出界；1：右边出界；2：上边出界；3：下边出界；）
    /// </summary>
    [NonSerialized] public int outBoundIndex = -1;
    void InitForLimitBound()
    {
        Camera camera = Camera.main;
        _rangeRotateX = camera.fieldOfView / 2;
        _screenWidthHalf = Screen.width / 2f;
        _screenHeightHalf = Screen.height / 2f;
        _screenNormal = _screenHeightHalf / Mathf.Tan(_rangeRotateX / 180f * Mathf.PI);
        _rangeRotateY = Mathf.Atan(_screenWidthHalf / _screenNormal) / Mathf.PI * 180f;
    }
    Vector3 LimitAngles(Vector3 angles)
    {
        //Unity默认范围（0，360）格式化为自定义范围（-180，180）
        angles.y = angles.y > 180 ? angles.y - 360 : angles.y;
        angles.x = angles.x > 180 ? angles.x - 360 : angles.x;
        //记录原来的角度
        float angleY = angles.y;
        float angleX = angles.x;
        //记录是否出界
        if (angleY < -_rangeRotateY) outBoundIndex = 0;
        else if (angleY > _rangeRotateY) outBoundIndex = 1;
        else if (angleX < -_rangeRotateX) outBoundIndex = 2;
        else if (angleX > _rangeRotateX) outBoundIndex = 3;
        else outBoundIndex = -1;
        //返回限制边界后的角度
        angles.y = Mathf.Clamp(angleY, -_rangeRotateY, _rangeRotateY);
        float rayLen = _screenNormal / Mathf.Cos(Mathf.Abs(angles.y) / 180 * Mathf.PI);
        float maxRangeRotateX = Mathf.Atan(_screenHeightHalf / rayLen) / Mathf.PI * 180f;
        if (Mathf.Abs(angleX) > Mathf.Abs(maxRangeRotateX)) angles.x = maxRangeRotateX * (angleX > 0 ? 1 : -1);
        return angles;
    }
    #endregion
}
