namespace GamecraftModdingAPI.Blocks
{
    /// <summary>
    /// Common tweakable stats operations.
	/// The functionality of this class works best in build mode.
    /// </summary>
    public static class Tweakable
    {
		private static TweakableEngine tweakableEngine = new TweakableEngine();

        /// <summary>
        /// Get the tweakable stat's value using a dynamic variable type.
		/// This is similar to GetStat<T> but without strong type enforcement.
		/// This should be used in dynamically-typed languages like Python.
        /// </summary>
        /// <returns>The stat's value.</returns>
        /// <param name="blockID">The block's id.</param>
        /// <param name="stat">The stat's enumerated id.</param>
		public static dynamic GetStatD(uint blockID, TweakableStat stat)
        {
            return tweakableEngine.GetStatDynamic(blockID, stat);
        }

        /// <summary>
        /// Get the tweakable stat's value.
		/// If T is not the same type as the stat, an InvalidCastException will be thrown.
        /// </summary>
        /// <returns>The stat's value.</returns>
		/// <param name="blockID">The block's id.</param>
        /// <param name="stat">The stat's enumerated id.</param>
        /// <typeparam name="T">The stat's type.</typeparam>
		public static T GetStat<T>(uint blockID, TweakableStat stat)
		{
			return tweakableEngine.GetStatAny<T>(blockID, stat);
		}

        /// <summary>
        /// Set the tweakable stat's value using dynamically-typed variables.
		/// This is similar to SetStat<T> but without strong type enforcement.
		/// This should be used in dynamically-typed languages like Python.
        /// </summary>
        /// <returns>The stat's new value.</returns>
		/// <param name="blockID">The block's id.</param>
        /// <param name="stat">The stat's enumerated id.</param>
        /// <param name="value">The stat's new value.</param>
		public static dynamic SetStatD(uint blockID, TweakableStat stat, dynamic value)
        {
            return tweakableEngine.SetStatDynamic(blockID, stat, value);
        }

        /// <summary>
        /// Set the tweakable stat's value.
		/// If T is not the stat's actual type, an InvalidCastException will be thrown.
		/// </summary>
		/// <returns>The stat's new value.</returns>
        /// <param name="blockID">The block's id.</param>
        /// <param name="stat">The stat's enumerated id.</param>
		/// <param name="value">The stat's new value.</param>
        /// <typeparam name="T">The stat's type.</typeparam>
		public static T SetStat<T>(uint blockID, TweakableStat stat, T value)
		{
			return tweakableEngine.SetStatAny<T>(blockID, stat, value);
		}

		/// <summary>
        /// Add another value to the tweakable stat's value using dynamically-typed variables.
        /// This is similar to AddStat<T> but without strong type enforcement.
        /// This should be used in dynamically-typed languages like Python.
        /// </summary>
        /// <returns>The stat's new value.</returns>
        /// <param name="blockID">The block's id.</param>
        /// <param name="stat">The stat's enumerated id.</param>
        /// <param name="value">The value to be added to the stat.</param>
		public static dynamic AddStatD(uint blockID, TweakableStat stat, dynamic value)
        {
            return tweakableEngine.AddStatDynamic(blockID, stat, value);
        }

		/// <summary>
        /// Add another value to the tweakable stat's value.
        /// If T is not the stat's actual type, an InvalidCastException will be thrown.
        /// </summary>
        /// <returns>The stat's new value.</returns>
        /// <param name="blockID">The block's id.</param>
        /// <param name="stat">The stat's enumerated id.</param>
        /// <param name="value">The value to be added to the stat.</param>
        /// <typeparam name="T">The stat's type.</typeparam>
		public static T AddStat<T>(uint blockID, TweakableStat stat, T value)
		{
			return tweakableEngine.AddStatAny<T>(blockID, stat, value);
		}

		public static void Init()
		{
			GamecraftModdingAPI.Utility.GameEngineManager.AddGameEngine(tweakableEngine);
		}
    }
}