using System;

using Svelto.ECS;

namespace GamecraftModdingAPI.Events
{
    public class HandlerBuilder
    {
		private string name;

		private int? type;

		private Action<EntitiesDB> activated;

		private Action<EntitiesDB> destroyed;

        /// <summary>
        /// Create a new event handler builder.
        /// </summary>
        public HandlerBuilder()
        {
        }

        /// <summary>
        /// Create a new event handler builder.
		/// This is equivalent to new <code>HandlerBuilder().Name(name)</code>
        /// </summary>
        /// <param name="name">The handler name.</param>
		public HandlerBuilder(string name)
		{
			this.name = name;
		}

        /// <summary>
		/// Create and return an event handler builder.
        /// </summary>
        /// <returns>The builder.</returns>
		public static HandlerBuilder Builder()
		{
			return new HandlerBuilder();
		}

        /// <summary>
        /// Create and return an event handler builder.
		/// This is equivalent to <code>Builder().Name(name)</code>
        /// </summary>
        /// <returns>The builder.</returns>
        /// <param name="name">The handler name.</param>
		public static HandlerBuilder Builder(string name)
		{
			return new HandlerBuilder(name);
		}

        /// <summary>
        /// Name the event handler.
        /// </summary>
        /// <returns>The builder.</returns>
        /// <param name="name">The event handler name.</param>
		public HandlerBuilder Name(string name)
		{
			this.name = name;
			return this;
		}

        /// <summary>
        /// Set the action to perform on when the activated event occurs.
        /// </summary>
        /// <returns>The builder.</returns>
        /// <param name="action">The activated event action.</param>
		public HandlerBuilder OnActivation(Action action)
		{
			return OnActivation((_) => { action(); });
		}

		/// <summary>
        /// Set the action to perform on when the activated event occurs.
        /// </summary>
        /// <returns>The builder.</returns>
        /// <param name="action">The activated event action.</param>
		public HandlerBuilder OnActivation(Action<EntitiesDB> action)
		{
			this.activated = action;
			return this;
		}

		/// <summary>
        /// Set the action to perform when the destroyed event occurs.
        /// </summary>
        /// <returns>The builder.</returns>
        /// <param name="action">The destroyed event action.</param>
		public HandlerBuilder OnDestruction(Action action)
        {
            return OnDestruction((_) => { action(); });
        }

		/// <summary>
        /// Set the action to perform when the destroyed event occurs.
        /// </summary>
        /// <returns>The builder.</returns>
        /// <param name="action">The destroyed event action.</param>
        public HandlerBuilder OnDestruction(Action<EntitiesDB> action)
        {
			this.destroyed = action;
            return this;
        }

        /// <summary>
        /// Set the type of event to handle.
        /// </summary>
        /// <returns>The builder.</returns>
        /// <param name="eventType">The event type.</param>
		public HandlerBuilder Handle(EventType eventType)
		{
			return Handle((int)eventType);
		}

		/// <summary>
        /// Set the type of event to handle.
        /// </summary>
        /// <returns>The builder.</returns>
        /// <param name="eventType">The event type.</param>
		public HandlerBuilder Handle(int eventType)
		{
			this.type = eventType;
			return this;
		}

        /// <summary>
        /// Build the event handler.
        /// </summary>
        /// <returns>The event handler.</returns>
        /// <param name="register">Automatically register the event handler with EventManager.AddEventHandler().</param>
		public IEventHandlerEngine Build(bool register = true)
		{
			if (string.IsNullOrWhiteSpace(name))
            {
                throw new EventParameterMissingException("Event handler name must be defined before Build() is called");
            }
			if (activated == null && destroyed == null)
			{
				throw new EventParameterMissingException("Event handler destruction or activated event action must be defined before Build() is called");
			}
			if (!type.HasValue)
			{
				throw new EventParameterMissingException("Event handler event type must be defined before Build() is called");
			}
			Action<EntitiesDB> validActivated = activated;
            if (validActivated == null)
			{
				validActivated = (_) => { };
			}
			Action<EntitiesDB> validDestroyed = destroyed;
            if (validDestroyed == null)
            {
                validDestroyed = (_) => { };
            }
			SimpleEventHandlerEngine result = new SimpleEventHandlerEngine(validActivated, validDestroyed, type.Value, name);
			if (register)
			{
				EventManager.AddEventHandler(result);
			}
			return result;
		}
    }
}