#nullable enable


namespace TagFighter.Effects.Steps
{
    using System.Reflection;
    using System.Collections.Generic;
    using System.Linq;
    using TagFighter.Effects.ResourceLocationAccessors.ContextRegisters;

    [StepType(StepTypeAttribute.GetterStep)]
    public class ContextResourceGet : OutputStep<double>
    {
        [CareBoo.Serially.TypeFilter(derivedFrom: typeof(Resources.Resource<>))]
        public CareBoo.Serially.SerializableType? Resource;

        [CareBoo.Serially.TypeFilter(derivedFrom: typeof(ContextRegister<>))]
        public CareBoo.Serially.SerializableType? Register;

        public override double Run(EffectInput blackBoard) {
            if (!IsValid || Register == null || Resource == null) {
                UnityEngine.Debug.LogError($"{this} Inner types are null");
                return 0;
            }

            var getSpecificMethod = typeof(ContextResourceGet).GetMethod(nameof(GetSpecific), BindingFlags.NonPublic | BindingFlags.Instance).
                                            MakeGenericMethod(Resource.Type, Resource.Type.BaseType.GetGenericArguments()[0], Register.Type);
            var value = getSpecificMethod.Invoke(this, new object[] { blackBoard });

            return (int)value;
        }

        public double Test(EffectInput[] Data) {
            return 0;
        }

        int GetSpecific<TResource, TUnitType, TContextRegister>(EffectInput blackBoard)
            where TResource : Resources.Resource<TUnitType>
            where TUnitType : Resources.IUnitType
            where TContextRegister : IContextRegister {

            return blackBoard != null ? blackBoard.Context.GetResource<TResource, TUnitType, TContextRegister>().AsPrimitive() : 0;
        }

        public override IEnumerable<IPort> Inputs => Enumerable.Empty<IPort>();

        public override string ToString() {
            var resourceName = Resource == null || Resource.Type == null ? "*" : Resource.Type.Name;
            var registerName = Register == null || Register.Type == null ? "*" : Register.Type.Name;

            return $"Context.Get.{resourceName}.{registerName}";
        }

        public override bool IsValid {
            get {
                return Register != null && Register.Type != null && Resource != null && Resource.Type != null;
            }
        }
        public override EffectStepNodeData ToData() {
            var effectStepNodeData = base.ToData();
            effectStepNodeData.Resource = Resource;
            effectStepNodeData.Register = Register;
            return effectStepNodeData;
        }

        public override bool FromData(EffectStepNodeData effectStepNodeData, Dictionary<string, EffectStepNode> guidToNode) {
            base.FromData(effectStepNodeData, guidToNode);
            Resource = effectStepNodeData.Resource;
            Register = effectStepNodeData.Register;
            return true;
        }

    }
}