﻿using FMODUnity;
using Impact.Interactions;
using Impact.Utility;
using UnityEngine;

namespace Impact.Integration.FMOD

{    /// <summary>
     /// Interaction for playing audio with FMOD.
     /// </summary>
    [CreateAssetMenu(fileName = "New FMOD Audio Interaction", menuName = "Impact/FMOD/FMOD Audio Interaction", order = 0)]
    public class FMODAudioInteraction : ImpactInteractionBase
    {
        private const string interactionResultPoolKey = "FMODAudioInteractionResult";

        [SerializeField]
        private EventReference _collisionEvent;
        [SerializeField]
        private EventReference _slideEvent;
        [SerializeField]
        private EventReference _rollEvent;

        [SerializeField]
        private Range _velocityRange = new Range(2, 9);
        [SerializeField]
        private float _collisionNormalInfluence = 1;

        /// <summary>
        /// TheFMOD event to use for collisions.
        /// </summary>
        public EventReference CollisionEvent
        {
            get { return _collisionEvent; }
            set { _collisionEvent = value; }
        }

        /// <summary>
        /// The FMOD event to use for sliding.
        /// </summary>
        public EventReference SlideEvent
        {
            get { return _slideEvent; }
            set { _slideEvent = value; }
        }

        /// <summary>
        /// The FMOD event to use for rolling.
        /// </summary>
        public EventReference RollEvent
        {
            get { return _rollEvent; }
            set { _rollEvent = value; }
        }

        /// <summary>
        /// The range input velocities will be compared to when calculating the collision intensity.
        /// </summary>
        public Range VelocityRange
        {
            get { return _velocityRange; }
            set { _velocityRange = value; }
        }

        /// <summary>
        /// How much the collision normal affects the collision intensity.
        /// </summary>
        public float CollisionNormalInfluence
        {
            get { return _collisionNormalInfluence; }
            set { _collisionNormalInfluence = value; }
        }

        public override IInteractionResult GetInteractionResult<T>(T interactionData)
        {
            //Immediately break out if intensity is less than the velocity range minimum, since any result would be invalid anyways.
            float intensity = ImpactInteractionUtilities.GetCollisionIntensity(interactionData, CollisionNormalInfluence);
            if (intensity < VelocityRange.Min)
                return null;

            long key = 0;
            if (!ImpactInteractionUtilities.GetKeyAndValidate(interactionData, this, out key))
                return null;

            FMODAudioInteractionResult result;

            if (ImpactManagerInstance.TryGetInteractionResultFromPool(interactionResultPoolKey, out result))
            {
                result.OriginalData = InteractionDataUtilities.ToInteractionData(interactionData);

                result.Event = getEvent(interactionData.InteractionType);
                result.Intensity = VelocityRange.Normalize(intensity);
                result.Key = key;

                return result;
            }

            return null;
        }

        private EventReference getEvent(int interactionType)
        {
            if (interactionType == InteractionData.InteractionTypeCollision)
                return _collisionEvent;
            else if (interactionType == InteractionData.InteractionTypeSlide)
                return _slideEvent;
            else if (interactionType == InteractionData.InteractionTypeRoll)
                return _rollEvent;

            return new EventReference();
        }

        public override void Preload()
        {
            ImpactManagerInstance.CreateInteractionResultPool<FMODAudioInteractionResult>(interactionResultPoolKey);
        }
    }
}

