using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
using UnityEngine;
public class StressReceiver : MonoBehaviour
{
  
    public float trauma;
    private float _trauma;
    private float _currMaxTrauma;
    private Vector3 _lastPosition;
    private float _size;
    private Vector3 _lastRotation;
    [Tooltip("Exponent for calculating the shake factor. Useful for creating different effect fade outs")]
    public float TraumaExponent = 1;
    [Tooltip("Maximum angle that the gameobject can shake. In euler angles.")]
    public Vector3 MaximumAngularShake = Vector3.one * 5;
    [Tooltip("Maximum translation that the gameobject can receive when applying the shake effect.")]
    public Vector3 MaximumTranslationShake = Vector3.one * .75f;
    private System.Action callBack;
    [ContextMenu("asdasda")]
    public void Test()
    {
        InduceStress(trauma,1,null);
    }
    private void Update()
    {
        float shake = Mathf.Pow(_trauma, TraumaExponent);
        shake /= _currMaxTrauma;
        // float shake = _trauma;
        /* Only apply this when there is active trauma */
        if(shake > 0.01f)
        {
            var previousRotation = _lastRotation;
            var previousPosition = _lastPosition;
            /* In order to avoid affecting the transform current position and rotation each frame we substract the previous translation and rotation */
            _lastPosition = new Vector3(
                MaximumTranslationShake.x * (Mathf.PerlinNoise(0, Time.time * 25) * 2 - 1),
                MaximumTranslationShake.y * (Mathf.PerlinNoise(1, Time.time * 25) * 2 - 1),
                MaximumTranslationShake.z * (Mathf.PerlinNoise(2, Time.time * 25) * 2 - 1)
            ) * shake*_size;
            _lastRotation = new Vector3(
                MaximumAngularShake.x * (Mathf.PerlinNoise(3, Time.time * 25) * 2 - 1),
                MaximumAngularShake.y * (Mathf.PerlinNoise(4, Time.time * 25) * 2 - 1),
                MaximumAngularShake.z * (Mathf.PerlinNoise(5, Time.time * 25) * 2 - 1)
            ) * shake*_size;
            transform.localPosition += _lastPosition - previousPosition;
            transform.localRotation = Quaternion.Euler(transform.localRotation.eulerAngles + _lastRotation - previousRotation);
            _trauma =_trauma - Time.deltaTime;
        }
        else
        {
            if (_lastPosition == Vector3.zero && _lastRotation == Vector3.zero)
            {
                callBack?.Invoke();
                return;
            }
           
            /* Clear the transform of any left over translation and rotations */
            transform.localPosition -= _lastPosition;
            transform.localRotation = Quaternion.Euler(transform.localRotation.eulerAngles - _lastRotation);
            _lastPosition = Vector3.zero;
            _lastRotation = Vector3.zero;
            callBack?.Invoke();
        }
    }
    /// 
    ///  Applies a stress value to the current object.
    /// 
    /// [0,1] Amount of stress to apply to the object
    public void InduceStress(float time,float size,System.Action callBack)
    {
        this._size = size;
        this.callBack = callBack;
        _trauma = time;
        _currMaxTrauma=time;
    }
}