using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Svelto.ECS;

using GamecraftModdingAPI.Utility;

namespace GamecraftModdingAPI.Events
{
    /// <summary>
    /// A simple implementation of IEventHandlerEngine sufficient for most uses
    /// </summary>
    [Obsolete]
    public class SimpleEventHandlerEngine : IEventHandlerEngine
    {
        public int type { get; set; }
        public string Name { get; set; }

        private bool isActivated = false;

		private bool jankActivateFix = false;

		private bool jankDestroyFix = false;

        private readonly Action<EntitiesDB> onActivated;

        private readonly Action<EntitiesDB> onDestroyed;

        public EntitiesDB entitiesDB { set; private get; }

		public bool isRemovable => true;

		public void Add(ref ModEventEntityStruct entityView, EGID egid)
        {
            if (entityView.type.Equals(this.type))
            {
				jankActivateFix = !jankActivateFix;
                if (jankActivateFix) return;
                isActivated = true;
				onActivatedInvokeCatchError(entitiesDB);
            }
        }

        /// <summary>
        /// Manually activate the EventHandler.
		/// Once activated, the next remove event will not be ignored.
        /// </summary>
        /// <param name="handle">Whether to invoke the activated action</param>
		public void Activate(bool handle = false)
		{
			isActivated = true;
			if (handle && entitiesDB != null)
			{
				onActivatedInvokeCatchError(entitiesDB);
			}
		}

		public void Deactivate()
		{
			isActivated = false;
		}

        public void Ready() { }

        public void Remove(ref ModEventEntityStruct entityView, EGID egid)
        {
            if (entityView.type.Equals(this.type) && isActivated)
            {
				jankDestroyFix = !jankDestroyFix;
                if (jankDestroyFix) return;
                isActivated = false;
				onDestroyedInvokeCatchError(entitiesDB);
            }
        }

        public void Dispose()
        {
            if (isActivated)
            {
                isActivated = false;
				onDestroyedInvokeCatchError(entitiesDB);
            }
        }

        /// <summary>
        /// Construct the engine
        /// </summary>
        /// <param name="activated">The operation to do when the event is created</param>
        /// <param name="removed">The operation to do when the event is destroyed (if applicable)</param>
        /// <param name="type">The type of event to handle</param>
        /// <param name="name">The name of the engine</param>
        /// <param name="simple">A useless parameter to use to avoid Python overload resolution errors</param>
        public SimpleEventHandlerEngine(Action activated, Action removed, int type, string name, bool simple = true) 
            : this((EntitiesDB _) => { activated.Invoke(); }, (EntitiesDB _) => { removed.Invoke(); }, type, name) { }

        /// <summary>
        /// Construct the engine
        /// </summary>
        /// <param name="activated">The operation to do when the event is created</param>
        /// <param name="removed">The operation to do when the event is destroyed (if applicable)</param>
        /// <param name="type">The type of event to handler</param>
        /// <param name="name">The name of the engine</param>
        public SimpleEventHandlerEngine(Action<EntitiesDB> activated, Action<EntitiesDB> removed, int type, string name)
        {
            this.type = type;
            this.Name = name;
            this.onActivated = activated;
            this.onDestroyed = removed;
        }

		private void onActivatedInvokeCatchError(EntitiesDB _entitiesDB)
		{
			try
			{
				onActivated.Invoke(_entitiesDB);
			}
			catch (Exception e)
			{
				EventRuntimeException wrappedException = new EventRuntimeException($"EventHandler {Name} threw an exception when activated", e);
				Logging.LogWarning(wrappedException.ToString());
			}
		}

		private void onDestroyedInvokeCatchError(EntitiesDB _entitiesDB)
        {
            try
            {
                onDestroyed.Invoke(_entitiesDB);
            }
            catch (Exception e)
            {
                EventRuntimeException wrappedException = new EventRuntimeException($"EventHandler {Name} threw an exception when destroyed", e);
                Logging.LogWarning(wrappedException.ToString());
            }
        }

		public SimpleEventHandlerEngine(Action activated, Action removed, EventType type, string name, bool simple = true)
            : this((EntitiesDB _) => { activated.Invoke(); }, (EntitiesDB _) => { removed.Invoke(); }, (int)type, name) { }

		public SimpleEventHandlerEngine(Action<EntitiesDB> activated, Action<EntitiesDB> removed, EventType type, string name, bool simple = true)
			: this(activated, removed, (int)type, name) { }
    }
}