using System;
using System.Collections;
using System.Collections.Generic;
using Server;
using Server.Gumps;
using Server.Multis;
using Server.Network;
using Server.ContextMenus;
using Server.Engines.PartySystem;

namespace Server.Items
{
    public class TreasureMapChest : LockableContainer
    {
        public override int LabelNumber { get { return 1074025; } } //3000541

        public static Type[] Artifacts { get { return m_Artifacts; } }

        private static Type[] m_Artifacts = new Type[]
        {
            typeof( HearthOfHomeFireDeed ), typeof( HolySword ), typeof( HolyShield ), typeof( LeggingsOfEmbers ),
            typeof( RoseOfTrinsic ), typeof( SamuraiHelm ), typeof( ShaminoCrossbow ), typeof( TapestryOfSosaria ),

            typeof( CandelabraOfSouls ), typeof( GoldBricks ), typeof( PhillipsWoodenSteed ),
            typeof( ArcticDeathDealer ), typeof( BlazeOfDeath ), typeof( BurglarsBandana ),
            typeof( CavortingClub ), typeof( DreadPirateHat ),
            typeof( EnchantedTitanLegBone ), typeof( GwennosHarp ), typeof( IolosLute ),
            typeof( LunaLance ), typeof( NightsKiss ), typeof( NoxRangersHeavyCrossbow ),
            typeof( PolarBearMask ), typeof( VioletCourage ), typeof( HeartOfTheLion ),
            typeof( ColdBlood ), typeof( AlchemistsBauble )
        };

        private int m_Level;
        private DateTime m_DeleteTime;
        private Timer m_Timer;
        private Mobile m_Owner;
        private bool m_Temporary;

        private ArrayList m_Guardians;
        private ArrayList m_SecondaryGuardians;

        [CommandProperty(AccessLevel.GameMaster)]
        public int Level { get { return m_Level; } set { m_Level = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public Mobile Owner { get { return m_Owner; } set { m_Owner = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public DateTime DeleteTime { get { return m_DeleteTime; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public bool Temporary { get { return m_Temporary; } set { m_Temporary = value; } }

        public ArrayList Guardians { get { return m_Guardians; } }
        public ArrayList SecondaryGuardians { get { return m_SecondaryGuardians; } }

        [Constructable]
        public TreasureMapChest(int level) : this(null, level, false)
        {
        }

        public TreasureMapChest(Mobile owner, int level, bool temporary) : base(0xE40)
        {
            m_Owner = owner;
            m_Level = level;
            m_DeleteTime = DateTime.Now + TimeSpan.FromHours(1.5);

            m_Temporary = temporary;
            m_Guardians = new ArrayList();
            m_SecondaryGuardians = new ArrayList();

            m_Timer = new DeleteTimer(this, m_DeleteTime);
            m_Timer.Start();

            Fill(this, level, owner);
        }

        private static void GetRandomAOSStats(out int attributeCount, out int min, out int max, int level)
        {
            int rnd = Utility.Random((20 - level));

            if (rnd < 1)
            {
                attributeCount = Utility.RandomMinMax(4, 6);
                min = 80; max = 100;
            }
            else if (rnd < 3)
            {
                attributeCount = Utility.RandomMinMax(2, 6);
                min = 70; max = 100;
            }
            else if (rnd < 6)
            {
                attributeCount = Utility.RandomMinMax(2, 4);
                min = 60; max = 100;
            }
            else if (rnd < 10)
            {
                attributeCount = Utility.RandomMinMax(1, 4);
                min = 50; max = 100;
            }
            else
            {
                attributeCount = Utility.RandomMinMax(1, 3); ;
                min = 40; max = 70;
            }
        }

        private static void PlaceItemIn(Container parent, int x, int y, Item item)
        {
            parent.AddItem(item);
            item.Location = new Point3D(x, y, 0);
        }

        public static void Fill(LockableContainer cont, int level, Mobile owner)
        {
            cont.Movable = false;
            cont.Locked = true;

            if (level == 0)
            {
                cont.LockLevel = 0; // Can't be unlocked

                cont.DropItem(new Gold(Utility.RandomMinMax(50, 100)));

                if (Utility.RandomDouble() < 0.75)
                    cont.DropItem(new TreasureMap(0, Map.Trammel));
            }
            else
            {
                cont.TrapType = TrapType.ExplosionTrap;
                cont.TrapPower = level * 25;
                cont.TrapLevel = level;

                switch (level)
                {
                    case 1: cont.RequiredSkill = 36; break;
                    case 2: cont.RequiredSkill = 76; break;
                    case 3: cont.RequiredSkill = 84; break;
                    case 4: cont.RequiredSkill = 92; break;
                    case 5: cont.RequiredSkill = 100; break;
                    case 6: cont.RequiredSkill = 100; break;
                    case 7: cont.RequiredSkill = 100; break;
                    case 8: cont.RequiredSkill = 100; break;
                    case 9: cont.RequiredSkill = 100; break;
                }

                cont.LockLevel = cont.RequiredSkill - 10;
                cont.MaxLockLevel = cont.RequiredSkill + 40;

                //Scrolly
                TreasureMapChestBag scrollBag = new TreasureMapChestBag(cont);

                for (int i = 0; i < level * 5; ++i)
                    scrollBag.DropItem(Loot.RandomScroll(0, 63, SpellbookType.Regular));

                scrollBag.Name = "Magicke svitky";
                scrollBag.Hue = 195;
                PlaceItemIn(cont, 30, 51, scrollBag);

                //zbrane a brnko
                TreasureMapChestBag weaponBag = new TreasureMapChestBag(cont);
                TreasureMapChestBag armorBag = new TreasureMapChestBag(cont);
                TreasureMapChestBag jewelryBag = new TreasureMapChestBag(cont);

                for (int i = 0; i < level * 6; ++i)
                {
                    Item item;

                    //if ( Core.AOS )
                    item = Loot.RandomArmorOrShieldOrWeaponOrJewelry();
                    /*else
						item = Loot.RandomArmorOrShieldOrWeapon();*/

                    if (item is BaseWeapon)
                    {
                        BaseWeapon weapon = (BaseWeapon)item;

                        if (0.75 > Utility.RandomDouble()) //Core.AOS
                        {
                            int attributeCount;
                            int min, max;

                            GetRandomAOSStats(out attributeCount, out min, out max, level);

                            BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max);
                        }
                        else
                        {
                            weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(6);
                            weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(6);
                            weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(6);
                        }

                        weaponBag.DropItem(item);
                    }
                    else if (item is BaseArmor)
                    {
                        BaseArmor armor = (BaseArmor)item;

                        if (0.75 > Utility.RandomDouble())
                        {
                            int attributeCount;
                            int min, max;

                            GetRandomAOSStats(out attributeCount, out min, out max, level);

                            BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max);
                        }
                        else
                        {
                            armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(6);
                            armor.Durability = (ArmorDurabilityLevel)Utility.Random(6);
                        }

                        armorBag.DropItem(item);
                    }
                    else if (item is BaseJewel)
                    {
                        int attributeCount;
                        int min, max;

                        GetRandomAOSStats(out attributeCount, out min, out max, level);

                        BaseRunicTool.ApplyAttributesTo((BaseJewel)item, attributeCount, min, max);

                        jewelryBag.DropItem(item);
                    }
                }

                weaponBag.Name = "Zbrane";
                weaponBag.Hue = 39;
                PlaceItemIn(cont, 30, 130, weaponBag);

                armorBag.Name = "Brneni";
                armorBag.Hue = 215;
                PlaceItemIn(cont, 70, 130, armorBag);

                jewelryBag.Name = "Sperky";
                jewelryBag.Hue = 996;
                PlaceItemIn(cont, 110, 130, jewelryBag);

                cont.DropItem(new Gold((level > 6) ? (level * 1000) * 2 : level * 1000));

                if (level > 8)
                    cont.DropItem(new Gold(level * 1000));
            }

            int reagents;
            if (level == 0)
                reagents = 12;
            else
                reagents = level * 3;

            //regy
            TreasureMapChestBag reagentBag = new TreasureMapChestBag(cont);

            for (int i = 0; i < reagents; i++)
            {
                Item item = Loot.RandomPossibleReagent();
                item.Amount = Utility.RandomMinMax(40, 60);
                reagentBag.DropItem(item);
            }

            reagentBag.Name = "Reagenty";
            reagentBag.Hue = 374;
            PlaceItemIn(cont, 70, 51, reagentBag);

            //gemy
            TreasureMapChestBag gemBag = new TreasureMapChestBag(cont);

            int gems;
            if (level == 0)
                gems = 2;
            else
                gems = level * 3;

            for (int i = 0; i < gems; i++)
            {
                Item item = Loot.RandomGem();
                gemBag.DropItem(item);
            }

            gems = level;

            if (level > 6)
                gems = level * 2;

            for (int i = 0; i < gems; i++)
            {
                Item item = Loot.RandomMLGem();
                gemBag.DropItem(item);
            }

            gemBag.Name = "Drahokamy";
            gemBag.Hue = 45;
            PlaceItemIn(cont, 110, 51, gemBag);

            if (level > 5 && Core.AOS)
                cont.DropItem((Item)Activator.CreateInstance(m_Artifacts[Utility.Random(m_Artifacts.Length)]));

            //======= START - PRIDANE VECI

            //powerscroll
            if (Utility.RandomDouble() < 0.01 || level > 6)
            {
                int slevel;
                double random = Utility.RandomDouble();

                if (0.1 >= random)
                    slevel = 20;
                else if (0.3 >= random)
                    slevel = 15;
                else if (0.6 >= random)
                    slevel = 10;
                else
                    slevel = 5;

                if (level == 4 && slevel > 15)
                    slevel = 10;
                else if (level < 4 && slevel > 10)
                    slevel = 5;

                switch (Utility.Random(3))
                {
                    case 0: // skill scroll
                        {
                            PowerScroll ps = PowerScroll.CreateRandom(slevel, slevel);
                            cont.DropItem(ps);
                            break;
                        }
                    case 1: // item level scroll LevelUpScroll
                        {
                            //                   LevelUpScroll ls = LevelUpScroll(slevel);
                            cont.DropItem(new LevelUpScroll(slevel));
                            break;
                        }
                    case 2: // pet scroll
                        {
                            PetPowerScroll pps = PetPowerScroll.CreateRandom(slevel, slevel);
                            cont.DropItem(pps);
                            break;
                        }
                }
            }
            //level item
            if (Utility.RandomDouble() < 0.01 || level > 6)
            {
                cont.DropItem(Loot.RandomLevelItem(true));

                if (level > 6)
                {
                    if (level > 8)
                        cont.DropItem((Item)Activator.CreateInstance(Mobiles.Teragon.Artifacts[Utility.Random(Mobiles.Teragon.Artifacts.Length)]));

                    if (Utility.RandomDouble() < 0.4 || level > 7)
                        cont.DropItem((Item)Activator.CreateInstance(Mobiles.Teragon.Artifacts[Utility.Random(Mobiles.Teragon.Artifacts.Length)]));

                    cont.DropItem(new RandomTalisman());
                    cont.DropItem(new MagicalWire(Utility.RandomMinMax(1, 2)));
                    // 			      cont.DropItem( (Item)Activator.CreateInstance( TreasureMessageChest.Artifacts[Utility.Random(TreasureMessageChest.Artifacts.Length)] ) );
                    // 			      cont.DropItem( (Item)Activator.CreateInstance( TreasureMessageChest.Artifacts[Utility.Random(TreasureMessageChest.Artifacts.Length)] ) );
                    if (Utility.RandomDouble() < 0.5 || level > 8)
                        cont.DropItem((Item)Activator.CreateInstance(Mobiles.Paragon.MLMiniArtifacts[Utility.Random(Mobiles.Paragon.MLMiniArtifacts.Length)]));
                }
            }
            //runic tool nebo talisman
            if (Utility.RandomDouble() < 0.05 || level > 6)
            {
                if (Utility.RandomBool() || level > 6)
                    cont.DropItem(Loot.RandomRunicTool());
                else
                    cont.DropItem(new RandomTalisman());
            }
            //Mesicni Kamen, draty, scrolly
            if (level > 8)
            {
                cont.DropItem(new MesicniKamen(Utility.RandomMinMax(1, 3)));
                cont.DropItem(new MagicalWire(Utility.RandomMinMax(2, 3)));

                if (Utility.RandomDouble() < 0.1)
                    cont.DropItem(new MagicScroll(1, true));
                else
                    cont.DropItem(new MagicScroll());
            }
            if (Utility.RandomDouble() < 0.0005 || ((level > 6 && Utility.RandomDouble() < 0.05) || level > 8))
            {
                cont.DropItem(new PotionPouch());
            }
            //PS Tokeny
            if (Utility.RandomDouble() < 0.05 || ((level > 6 && Utility.RandomDouble() < 0.70) || level > 8))
            {
                cont.DropItem(new PSToken((level > 6) ? ((level > 8) ? 5 : 3) : 1));
            }
            //Powder Of Translocation
            if (Utility.RandomDouble() < 0.1 || ((level > 6 && Utility.RandomDouble() < 0.70) || level > 8))
            {
                cont.DropItem(new PowderOfTranslocation((level > 6) ? ((level > 8) ? 100 : 50) : Utility.RandomMinMax(5, 20)));
            }
            //Evo Dust
            if (Utility.RandomDouble() < 0.2 || ((level > 6 && Utility.RandomDouble() < 0.60) || level > 8))
            {
                int dusts = ((level > 6) ? ((level > 8) ? 2500 : 1000) : (level > 4) ? 500 : 250);

                if (Utility.RandomBool())
                {
                    if (level > 4 && Utility.RandomBool())
                        cont.DropItem(new Xanthos.Evo.RaelisDemonioDust(dusts));
                    else
                        cont.DropItem(new Xanthos.Evo.RaelisDragonDust(dusts));
                }
                else
                {
                    if (level > 4 && Utility.RandomBool())
                        cont.DropItem(new Xanthos.Evo.EvoSpiderDust(dusts));
                    else
                        cont.DropItem(new Xanthos.Evo.HiryuEvoDust(dusts));
                }
            }
            //Powder Of Temperament
            if (Utility.RandomDouble() < 0.05 || ((level > 6 && Utility.RandomDouble() < 0.10) || level > 8))
            {
                cont.DropItem(new PowderOfTemperament((level > 6) ? ((level > 8) ? 10 : 5) : 2));
            }
            //dye tub
            if (Utility.RandomDouble() < 0.03 || ((level > 6 && Utility.RandomDouble() < 0.70) || level > 8))
            {
                int theHue = ((level > 6 && Utility.RandomDouble() < 0.25) || level > 7) ?
                   (Utility.RandomBool() ? Utility.RandomMinMax(1909, 1976) : Utility.RandomMinMax(1568, 1600)) :
                   Utility.RandomMinMax(1150, 1177);

                AllDyeTubsAll dt = new AllDyeTubsAll();
                dt.DyedHue = theHue;
                dt.Hue = theHue;
                dt.Charges = (theHue > 1200) ? Utility.RandomMinMax(1, 2) : Utility.RandomMinMax(1, 5);
                cont.DropItem(dt);
            }

            double piecechance = 0.02;

            switch (level)
            {
                case 2: piecechance = 0.05; break;
                case 3: piecechance = 0.08; break;
                case 4: piecechance = 0.15; break;
                case 5: piecechance = 0.3; break;
                case 6: piecechance = 0.4; break;
                case 7: piecechance = 0.6; break;
                case 8: piecechance = 0.9; break;
                case 9: piecechance = 1.00; break;
            }

            //Treasure map piece
            if (Utility.RandomDouble() < piecechance)
            {
                if (level < 6)
                    cont.DropItem(new TreasureMapPiece());
                else if (level < 8)
                    cont.DropItem(new TreasureMapPieceRare());
                else
                    cont.DropItem(new TreasureMapPieceAncient());
            }
            //ParchmentMessage
            if (Utility.RandomDouble() < 0.01)
            {
                cont.DropItem(new ParchmentMessage((Utility.RandomDouble() < 0.95) ? Map.Trammel : Map.Felucca, (level > 6) ? 5 : level));
            }
            //Guild Coins
            if (owner != null && Guilds.Guild.GainChance(owner, 1, 10))
            {
                cont.DropItem(new GuildCoin(level * 1000));
            }
            //Charm of luck items
            if (owner != null && level > 6 && owner.Backpack.ConsumeTotal(typeof(CharmOfLuck), 1))
            {
                Bag charmbag = new Bag();
                charmbag.Hue = 2577;
                charmbag.Name = "Bag of Luck [" + owner.RawName + "]";

                charmbag.DropItem(new SpendingPointsScroll());

                double skillBonus = (double)owner.Skills[SkillName.Cartography].Value / 1000.0;

                owner.SendMessage("Charm of luck pouzit");
                owner.SendMessage("Cartography bonus na nalezeni predmetu: +{0:F2}%", skillBonus * 100);

                if (Utility.RandomDouble() < 0.5 + skillBonus)
                    charmbag.DropItem((Item)Activator.CreateInstance(ASoullessBlade.ExtraLoot[Utility.Random(ASoullessBlade.ExtraLoot.Length)]));

                if (Utility.RandomDouble() < 0.1 + skillBonus)
                    charmbag.DropItem((Item)Activator.CreateInstance(ASoullessBlade.ExtraLoot[Utility.Random(ASoullessBlade.ExtraLoot.Length)]));

                if (Utility.RandomDouble() < 0.4 + skillBonus)
                    charmbag.DropItem((Item)Activator.CreateInstance(Mobiles.Teragon.Artifacts[Utility.Random(Mobiles.Teragon.Artifacts.Length)]));

                if (Utility.RandomDouble() < 0.1 + skillBonus)
                    charmbag.DropItem((Item)Activator.CreateInstance(Mobiles.Teragon.Artifacts[Utility.Random(Mobiles.Teragon.Artifacts.Length)]));

                if (Utility.RandomDouble() < 0.1 + skillBonus)
                    charmbag.DropItem((Item)Activator.CreateInstance(Mobiles.Teragon.Artifacts[Utility.Random(Mobiles.Teragon.Artifacts.Length)]));

                if (Utility.RandomDouble() < 0.15 + skillBonus)
                    charmbag.DropItem(ClothingSkillScroll.CreateRandom(1, Utility.RandomList(1, 1, 1, 1, 1, 1, 2, 2, 2)));

                if (Utility.RandomDouble() < 0.5 + skillBonus)
                {
                    ClothingSkillScroll cs = new ClothingSkillScroll(SkillName.Cartography, 1.0);
                    cs.BlessedFor = owner;
                    charmbag.DropItem(cs);
                }

                if (Utility.RandomDouble() < 0.25 + skillBonus)
                    charmbag.DropItem(new ArtifactFragment(Utility.RandomList(2, 2, 3, 3, 4, 5, 5, 5, 6, 7, 8)));

                if (Utility.RandomDouble() < 0.3 + skillBonus)
                {
                    CommodityDeed cDeed = new CommodityDeed();
                    Item comm = Loot.RandomResource();
                    comm.Amount = Utility.RandomMinMax(100, 500);

                    if (comm is Cloth)
                        comm.Hue = Utility.RandomMinMax(2432, 2513);

                    cDeed.SetCommodity(comm);
                    charmbag.DropItem(cDeed);
                }

                if (Utility.RandomDouble() < 0.2 + skillBonus)
                    charmbag.DropItem(new CechovniMince(Utility.RandomMinMax(10, 75)));

                cont.DropItem(charmbag);
            }


            //======= END - PRIDANE VECI
        }

        public override bool CheckLocked(Mobile from)
        {
            if ( /*this.Level == 0 && */from.AccessLevel < AccessLevel.GameMaster)
            {
                foreach (Mobile m in this.Guardians)
                {
                    if (m.Alive)
                    {
                        from.SendLocalizedMessage(1046448); // You must first kill the guardians before you may open this chest.
                        return true;
                    }
                }

                return base.CheckLocked(from);
            }
            else
            {
                return base.CheckLocked(from);
            }
        }

        public ArrayList m_Lifted = new ArrayList();

        private bool CheckLoot(Mobile m, bool criminalAction)
        {
            if (m_Temporary)
                return false;

            if (m.AccessLevel >= AccessLevel.GameMaster || m_Owner == null || m == m_Owner)
                return true;

            Party p = Party.Get(m_Owner);

            if (p != null && p.Contains(m))
                return true;

            Map map = this.Map;

            if (map != null && (map.Rules & MapRules.HarmfulRestrictions) == 0)
            {
                if (criminalAction)
                    m.CriminalAction(true);
                else
                    m.SendLocalizedMessage(1010630); // Taking someone else's treasure is a criminal offense!

                return true;
            }

            m.SendLocalizedMessage(1010631); // You did not discover this chest!
            return false;
        }

        public override bool IsDecoContainer
        {
            get { return false; }
        }

        public override bool CheckItemUse(Mobile from, Item item)
        {
            return CheckLoot(from, item != this) && base.CheckItemUse(from, item);
        }

        public override bool CheckLift(Mobile from, Item item, ref LRReason reject)
        {
            return CheckLoot(from, true) && base.CheckLift(from, item, ref reject);
        }

        public override void OnItemLifted(Mobile from, Item item)
        {
            bool notYetLifted = !m_Lifted.Contains(item);

            from.RevealingAction();

            if (notYetLifted)
            {
                m_Lifted.Add(item);

                if (0.1 >= Utility.RandomDouble() && from.AccessLevel < AccessLevel.GameMaster) // 10% chance to spawn a new monster
                    TreasureMap.Spawn(m_Level, GetWorldLocation(), Map, from, false, this);
            }

            base.OnItemLifted(from, item);
        }

        public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight)
        {
            if (m.AccessLevel < AccessLevel.GameMaster)
            {
                m.SendLocalizedMessage(1048122, "", 0x8A5); // The chest refuses to be filled with treasure again.
                return false;
            }

            return base.CheckHold(m, item, message, checkItems, plusItems, plusWeight);
        }

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

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

            writer.Write((int)3); // version 

            writer.WriteMobileList(m_SecondaryGuardians, true);
            writer.WriteMobileList(m_Guardians, true);
            writer.Write((bool)m_Temporary);

            writer.Write(m_Owner);

            writer.Write((int)m_Level);
            writer.WriteDeltaTime(m_DeleteTime);
            writer.WriteItemList(m_Lifted, true);
        }

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

            int version = reader.ReadInt();

            switch (version)
            {
                case 3:
                    {
                        m_SecondaryGuardians = reader.ReadMobileList();

                        goto case 2;
                    }
                case 2:
                    {
                        m_Guardians = reader.ReadMobileList();
                        m_Temporary = reader.ReadBool();

                        goto case 1;
                    }
                case 1:
                    {
                        m_Owner = reader.ReadMobile();

                        goto case 0;
                    }
                case 0:
                    {
                        m_Level = reader.ReadInt();
                        m_DeleteTime = reader.ReadDeltaTime();
                        m_Lifted = reader.ReadItemList();

                        if (version < 2)
                            m_Guardians = new ArrayList();

                        if (version < 3)
                            m_SecondaryGuardians = new ArrayList();

                        break;
                    }
            }

            if (!m_Temporary)
            {
                m_Timer = new DeleteTimer(this, m_DeleteTime);
                m_Timer.Start();
            }
            else
            {
                Delete();
            }
        }

        public override void OnAfterDelete()
        {
            if (m_Timer != null)
                m_Timer.Stop();

            m_Timer = null;

            foreach (Mobile m in this.Guardians)
            {
                if (m == null || m.Deleted)
                    continue;

                m.Delete();
            }

            foreach (Mobile m in this.SecondaryGuardians)
            {
                if (m == null || m.Deleted)
                    continue;

                m.Delete();
            }

            base.OnAfterDelete();
        }

        public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
        {
            base.GetContextMenuEntries(from, list);

            if (from.Alive)
                list.Add(new RemoveEntry(from, this));
        }

        public void BeginRemove(Mobile from)
        {
            if (!from.Alive)
                return;

            from.CloseGump(typeof(RemoveGump));
            from.SendGump(new RemoveGump(from, this));
        }

        public void EndRemove(Mobile from)
        {
            if (Deleted || from != m_Owner || !from.InRange(GetWorldLocation(), 3))
                return;

            from.SendLocalizedMessage(1048124, "", 0x8A5); // The old, rusted chest crumbles when you hit it.
            this.Delete();
        }

        private class RemoveGump : Gump
        {
            private Mobile m_From;
            private TreasureMapChest m_Chest;

            public RemoveGump(Mobile from, TreasureMapChest chest) : base(15, 15)
            {
                m_From = from;
                m_Chest = chest;

                Closable = false;
                Disposable = false;

                AddPage(0);

                AddBackground(30, 0, 240, 240, 2620);

                AddHtmlLocalized(45, 15, 200, 80, 1048125, 0xFFFFFF, false, false); // When this treasure chest is removed, any items still inside of it will be lost.
                AddHtmlLocalized(45, 95, 200, 60, 1048126, 0xFFFFFF, false, false); // Are you certain you're ready to remove this chest?

                AddButton(40, 153, 4005, 4007, 1, GumpButtonType.Reply, 0);
                AddHtmlLocalized(75, 155, 180, 40, 1048127, 0xFFFFFF, false, false); // Remove the Treasure Chest

                AddButton(40, 195, 4005, 4007, 2, GumpButtonType.Reply, 0);
                AddHtmlLocalized(75, 197, 180, 35, 1006045, 0xFFFFFF, false, false); // Cancel
            }

            public override void OnResponse(NetState sender, RelayInfo info)
            {
                if (info.ButtonID == 1)
                    m_Chest.EndRemove(m_From);
            }
        }

        private class RemoveEntry : ContextMenuEntry
        {
            private Mobile m_From;
            private TreasureMapChest m_Chest;

            public RemoveEntry(Mobile from, TreasureMapChest chest) : base(6149, 3)
            {
                m_From = from;
                m_Chest = chest;

                Enabled = (from == chest.Owner);
            }

            public override void OnClick()
            {
                if (m_Chest.Deleted || m_From != m_Chest.Owner || !m_From.CheckAlive())
                    return;

                m_Chest.BeginRemove(m_From);
            }
        }

        private class DeleteTimer : Timer
        {
            private Item m_Item;

            public DeleteTimer(Item item, DateTime time) : base(time - DateTime.Now)
            {
                m_Item = item;
                Priority = TimerPriority.OneMinute;
            }

            protected override void OnTick()
            {
                m_Item.Delete();
            }
        }
    }
}