/*
 * +================================================================================+
 *      __  ___  ______________  __  __  ______________   ____
 *     / / / / |/ /  _/_  __/\ \/ / / / / /_  __/  _/ /  / __/
 *    / /_/ /    // /  / /    \  / / /_/ / / / _/ // /___\ \
 *    \____/_/|_/___/ /_/     /_/  \____/ /_/ /___/____/___/
 *
 * +================================================================================+
 *
 *    "THE BEER-WARE LICENSE"
 *    -----------------------
 *
 *    As long as you retain this notice you can do whatever you want with this
 *    stuff. However it is expressly forbidden to sell or commercially distribute
 *    Unity Utils or parts of it apart from your games.
 *    If you meet any of the authors some day, and you think this stuff is
 *    worth it, you can buy them a beer in return.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *    THE SOFTWARE.
 *
 * +================================================================================+
 *
 *    Authors:
 *    David Krummenacher (dave@timbookedtwo.com)
 *
 */

using UnityEngine;

namespace Utils.AnimatorController {

	/// <summary>
	/// Freezes and unfreezes a the animators rigidbody.
	/// </summary>
	public class FreezeRigidbodyBehaviourScript : StateMachineBehaviour {

		[Tooltip("Determines wheter the childrens rigidbodies are included.")]
		/// <summary>
		/// Determines wheter the childrens rigidbodies are included.
		/// </summary>
		public bool IncludeChildren = false;

		[Header("On state enter")]
		[Tooltip("Wheter to set the velocity to 0 or not on entering the state.")]
		/// <summary>
		/// Wheter to set the velocity to 0 or not on entering the state.
		/// </summary>
		public bool ResetVelocityOnEnter = true;
		[Tooltip("Wheter to set the angular velocity to 0 or not on entering the state.")]
		/// <summary>
		/// Wheter to set the angular velocity to 0 or not on entering the state.
		/// </summary>
		public bool ResetAngularVelocityOnEnter = true;
		[Tooltip("If the rigidbody should be set to kinematic on entering the state.")]
		/// <summary>
		/// If the rigidbody should be set to kinematic on entering the state.
		/// </summary>
		public bool IsKinematicOnEnter = true;
		[Tooltip("Wheter to use gravity on entering the state.")]
		/// <summary>
		/// Wheter to use gravity on entering the state.
		/// </summary>
		public bool UseGravityOnEnter = false;

		[Header("On state exit")]
		[Tooltip("Wheter to set the velocity to 0 or not on exiting the state.")]
		/// <summary>
		/// Wheter to set the velocity to 0 or not on exiting the state.
		/// </summary>
		public bool ResetVelocityOnExit = false;
		[Tooltip("Wheter to set the angular velocity to 0 or not on exiting the state.")]
		/// <summary>
		/// Wheter to set the angular velocity to 0 or not on exiting the state.
		/// </summary>
		public bool ResetAngularVelocityOnExit = false;
		[Tooltip("If the rigidbody should be set to kinematic on exiting the state.")]
		/// <summary>
		/// If the rigidbody should be set to kinematic on exiting the state.
		/// </summary>
		public bool IsKinematicOnExit = false;
		[Tooltip("Wheter to use gravity on exiting the state.")]
		/// <summary>
		/// Wheter to use gravity on exiting the state.
		/// </summary>
		public bool UseGravityOnExit = true;

		override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
			// Get necessairy rigidodies
			Rigidbody[] rigidbodies;
			if (IncludeChildren) rigidbodies = animator.gameObject.GetComponentsInChildren<Rigidbody>();
			else rigidbodies = animator.gameObject.GetComponents<Rigidbody>();

			// Apply settings to the rigidbodies
			foreach (Rigidbody rigidbody in rigidbodies) {
				if (ResetVelocityOnEnter) rigidbody.velocity = Vector3.zero;
				if (ResetAngularVelocityOnEnter) rigidbody.angularVelocity = Vector3.zero;

				rigidbody.isKinematic = IsKinematicOnEnter;
				rigidbody.useGravity = UseGravityOnEnter;
			}
		}
		
		override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
			// Get necessairy rigidodies
			Rigidbody[] rigidbodies;
			if (IncludeChildren) rigidbodies = animator.gameObject.GetComponentsInChildren<Rigidbody>();
			else rigidbodies = animator.gameObject.GetComponents<Rigidbody>();

			// Apply settings to the rigidbodies
			foreach (Rigidbody rigidbody in rigidbodies) {
				if (ResetVelocityOnExit) rigidbody.velocity = Vector3.zero;
				if (ResetAngularVelocityOnExit) rigidbody.angularVelocity = Vector3.zero;

				rigidbody.isKinematic = IsKinematicOnExit;
				rigidbody.useGravity = UseGravityOnExit;
			}
		}
	}
}
