//Created by Neodrop
//neodrop@unity3d.ru
using System.Reflection;
using UnityEngine;
using System.Collections;
//#pragma warning disable

public class AntaresInterpolator : MonoBehaviour {

    public Component target;
    public AnimationClip sourceClip;
    public AnimationCurve curve;
    public string fieldName;
    public float interpolationValue;
    private bool _evaluateAutomatically = false;
    private float _currentTime = 1000123, _currentTimeLast = 0;

    void Awake()
    {
        if (target == null)
        {
            Debug.Log("Interpolator has no target!");
            return;
        }
        RegisterInterpolator();
    }

    /// <summary>
    /// Reset Interpolator and stop Auto interpolation
    /// </summary>
    public void Reset()
    {
        if (Application.isPlaying)
        {
            ResetRuntime();
            return;
        }
        target = null;
        sourceClip = null;
        curve = null;
        fieldName = null;
    }

    private void ResetRuntime()
    {
        StopAllCoroutines();
        _evaluateAutomatically = false;
        _currentTime = 1000123;
    }

    /// <summary>
    /// Get interpolated value
    /// </summary>
    /// <param name="time">Time in range from 0 to last curve key time</param>
    /// <returns>interpolated float value</returns>
    public float Evaluate(float time)
    {
        if (curve == null) return 0;
        if (_currentTime != 1000123) _currentTimeLast = _currentTime;
        return curve.Evaluate(time);
    }

    /// <summary>
    /// Get interpolated value automatically
    /// </summary>
    /// <returns>interpolated float value</returns>
    public float EvaluateAutomatically()
    {
        if (curve == null) return 0;
        if (!_evaluateAutomatically && _currentTime > 0) StartCoroutine(WorkAuto());
        return Evaluate(_currentTime);
    }

    public float GetCurrentTimeForEditor()
    {
        return _currentTimeLast;
    }

    IEnumerator WorkAuto()
    {
        _evaluateAutomatically = true;
        _currentTime = 0;
        float finishTime = Time.realtimeSinceStartup + curve.keys[curve.keys.Length - 1].time;
        while (Time.realtimeSinceStartup <= finishTime)
        {
            yield return null;
            _currentTime += Time.deltaTime;
        }
        _evaluateAutomatically = false;
    }

    void RegisterInterpolator()
    {
        FieldInfo f = target.GetType().GetField(fieldName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
        if (f == null) return;
        f.SetValue(target, this);
    }
}
