using ModernUO.Serialization;
using Server.Items;

namespace Server.Mobiles;

[SerializationGenerator(0, false)]
public partial class ArcherGuard : BaseGuard
{
    private bool _shooting;

    [Constructible]
    public ArcherGuard(Mobile target = null) : base(target)
    {
        InitStats(100, 125, 25);
        SpeechHue = Utility.RandomDyedHue();
        Hue = Race.Human.RandomSkinHue();

        if (Female = Utility.RandomBool())
        {
            Body = 0x191;
            Name = NameList.RandomName("female");
        }
        else
        {
            Body = 0x190;
            Name = NameList.RandomName("male");
        }

        new Horse().Rider = this;

        AddItem(new StuddedChest());
        AddItem(new StuddedArms());
        AddItem(new StuddedGloves());
        AddItem(new StuddedGorget());
        AddItem(new StuddedLegs());
        AddItem(new Boots());
        AddItem(new SkullCap());

        var bow = new Bow();

        bow.Movable = false;
        bow.Crafter = Name;
        bow.Quality = WeaponQuality.Exceptional;

        AddItem(bow);

        var pack = new Backpack
        {
            Movable = false
        };

        pack.DropItem(new Arrow(250)
        {
            LootType = LootType.Newbied
        });
        pack.DropItem(new Gold(10, 25));

        AddItem(pack);

        Skills.Anatomy.Base = 120.0;
        Skills.Tactics.Base = 120.0;
        Skills.Archery.Base = 120.0;
        Skills.MagicResist.Base = 120.0;
        Skills.DetectHidden.Base = 100.0;

        NextCombatTime = Core.TickCount + 500;
        Focus = target;
    }

    [SerializableProperty(0)]
    [CommandProperty(AccessLevel.GameMaster)]
    public override Mobile Focus
    {
        get => _focus;
        set
        {
            if (Deleted)
            {
                return;
            }

            var oldFocus = _focus;

            if (oldFocus != value)
            {
                _focus = value;

                if (value != null)
                {
                    AggressiveAction(value);
                }

                Combatant = value;

                if (oldFocus?.Alive == false)
                {
                    Say("Thou hast suffered thy punishment, scoundrel.");
                }

                if (value != null)
                {
                    Say(500131); // Thou wilt regret thine actions, swine!
                }

                AttackTimer = null;
                IdleTimer = null;

                if (_focus != null)
                {
                    AttackTimer = new GuardAttackTimer(this);
                    AttackTimer.Start();
                }
                else
                {
                    IdleTimer = new GuardIdleTimer(this);
                }
            }
            else if (_focus == null && IdleTimer == null && Spawner != null)
            {
                IdleTimer = new GuardIdleTimer(this);
            }

            this.MarkDirty();
        }
    }

    public override bool OnBeforeDeath()
    {
        if (_focus?.Alive == true)
        {
            new GuardAvengeTimer(_focus).Start(); // If a guard dies, three more guards will spawn
        }

        return base.OnBeforeDeath();
    }

    public override void NonLethalAttack(Mobile target)
    {
        if (!InRange(target, 20))
        {
            _shooting = false;
            Focus = null;
            return;
        }

        if (!InLOS(target))
        {
            _shooting = false;
            TeleportTo(this, target.Location);
            return;
        }

        if (!CanSee(target))
        {
            _shooting = false;

            if (InRange(target, 2))
            {
                if (UseSkill(SkillName.DetectHidden))
                {
                    Say("Reveal!");
                }
            }
            else if (!Move(GetDirectionTo(target) | Direction.Running) && OutOfMaxDistance(target))
            {
                TeleportTo(this, target.Location);
            }

            return;
        }

        if (_shooting)
        {
            if (TimeToSpare() || OutOfMaxDistance(target))
            {
                _shooting = false;
            }

            return;
        }

        if (InRange(target, 1) && !Move(GetDirectionTo(target) - 4 | Direction.Running) && OutOfMaxDistance(target))
        {
            TeleportTo(this, target.Location);
            return;
        }

        if (InMinDistance(target))
        {
            _shooting = true;
        }
    }

    private bool TimeToSpare() => NextCombatTime - Core.TickCount > 1000;

    private bool OutOfMaxDistance(IPoint2D target) => !InRange(target, Weapon.MaxRange);

    private bool InMinDistance(IPoint2D target) => InRange(target, 4);
}
