namespace pdinklag.CPW.Common
{
    /// <summary>
    /// Interface for strike reactions.
    /// </summary>
    public interface IStrikeReaction : IContext
    {
        /// <summary>
        /// The wrestler being hit by the strike.
        /// </summary>
        IWrestler Wrestler { get; }

        /// <summary>
        /// The body part that was hit first.
        /// </summary>
        RagdollPart HitBodyPart { get; }

        /// <summary>
        /// A value describing in what direction the hit occured on the forward axis,
        /// 1 meaning the hit came precisely from the victim's front, -1 meaning it came from the back.
        /// </summary>
        float HitFront { get; }

        /// <summary>
        /// A value describing where the victim was hit on the Y axis,
        /// 1 meaning the head, 0 around the lower body and -1 the feet.
        /// </summary>
        float HitHeight { get; }

        /// <summary>
        /// The damage applied to the victim.
        /// 
        /// Initially, this equals the base damage as given by the strike.
        /// </summary>
        float Damage { get; set; }

        /// <summary>
        /// Puts the victim in a special strike reaction state,
        /// revoking player or AI control and making him immune to other damage.
        /// </summary>
        void GotoStrikeReactionState();
        
        /// <summary>
        /// Makes the wrestler mimic the given state until the playback has finished, then goes to said state.
        /// </summary>
        /// <param name="state">the state to finish as</param>
        /// <param name="p">the anim playback to wait for</param>
        void FinishAs(TargetState state, IAnimPlayback p);

        /// <summary>
        /// Applies the hit force to the ragdoll.
        /// </summary>
        /// <param name="multiplier">the multiplier for the impulse</param>
        void ApplyRagdollForce(float multiplier = 1.0f);

        /// <summary>
        /// Applies the damage.
        /// </summary>
        void ApplyDamage();

        /// <summary>
        /// Plays the default hit sound as given by the damage type.
        /// </summary>
        void PlayDefaultHitSound();

        /// <summary>
        /// Plays an animation.
        /// </summary>
        /// <param name="address">the animation's asset ID</param>
        /// <param name="transitionDuration">the time, in seconds, to blend into the animation</param>
        /// <returns>the animation playback</returns>
        IAnimPlayback PlayAnim(AssetAddress address, float transitionDuration = 0.5f);

        /// <summary>
        /// Plays the strike reaction for the specified damage type.
        /// 
        /// This potentially includes applying damage and transitioning into a different state.
        /// </summary>
        /// <param name="damageType">the damage type to play the reaction for</param>
        /// <param name="ctx">the execution context</param>
        /// <returns>the corresponding yield instruction</returns>
        YieldInstructionCode PlayReactionFor(AssetAddress damageType);

        /// <summary>
        /// Plays the default strike reaction for the victim's current state.
        /// 
        /// This potentially includes applying damage and transitioning into a different state.
        /// </summary>
        /// <param name="ctx">the execution context</param>
        /// <returns>the corresponding yield instruction</returns>
        YieldInstructionCode PlayDefaultReaction();
    }
}
