using System;
using Server.Items;
using System.Collections;
using System.Collections.Generic;
using Server.Spells;
using Server.Engines.CannedEvil;
using Server.Network;

namespace Server.Mobiles
{
    public class KhalAnkur : BaseChampion
    {
        public static Type[] ExtraLoot = new Type[]
        {
            typeof(SwaddlingClothes)
        };

        public override bool ClickTitle { get { return false; } }
        public override bool ShowFameTitle { get { return false; } }
        public override bool CanRummageCorpses { get { return true; } }
        public override bool BardImmune { get { return true; } }
        public override bool Unprovokable { get { return true; } }
        public override bool Uncalmable { get { return true; } }
        public override Poison PoisonImmune { get { return Poison.Lethal; } }
        public override int TreasureMapLevel { get { return 5; } }
        public override bool IsNotScaredOfDeath { get { return true; } } //neutika pri malem poctu hp

        public override WeaponAbility GetWeaponAbility()
        {
            return Utility.RandomBool() ? WeaponAbility.ConcussionBlow : WeaponAbility.CrushingBlow;
        }

        private DateTime m_Delay = DateTime.Now;
        private DateTime m_SilenceDelay = DateTime.Now;
        private DateTime m_SpawnedSkulls = DateTime.Now;
        private bool m_SpawnedSlowMob = false;

        public override ChampionSkullType SkullType { get { return ChampionSkullType.Greed; } }

        [Constructable]
        public KhalAnkur() : this(false, 5)
        {
        }

        [Constructable]
        public KhalAnkur(int range) : this(false, range)
        {
        }

        [Constructable]
        public KhalAnkur(bool ischampion, int range) : base(AIType.AI_Necromage, FightMode.Closest, ischampion, range)
        {
            Title = "the Ancestral Lich";
            Hue = 2558;
            Body = 24;
            BaseSoundID = 0x3E9;
            Name = "Khal Ankur";

            DropMin = 50;
            DropMax = 100;
            BonusLoot = "mesicnikamen";
            BonusLootAmount = Utility.RandomMinMax(1, 3);

            SetStr(700, 720);
            SetDex(1000, 1100);
            SetInt(1000, 1200);

            SetHits(90000);
            SetMana(2500);
            SetStam(1000);

            SetDamage(25, 30);

            SetDamageType(ResistanceType.Energy, 70);
            SetDamageType(ResistanceType.Physical, 30);

            SetResistance(ResistanceType.Physical, 70, 75);
            SetResistance(ResistanceType.Fire, 80, 90);
            SetResistance(ResistanceType.Cold, 70, 75);
            SetResistance(ResistanceType.Poison, 70, 75);
            SetResistance(ResistanceType.Energy, 70, 75);

            SetSkill(SkillName.EvalInt, 100.6, 150.5);
            SetSkill(SkillName.Necromancy, 120.6, 150.5);
            SetSkill(SkillName.SpiritSpeak, 120.1, 150.5);
            SetSkill(SkillName.Magery, 150.1, 160.1);
            SetSkill(SkillName.Poisoning, 80.5);
            SetSkill(SkillName.Meditation, 110.0);
            SetSkill(SkillName.MagicResist, 80.1, 85.0);
            SetSkill(SkillName.Parry, 90.1, 100.1);
            SetSkill(SkillName.Tactics, 120.0);
            SetSkill(SkillName.Anatomy, 100.0);
            SetSkill(SkillName.Wrestling, 90.1, 120.0);
            SetSkill(SkillName.Swords, 115.1, 120.0);

            Fame = 10000;
            Karma = -15000;

            Item reags = Loot.RandomReagent();
            reags.Amount = 30;
            PackItem(reags);

            PackNecroReg(60, 100);

            if (0.1 > Utility.RandomDouble())
                PackItem(ClothingSkillScroll.CreateRandomNoCraft(1, Utility.RandomList(1, 1, 1, 1, 1, 1, 1, 2, 3)));

            if (0.01 > Utility.RandomDouble())
                PackItem((Item)Activator.CreateInstance(ExtraLoot[Utility.Random(ExtraLoot.Length)]));
        }

        public override int GetIdleSound()
        {
            return 0x1CE;
        }

        public override bool OnBeforeDeath()
        {
            Server.Regions.KhaldunRegion.DropHealthOrb(this);
            Server.Regions.KhaldunRegion.DropHealthOrb(this);

            return base.OnBeforeDeath();
        }

        public override void OnKilledBy(Mobile mob)
        {
            base.OnKilledBy(mob);

            if (mob == null)
                return;

            if (mob.Player && Paragon.CheckArtifactChance(mob, this))
            {
                if (mob.Talisman is KhalAnkurAmulet)
                    ((KhalAnkurAmulet)mob.Talisman).SpendingPoints += 10;
                else
                {
                    Container pack = mob.Backpack;
                    KhalAnkurAmulet amulet = new KhalAnkurAmulet();
                    amulet.BlessedFor = mob;

                    if (pack == null || !pack.TryDropItem(mob, amulet, false))
                        mob.BankBox.DropItem(amulet);

                    mob.SendLocalizedMessage(1062317); // For your valor in combating the fallen beast, a special artifact has been bestowed on you.
                }
            }

            if (mob.Talisman is KhalAnkurAmulet)
                ((KhalAnkurAmulet)mob.Talisman).SpendingPoints += 5;

            if (Teragon.CheckArtifactChance(mob, this))
                Teragon.GiveArtifactTo(mob, this);
        }

        private static readonly Point3D[] m_SkullOffsets = new Point3D[]
        {
            new Point3D(5444, 1497, 0), new Point3D(5444, 1493, 0), new Point3D(5444, 1489, 0),
            new Point3D(5458, 1497, 0), new Point3D(5458, 1493, 0), new Point3D(5458, 1489, 0),
        };

        public override void OnDamage(int amount, Mobile from, bool willKill, int typ)
        {
            base.OnDamage(amount, from, willKill, typ);

            if (from == null)
                return;

            if (DateTime.Now > m_SpawnedSkulls && this.Hits < (this.HitsMax * 80) / 100 && KhaldunRevenant.IsInsideKhaldun(this))
            {
                m_SpawnedSkulls = DateTime.Now + TimeSpan.FromMinutes(5.0);

                for (int i = 0; i < m_SkullOffsets.GetLength(0); ++i)
                {
                    BaseCreature skull = (m_SkullOffsets[i].Y == 1497) ? (BaseCreature)new SkullFury() : (Utility.RandomBool()) ? (BaseCreature)new ShadowFiend() : (BaseCreature)new RestlessGhost();

                    if (this.Map.CanSpawnMobile(m_SkullOffsets[i]))
                    {
                        TimeSpan duration = TimeSpan.FromMinutes(4.0);

                        new Server.Spells.UnsummonTimer(this, skull, duration).Start();
                        skull.SummonEnd = DateTime.Now + duration;
                        skull.SetHits(700);
                        skull.MoveToWorld(m_SkullOffsets[i], this.Map);
                        skull.CantWalk = true;
                    }
                }

                Server.Regions.KhaldunRegion.DropHealthOrb(this);
            }

            if (!m_SpawnedSlowMob && this.Hits < (this.HitsMax * 40) / 100 && KhaldunRevenant.IsInsideKhaldun(this))
            {
                m_SpawnedSlowMob = true;
                FixedParticles(0x375A, 1, 17, 0x7DA, 0x960, 0x3, EffectLayer.Waist);
                PlaySound(0x51A);
                PublicOverheadMessage(MessageType.Regular, 193, true, "Undead Guardian");
                Blessed = true;
                Frozen = true;
                CantWalk = true;
                Timer.DelayCall(TimeSpan.FromSeconds(5), new TimerCallback(Teleport));
            }

            if (m_SpawnedSlowMob && this.Hits > (this.HitsMax * 90) / 100)
                m_SpawnedSlowMob = false;

            if (!InRange(from, 2) && Utility.RandomDouble() < 0.05)
            {
                FixedParticles(0x375A, 1, 17, 0x7DA, 0x960, 0x3, EffectLayer.Waist);
                MadSquirrel summon = new MadSquirrel(from, 1.0);
                summon.Name = "a shadow skeleton";
                summon.Body = Utility.RandomList(50, 56);
                summon.BaseSoundID = 0x48D;
                summon.Hue = 1;
                summon.MoveToWorld(this.Location, this.Map);
            }

            if (Utility.RandomDouble() < 0.005 && from.Player)
            {
                Waller(3, 6, from);
            }

            if (Utility.RandomDouble() < 0.005)
            {
                LysanderGathenwale.SummoningRing(this, typeof(Shade));
            }

            if (DateTime.Now > m_SilenceDelay && Utility.RandomDouble() < 0.01)
            {
                if (!IsUnderInfluence(from))
                {
                    m_SilenceDelay = DateTime.Now + TimeSpan.FromSeconds(30.0);
                    Silence(from, this);
                }
            }

            if (DateTime.Now > m_Delay && this.Hits < (this.HitsMax * 30) / 100)
            {
                m_Delay = DateTime.Now + TimeSpan.FromSeconds(Utility.RandomMinMax(30, 30));
                // Effects
                Effects.PlaySound(this.Location, this.Map, this.GetAngerSound());
                // 				EffectCircle( this.Location, this.Map, 6, typeof( Skeleton ), this );

                ArrayList targets = Utilitky.GetTargets(this, 6, true);

                for (int i = 0; i < targets.Count; ++i)
                {
                    Mobile m = (Mobile)targets[i];

                    if (m == null || m.Deleted)
                        continue;

                    m.RevealingAction();
                    m.FixedParticles(0x3709, 1, 30, 9965, 5, 7, EffectLayer.Waist);
                    m.FixedParticles(0x376A, 1, 30, 9502, 5, 3, EffectLayer.Waist);
                    m.PlaySound(0x231);

                    int auradamage = Engines.XmlSpawner2.XmlSpecial.PercentualDamage(Utility.RandomMinMax(15, 25), m);

                    if (m is Xanthos.Interfaces.IEvoCreature)
                        auradamage *= 2;

                    m.Hits -= auradamage;
                    ISTile5.SendDmgPacket(m, auradamage);

                    if (m.Hits < 2)
                        m.Kill();
                }
            }
        }

        #region Effects
        private void Teleport()
        {
            Location = new Point3D(5451, 1499, 10);
            // 			ProcessDelta();
            FixedParticles(0x376A, 9, 32, 0x13AF, EffectLayer.Waist);
            PlaySound(0x1FE);

            Zombie zombik = new Zombie();
            zombik.Hue = Utility.RandomNeutralHue() | 0x8000;
            zombik.Name = "a khal ankur guardian";

            zombik.SetHits(18000);
            zombik.SetStam(2500);

            zombik.SetDamage(15, 18);
            zombik.SetResistance(ResistanceType.Physical, 75);
            zombik.SetResistance(ResistanceType.Fire, 75);
            zombik.SetResistance(ResistanceType.Cold, 75);
            zombik.SetResistance(ResistanceType.Poison, 75);
            zombik.SetResistance(ResistanceType.Energy, 75);
            zombik.MoveToWorld(new Point3D(5451, 1484, 0), this.Map);
            zombik.CantWalk = true;

            Timer.DelayCall(TimeSpan.FromSeconds(3.0), new TimerStateCallback(MoveZombie), new object[] { zombik });
        }

        private void MoveZombie(object state)
        {
            object[] args = (object[])state;
            Mobile zombik = (Mobile)args[0];

            if (Deleted)
                return;

            if (zombik == null || zombik.Deleted || !zombik.Alive)
            {
                FixedParticles(0x376A, 9, 32, 0x13AF, EffectLayer.Waist);
                CantWalk = false;
                Blessed = false;
                Frozen = false;
                PublicOverheadMessage(MessageType.Regular, 193, false, "Let's finish this!");
                return;
            }

            if (zombik.Y == 1495)
            {
                PublicOverheadMessage(MessageType.Regular, 193, true, "BUM!");

                foreach (Mobile m in zombik.GetMobilesInRange(20))
                {
                    if (m != zombik && m.Player && zombik.CanBeHarmful(m) && m.AccessLevel == AccessLevel.Player && zombik.InLOS(m))
                    {
                        m.RevealingAction();
                        m.FixedParticles(0x373A, 1, 17, 0x7E2, EffectLayer.Waist);
                        m.PlaySound(505);
                        m.Kill();
                    }
                }

                FixedParticles(0x3709, 1, 30, 9965, 5, 7, EffectLayer.Waist);
                FixedParticles(0x376A, 1, 30, 9502, 5, 3, EffectLayer.Waist);
                PlaySound(0x231);

                zombik.Delete();
                this.Delete();

                return;
            }

            zombik.Y++;
            zombik.X = 5451;
            // 			zombik.FixedParticles( 0x376A, 9, 32, 0x13AF, EffectLayer.Waist );
            zombik.PlaySound(0x1FE);

            if (Utility.RandomBool())
                PublicOverheadMessage(MessageType.Regular, 193, false, "Come close my guardian!");

            Timer.DelayCall(TimeSpan.FromSeconds(3.0), new TimerStateCallback(MoveZombie), new object[] { zombik });
        }

        public static void Waller(int h1, int h2, Mobile from)
        {
            if (from == null)
                return;

            Map m = from.Map;

            if (m == null || m == Map.Internal)
                return;

            bool dir = Utility.RandomBool();
            Rectangle3D r = new Rectangle3D(from.X - 1, from.Y - 1, from.Z, dir ? h1 : h2, dir ? h2 : h1, 0);

            Point3D p1 = new Point3D(r.Start.X, r.Start.Y - 1, from.Z); //So we dont' need to create a new one each point
            Point3D p2 = new Point3D(r.Start.X, r.Start.Y + r.Height - 1, from.Z);  //So we dont' need to create a new one each point

            Effects.PlaySound(from.Location, from.Map, 0x1F6);

            SelfDeletingItem item;
            int skip = (r.Height > r.Width) ? Utility.RandomBool() ? 0 : 1 : Utility.RandomBool() ? 2 : 3;
            int itemID = Utility.RandomBool() ? 762 : 577;

            if (r.Height == r.Width) //ctverec bez vychodu
            {
                skip = 5;
                itemID = 577;
            }

            for (int x = r.Start.X; x <= (r.Start.X + r.Width - 1); x++)
            {
                p1.X = x;
                p2.X = x;

                p1.Z = from.Z;
                p2.Z = from.Z;

                if (skip != 0)
                {
                    item = new SelfDeletingItem(itemID, "a stone wall", 7); //North bound
                    Effects.SendLocationParticles(item, 0x376A, 9, 10, 5025);
                    item.MoveToWorld(p1, m);
                }

                if (skip != 1)
                {
                    item = new SelfDeletingItem(itemID, "a stone wall", 7); //South bound
                    Effects.SendLocationParticles(item, 0x376A, 9, 10, 5025);
                    item.MoveToWorld(p2, m);
                }
            }

            p1 = new Point3D(r.Start.X - 1, r.Start.Y - 1, from.Z);
            p2 = new Point3D(r.Start.X + r.Width - 1, r.Start.Y, from.Z);

            for (int y = r.Start.Y; y <= (r.Start.Y + r.Height - 1); y++)
            {
                p1.Y = y;
                p2.Y = y;

                p1.Z = from.Z;
                p2.Z = from.Z;

                if (skip != 2)
                {
                    item = new SelfDeletingItem(itemID + 1, "a stone wall", 7); //West bound
                    Effects.SendLocationParticles(item, 0x376A, 9, 10, 5025);
                    item.MoveToWorld(p1, m);
                }

                if (skip != 3)
                {
                    item = new SelfDeletingItem(itemID + 1, "a stone wall", 7); //East bound
                    Effects.SendLocationParticles(item, 0x376A, 9, 10, 5025);
                    item.MoveToWorld(p2, m);
                }
            }
        }

        private static Hashtable m_Table = new Hashtable();

        private class ExpireTimer : Timer
        {
            private Mobile m_Mobile;
            private Mobile m_From;

            public ExpireTimer(Mobile m, Mobile from) : base(TimeSpan.FromSeconds(30.0))
            {
                m_Mobile = m;
                m_From = from;
                Priority = TimerPriority.OneSecond;
            }

            protected override void OnTick()
            {
                Stop();
                m_Table.Remove(m_Mobile);

                if (m_Mobile.Alive)
                {
                    m_Mobile.FixedParticles(0x373A, 10, 15, 5012, EffectLayer.Waist);
                    m_Mobile.PlaySound(0x1E0);
                }

                m_Mobile.SendMessage("Silence faded");
            }
        }

        public static bool IsUnderInfluence(Mobile mobile)
        {
            if (mobile == null) return false;

            ExpireTimer timer = (ExpireTimer)m_Table[mobile];

            if (timer == null)
                return false;

            return true;
        }

        public static void Silence(Mobile victim, Mobile from)
        {
            if (victim != null && !victim.Deleted && victim.Player && victim.AccessLevel == AccessLevel.Player && victim.Alive)
            {
                if (CrusadersShield.FullCrusadersSetPresent(victim) || Spellbook.FindEquippedSpellbook(victim) != null)
                {
                    victim.SendMessage("Jsi odolny/a proti kouzlu Silence");
                    return;
                }

                from.PublicOverheadMessage(MessageType.Regular, 193, true, String.Format("Silence on {0}!", victim.RawName));
                victim.PlaySound(0x204);
                victim.FixedEffect(0x376A, 6, 1);

                ExpireTimer timer = new ExpireTimer(victim, from);

                timer.Start();
                m_Table[victim] = timer;
            }
        }

        #endregion

        public override bool AlwaysMurderer { get { return true; } }

        public KhalAnkur(Serial serial) : base(serial)
        {
        }

        public override void Serialize(GenericWriter writer)
        {
            base.Serialize(writer);

            writer.Write((int)0); // version
        }

        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);

            int version = reader.ReadInt();

            Hits = HitsMax;
            Blessed = false;
        }
    }
}