using Server;
using System;
using System.Collections.Generic;
using Server.Mobiles;
using Server.Targeting;
using Server.Multis;

namespace Server.Items
{
    public class CauldronOfTransmutation : BaseAddon
    {
        public const int DecayPeriod = 4;
        private int _Charges;

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

                if (_Charges <= 0 && this.RootParent is Mobile)
                    ((Mobile)RootParent).SendLocalizedMessage(1152635); // The cauldron's magic is exhausted

                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public DateTime Expires { get; set; }

        public Timer DecayTimer { get; private set; }

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

        public CauldronOfTransmutation()
        {
            Charges = 5000;

            AddComponent(new InternalComponent(2421), 0, 0, 0);

            Expires = DateTime.UtcNow + TimeSpan.FromHours(DecayPeriod);
            BeginTimer();
        }

        public void BeginTimer()
        {
            EndTimer();

            DecayTimer = Timer.DelayCall(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10), CheckDecay);
            DecayTimer.Start();
        }

        public void EndTimer()
        {
            if (DecayTimer != null)
            {
                DecayTimer.Stop();
                DecayTimer = null;
            }
        }

        public void CheckDecay()
        {
            if (Expires < DateTime.UtcNow)
                Decay();
            else
                InvalidateProperties();
        }

        public void Decay()
        {
            if (RootParent is Mobile)
            {
                Mobile parent = (Mobile)RootParent;

                if (Name == null)
                    parent.SendLocalizedMessage(1072515, "#" + LabelNumber); // The ~1_name~ expired...
                else
                    parent.SendLocalizedMessage(1072515, Name); // The ~1_name~ expired...

                Effects.SendLocationParticles(EffectItem.Create(parent.Location, parent.Map, EffectItem.DefaultDuration), 0x3728, 8, 20, 5042);
                Effects.PlaySound(parent.Location, parent.Map, 0x201);
            }
            else
            {
                Effects.SendLocationParticles(EffectItem.Create(this.Location, this.Map, EffectItem.DefaultDuration), 0x3728, 8, 20, 5042);
                Effects.PlaySound(this.Location, this.Map, 0x201);
            }

            Delete();
        }

        public override void Delete()
        {
            base.Delete();

            EndTimer();
        }

        public override void OnComponentUsed(AddonComponent c, Mobile from)
        {
            if (from.InRange(c.Location, 3))
            {
                BaseHouse house = BaseHouse.FindHouseAt(from);

                if (house != null && house.IsCoOwner(from))
                {
                    from.Target = new InternalTarget(this);
                    from.SendLocalizedMessage(1152738); // Target ingots in your backpack to transmute them.
                }
            }
        }

        public bool TryTransmutate(Mobile from, Item dropped)
        {
            BaseHouse house = BaseHouse.FindHouseAt(from);

            if (house != null && house.IsOwner(from))
            {
                CraftResource res = CraftResources.GetFromType(dropped.GetType());

                if (res == Resource)
                {
                    if (dropped.Amount < 3)
                        from.SendLocalizedMessage(1152634); // There is not enough to transmute
                    else if (Charges <= 0)
                        from.SendLocalizedMessage(1152635); // The cauldron's magic is exhausted
                    else
                    {
                        CraftResourceInfo info = CraftResources.GetInfo(Resource + 1);

                        if (info != null && info.ResourceTypes.Length > 0)
                        {
                            int toDrop = Math.Min(Charges * 3, dropped.Amount);
                            CraftResource newRes = (CraftResource)(int)res + 1;

                            while (toDrop % 3 != 0)
                                toDrop--;

                            int newAmount = toDrop / 3;

                            if (toDrop < dropped.Amount)
                                dropped.Amount -= toDrop;
                            else
                                dropped.Delete();

                            Item item = Loot.Construct(info.ResourceTypes[0]);

                            if (item != null)
                            {
                                item.Amount = newAmount;
                                from.AddToBackpack(item);

                                from.SendLocalizedMessage(1152636); // The cauldron transmutes the material

                                from.PlaySound(Utility.RandomList(0x22, 0x23));

                                Charges -= newAmount;
                                Components.ForEach(c => c.InvalidateProperties());

                                return true;
                            }
                        }
                        else
                            from.SendLocalizedMessage(1152633); // The cauldron cannot transmute that
                    }
                }

            }
            else
                from.SendLocalizedMessage(1152632); // That is not yours!

            return false;
        }

        private class InternalTarget : Target
        {
            public CauldronOfTransmutation Addon { get; set; }

            public InternalTarget(CauldronOfTransmutation addon)
                : base(-1, false, TargetFlags.None)
            {
                Addon = addon;
            }

            protected override void OnTarget(Mobile from, object targeted)
            {
                if (Addon == null || !from.InRange(Addon.Location, 3))
                    from.SendLocalizedMessage(500295); // You are too far away to do that.

                if (targeted is Item)
                    Addon.TryTransmutate(from, (Item)targeted);
            }
        }

        private class InternalComponent : AddonComponent
        {
            public override bool ForceShowProperties { get { return true; } }

            public InternalComponent(int id)
                : base(id)
            {
            }

            public override void AddNameProperty(ObjectPropertyList list)
            {
                if (Addon != null && Addon.Resource != CraftResource.None)
                    list.Add(1152600, String.Format("#{0}", CraftResources.GetLocalizationNumber(Addon.Resource).ToString())); // ~1_RES~ Cauldron of Transmutation
                else
                    base.AddNameProperty(list);
            }

            public override void GetProperties(ObjectPropertyList list)
            {
                base.GetProperties(list);

                if (Addon == null || !(Addon is CauldronOfTransmutation) || Addon.Resource == CraftResource.None)
                    return;

                int left = 0;
                if (DateTime.UtcNow < ((CauldronOfTransmutation)Addon).Expires)
                    left = (int)(((CauldronOfTransmutation)Addon).Expires - DateTime.UtcNow).TotalSeconds;

                list.Add(1072517, left.ToString()); // Lifespan: ~1_val~ seconds

                CraftResource res = Addon.Resource;
                CraftResource res2 = (CraftResource)(int)res + 1;

                list.Add(1152630, String.Format("#{0}\t#{1}", CraftResources.GetLocalizationNumber(Addon.Resource), CraftResources.GetLocalizationNumber(res2))); // transmutes ~1_SOURCE~ to ~2_DEST~
                list.Add(1152631, String.Format("3\t1")); // ratio ~1_INPUT~ to ~2_OUTPUT~
                list.Add(1060584, ((CauldronOfTransmutation)Addon).Charges.ToString()); // uses remaining: ~1_val~

            }

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

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

            public override void Deserialize(GenericReader reader)
            {
                base.Deserialize(reader);
                int version = reader.ReadInt();
            }
        }

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

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

            writer.Write(Expires);
        }

        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);
            int version = reader.ReadInt();

            Expires = reader.ReadDateTime();

            if (Expires < DateTime.UtcNow)
                Decay();
            else
                BeginTimer();
        }
    }

    public class CauldronOfTransmutationDeed : BaseAddonDeed
    {
        public override BaseAddon Addon { get { return new CauldronOfTransmutation(); } }

        public const int DecayPeriod = 24;

        private Timer m_Timer;

        [CommandProperty(AccessLevel.GameMaster)]
        public DateTime Expires { get; set; }

        [Constructable]
        public CauldronOfTransmutationDeed(CraftResource resource)
        {
            Resource = resource;

            Expires = DateTime.UtcNow + TimeSpan.FromHours(DecayPeriod);
            m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10), CheckDecay);
        }

        public void CheckDecay()
        {
            if (Expires < DateTime.UtcNow)
                Decay();
            else
                InvalidateProperties();
        }

        public void Decay()
        {
            if (RootParent is Mobile)
            {
                Mobile parent = (Mobile)RootParent;

                if (Name == null)
                    parent.SendLocalizedMessage(1072515, "#" + LabelNumber); // The ~1_name~ expired...
                else
                    parent.SendLocalizedMessage(1072515, Name); // The ~1_name~ expired...

                Effects.SendLocationParticles(EffectItem.Create(parent.Location, parent.Map, EffectItem.DefaultDuration), 0x3728, 8, 20, 5042);
                Effects.PlaySound(parent.Location, parent.Map, 0x201);
            }
            else
            {
                Effects.SendLocationParticles(EffectItem.Create(this.Location, this.Map, EffectItem.DefaultDuration), 0x3728, 8, 20, 5042);
                Effects.PlaySound(this.Location, this.Map, 0x201);
            }

            Delete();
        }

        public override void Delete()
        {
            base.Delete();

            if (m_Timer != null)
            {
                m_Timer.Stop();
                m_Timer = null;
            }
        }

        public override void AddNameProperty(ObjectPropertyList list)
        {
            list.Add(1152600, String.Format("#{0}", CraftResources.GetLocalizationNumber(Resource))); // ~1_RES~ Cauldron of Transmutation
        }

        public override void GetProperties(ObjectPropertyList list)
        {
            base.GetProperties(list);

            int left = 0;
            if (DateTime.UtcNow < Expires)
                left = (int)(Expires - DateTime.UtcNow).TotalSeconds;

            list.Add(1072517, left.ToString()); // Lifespan: ~1_val~ seconds
            list.Add(1152628); // cannot re-deed
            list.Add(1152629, CauldronOfTransmutation.DecayPeriod.ToString()); // lasts ~1_count~ hours
        }

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

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

            writer.Write(Expires);
        }

        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);
            int version = reader.ReadInt();

            Expires = reader.ReadDateTime();

            if (Expires < DateTime.UtcNow)
                Decay();
            else
                m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10), CheckDecay);
        }
    }
}