using System;
using System.Linq;
using Creaturelib;
using Creaturelib.Generated;
using PkmnLibSharp.Utilities;

namespace PkmnLibSharp.Library.Moves
{
    public class MoveData : PointerWrapper
    {
        private string? _name;
        private string? _secondaryEffectName;
        
        public string Name => _name ??= AttackData.GetName(Ptr).PtrString()!;
        public byte Type => AttackData.GetType(Ptr);
        public MoveCategory Category => (MoveCategory) AttackData.GetCategory(Ptr);
        public byte BasePower => AttackData.GetBasePower(Ptr);
        public byte Accuracy => AttackData.GetAccuracy(Ptr);
        public byte BaseUsages => AttackData.GetBaseUsages(Ptr);
        public MoveTarget Target => (MoveTarget) AttackData.GetTarget(Ptr);
        public sbyte Priority => AttackData.GetPriority(Ptr);
        public bool HasSecondaryEffect => AttackData.HasSecondaryEffect(Ptr) == 1;
        public float SecondaryEffectChance => AttackData.GetSecondaryEffectChance(Ptr);

        public string SecondaryEffectName =>
            _secondaryEffectName ??= AttackData.GetSecondaryEffectName(Ptr).PtrString()!;

        public bool HasFlag(string s)
        {
            return AttackData.HasFlag(Ptr, s.ToPtr()) == 1;
        }

        public MoveData(string name, byte type, MoveCategory category, byte power, byte accuracy,
            byte baseUsage, MoveTarget target, sbyte priority, float effectChance, string effectName,
            EffectParameter[] parameters, string[] flags)
        {
            var ptr = IntPtr.Zero;
            var pars = parameters.Select(x => x.Ptr).ToArray().ArrayPtr();
            var f = flags.Select(x => x.ToPtr()).ToArray().ArrayPtr();

            AttackData.Construct(ref ptr, name.ToPtr(), type, (AttackCategory) category, power, accuracy, baseUsage,
                (AttackTarget) target, priority, effectChance, effectName.ToPtr(), pars,
                (ulong) parameters.Length, f, (ulong) flags.Length).Assert();
            Initialize(ptr);
        }

        protected override void DeletePtr()
        {
            AttackData.Destruct(Ptr);
        }
    }
}