using UnityEngine;

namespace ImpactCFX.Wwise
{
    public class WwiseAudioEffectProxy : PooledEffectObjectBase
    {
        private uint playingID;

        private float targetIntensity;
        private float currentIntensity;

        private CollisionResultData collisionResultData;

        public float AudioFadeOutTime = 0.2f;

        public void PlayWwiseAudioEffect(WwiseAudioEffectResult wwiseAudioEffectResult, CollisionResultData collisionResultData)
        {
            clearPlayingInstance();

            this.collisionResultData = collisionResultData;

            transform.position = collisionResultData.Point;
            currentIntensity = targetIntensity = wwiseAudioEffectResult.NormalizedIntensity;

            playingID = AkSoundEngine.PostEvent(wwiseAudioEffectResult.WwiseEventID, gameObject, (uint)AkCallbackType.AK_EndOfEvent, eventEndCallback, null);

            AkSoundEngine.SetRTPCValueByPlayingID(ImpactWwiseRTPCs.Intensity, wwiseAudioEffectResult.NormalizedIntensity, playingID);
            AkSoundEngine.SetRTPCValueByPlayingID(ImpactWwiseRTPCs.RawIntensity, wwiseAudioEffectResult.RawIntensity, playingID);
            AkSoundEngine.SetRTPCValueByPlayingID(ImpactWwiseRTPCs.CompositionValue, collisionResultData.MaterialComposition, playingID);
            AkSoundEngine.SetRTPCValueByPlayingID(ImpactWwiseRTPCs.CollisionType, (int)collisionResultData.CollisionType, playingID);

            if (collisionResultData.CollisionType == CollisionType.Collision)
                attach(collisionResultData);

            NeedsUpdate = true;
        }

        private void eventEndCallback(object in_cookie, AkCallbackType callType, object in_info)
        {
            ReturnToPool();
        }

        public void UpdateWwiseAudioEffectCollision(WwiseAudioEffectResult wwiseAudioEffectResult, CollisionResultData collisionResultData)
        {
            this.collisionResultData = collisionResultData;

            if (!isPlaying())
            {
                PlayWwiseAudioEffect(wwiseAudioEffectResult, collisionResultData);
            }

            currentIntensity = targetIntensity = wwiseAudioEffectResult.NormalizedIntensity;

            transform.position = collisionResultData.Point;

            AkSoundEngine.SetRTPCValueByPlayingID(ImpactWwiseRTPCs.RawIntensity, wwiseAudioEffectResult.RawIntensity, playingID);
            AkSoundEngine.SetRTPCValueByPlayingID(ImpactWwiseRTPCs.CompositionValue, collisionResultData.MaterialComposition, playingID);
        }

        public override void UpdatePooledObject()
        {
            if (collisionResultData.CollisionType != CollisionType.Collision)
            {
                currentIntensity = Mathf.MoveTowards(currentIntensity, targetIntensity, Time.deltaTime / AudioFadeOutTime);
                AkSoundEngine.SetRTPCValueByPlayingID(ImpactWwiseRTPCs.Intensity, currentIntensity, playingID);

                if (currentIntensity == 0)
                {
                    ReturnToPool();
                }

                targetIntensity = 0;
            }
        }

        public override void ReturnToPool()
        {
            clearPlayingInstance();

            base.ReturnToPool();
        }

        private void OnDestroy()
        {
            clearPlayingInstance();
        }

        private void clearPlayingInstance()
        {
            if (playingID != AkSoundEngine.AK_INVALID_PLAYING_ID)
                AkSoundEngine.StopPlayingID(playingID, 0);

            playingID = AkSoundEngine.AK_INVALID_PLAYING_ID;
        }

        private bool isPlaying()
        {
            return playingID != AkSoundEngine.AK_INVALID_PLAYING_ID;
        }
    }
}

