﻿using Impact.Interactions;
using Impact.Objects;
using UnityEngine;
using Impact.Utility.ObjectPool;

namespace Impact.Integration.MasterAudio
{
    /// <summary>
    /// The result of an  MasterAudio interaction.
    /// Handles collision, sliding, and rolling sounds.
    /// </summary>
    public class MasterAudioInteractionResult : IContinuousInteractionResult, IPoolable
    {
        /// <summary>
        /// The original interaction data this result was created from.
        /// </summary>
        public InteractionData OriginalData { get; set; }

        /// <summary>
        /// The result key for updating sliding and rolling.
        /// </summary>
        public long Key { get; set; }

        /// <summary>
        /// The MasterAudio sound group this result uses.
        /// </summary>
        public string SoundGroup;

        /// <summary>
        /// The value to scale the volume by based on the intensity of the interaction.
        /// </summary>
        public float VolumeScale;

        /// <summary>
        /// The audio pitch.
        /// </summary>
        public float Pitch;

        /// <summary>
        /// The interaction that created this result.
        /// Used to update the result for sliding and rolling.
        /// </summary>
        public MasterAudioInteraction Interaction;

        /// <summary>
        /// Is the intensity non-zero and is the sound group defined?
        /// </summary>
        public bool IsValid
        {
            get { return VolumeScale > 0 && !string.IsNullOrEmpty(SoundGroup); }
        }

        /// <summary>
        /// Is the audio still playing?
        /// </summary>
        public bool IsAlive
        {
            get { return currentVolumeScale > 0 || targetVolumeScale > 0; }
        }

        private IImpactObject parent;

        private float targetVolumeScale, currentVolumeScale;
        private float targetPitch, currentPitch;

        private DarkTonic.MasterAudio.PlaySoundResult playSoundResult;

        private bool isAvailable = true;

        /// <summary>
        /// Play audio using our data.
        /// </summary>
        /// <param name="parent">The Impact Object that created this result.</param>
        public void Process(IImpactObject parent)
        {
            this.parent = parent;

            targetVolumeScale = currentVolumeScale = VolumeScale;
            targetPitch = currentPitch = Pitch;

            //Dispose immediately for Collision interaction types
            if (OriginalData.InteractionType == InteractionData.InteractionTypeCollision)
            {
                DarkTonic.MasterAudio.MasterAudio.PlaySound3DAtVector3AndForget(SoundGroup, OriginalData.Point, VolumeScale, Pitch);
                Dispose();
            }
            else
            {
                playSoundResult = DarkTonic.MasterAudio.MasterAudio.PlaySound3DAtVector3(SoundGroup, OriginalData.Point, VolumeScale, Pitch);

                if (playSoundResult != null && playSoundResult.ActingVariation == null)
                    Dispose();
            }
        }

        /// <summary>
        /// Update the parameters for sliding and rolling and update position.
        /// </summary>
        public void FixedUpdate()
        {
            currentVolumeScale = Mathf.MoveTowards(currentVolumeScale, targetVolumeScale, 0.1f);

            float newPitch = Mathf.MoveTowards(currentPitch, targetPitch, 0.1f);
            float pitchDiff = newPitch - currentPitch;
            currentPitch = newPitch;

            if (playSoundResult != null && playSoundResult.ActingVariation != null)
            {
                playSoundResult.ActingVariation.AdjustVolume(currentVolumeScale);
                playSoundResult.ActingVariation.GlideByPitch(pitchDiff, 0f);
            }

            targetVolumeScale = 0;
        }

        /// <summary>
        /// Updates this result to adjust the parameters.
        /// </summary>
        /// <param name="newResult">The new interaction result with updated data.</param>
        public void KeepAlive(IInteractionResult newResult)
        {
            MasterAudioInteractionResult r = newResult as MasterAudioInteractionResult;

            targetVolumeScale = r.VolumeScale;
            targetPitch = Interaction.UpdatePitch(Pitch, r.OriginalData.Velocity);

            if (playSoundResult != null && playSoundResult.ActingVariation != null)
                playSoundResult.ActingVariation.Trans.position = r.OriginalData.Point;
        }

        /// <summary>
        /// Stop the play result.
        /// </summary>
        public void Dispose()
        {
            parent = null;

            if (playSoundResult != null && playSoundResult.ActingVariation != null)
                playSoundResult.ActingVariation.Stop();

            playSoundResult = null;
            MakeAvailable();
        }

        public void Retrieve()
        {
            isAvailable = false;
        }

        public void MakeAvailable()
        {
            isAvailable = true;
        }

        public bool IsAvailable()
        {
            return isAvailable;
        }
    }
}