using System;
using Bolt;
using Ludiq;

namespace BansheeGz.BGDatabase
{
    public abstract class BGBoltEntityAbstractEvent : GameObjectEventUnit<BGBoltEntityAbstractEventArgs>
    {
        private EventHandler<BGEventArgsAnyEntity> eventHandler;

        public override Type MessageListenerType => null;

        [DoNotSerialize]
        public ValueInput metaName { get; private set; }


        [DoNotSerialize]
        public ValueOutput entityId { get; private set; }

        [DoNotSerialize]
        public ValueOutput entityIndex { get; private set; }


        protected override void Definition()
        {
            base.Definition();
            metaName = ValueInput("metaName", "");

            entityId = ValueOutput<string>("entityId");
            entityIndex = ValueOutput<int>("entityIndex");
        }

        public override void StartListening(GraphStack stack)
        {
            var data = stack.GetElementData<Data>(this);
            if (data.isListening) return;
            var reference = stack.ToReference();
            var tableName = Flow.FetchValue<string>(metaName, reference);

            var table = BGRepo.I[tableName];
            eventHandler = (sender, args) =>
            {
                Trigger(reference, new BGBoltEntityAbstractEventArgs(args.Entity.Id.ToString(), args.Entity.Index));
            };
            AddListener(table.Id, eventHandler);

            base.StartListening(stack);
        }

        public override void StopListening(GraphStack stack)
        {
            if (eventHandler != null)
            {
                var reference = stack.ToReference();
                var tableName = Flow.FetchValue<string>(metaName, reference);
                var table = BGRepo.I[tableName];
                RemoveListener(table.Id, eventHandler);
            }
            base.StopListening(stack);
        }


        protected override void AssignArguments(Flow flow, BGBoltEntityAbstractEventArgs data)
        {
            flow.SetValue(this.entityId, data.entityId);
            flow.SetValue(this.entityIndex, data.entityIndex);
        }

        protected abstract void AddListener(BGId tableId, EventHandler<BGEventArgsAnyEntity> eventHandler1);
        protected abstract void RemoveListener(BGId tableId, EventHandler<BGEventArgsAnyEntity> eventHandler1);
    }
}