context: using Server;
  using System;
  using Server.Mobiles;
  using System.Collections.Generic;
  using System.Linq;
  
  namespace Server.Items
  {
      public class EodonPotionContext
      {
          public PotionEffect Type { get { return Potion.PotionEffect; } }
          public DateTime StartTime { get; set; }
          public DateTime Expires { get; set; }
          public EodonianPotion Potion { get; set; }
  
          public Timer Timer { get; set; }
  
          public EodonPotionContext(EodonianPotion potion)
          {
              Potion = potion;
              Expires = DateTime.UtcNow + potion.Cooldown;
              StartTime = DateTime.UtcNow;
          }
  
          public void OnTick(Mobile m)
          {
              if (DateTime.UtcNow >= Expires)
              {
                  Potion.EndEffects(m);
              }
              else
                  Potion.OnTick(m);
          }
  
          public void StopTimer()
          {
              if (Timer != null)
              {
                  Timer.Stop();
                  Timer = null;
              }
          }
      }
  
      public class EodonianPotion : BasePotion
      {
          public static Dictionary<Mobile, List<EodonPotionContext>> Contexts { get; set; }
          public static Timer Timer { get; set; }
  
          public virtual TimeSpan Cooldown { get { return TimeSpan.FromMinutes(20); } }
  
          public override int LabelNumber
          {
              get
              {
                  switch (this.PotionEffect)
                  {
                      default:
                      case PotionEffect.Barrab: return 1156724;
                      case PotionEffect.Jukari: return 1156726;
                      case PotionEffect.Kurak: return 1156728;
                      case PotionEffect.Barako: return 1156729;
                      case PotionEffect.Urali: return 1156734;
                      case PotionEffect.Sakkhra: return 1156732;
                  }
              }
          }
  
          public static void Initialize()
          {
              EventSink.PlayerDeath += new PlayerDeathEventHandler(EventSink_PlayerDeath);
          }
  
          public EodonianPotion(int id, PotionEffect effect)
              : base(id, effect)
          {
          }
  
          public override void Drink(Mobile m)
          {
              if (CanDoEffects(m))
              {
                  m.FixedEffect(0x375A, 10, 15);
                  m.PlaySound(0x1E7);
  
                  DoEffects(m);
                  BasePotion.PlayDrinkEffect(m);
  
                  Consume();
              }
          }
  
          public virtual void OnTick(Mobile m)
          {
          }
  
          public virtual bool CanDoEffects(Mobile m)
          {
              if (IsUnderEffects(m, this.PotionEffect))
              {
                  m.SendLocalizedMessage(502173); // You are already under a similar effect.
                  return false;
              }
  
              return true;
          }
  
          public virtual void DoEffects(Mobile m)
          {
              if (Contexts == null)
                  Contexts = new Dictionary<Mobile, List<EodonPotionContext>>();
  
              if (!Contexts.ContainsKey(m) || Contexts[m] == null)
                  Contexts[m] = new List<EodonPotionContext>();
  
              AddBuff(m);
  
              Contexts[m].Add(new EodonPotionContext(this));
              BeginTimer();
          }
  
          public virtual void EndEffects(Mobile m)
          {
              RemoveContext(m);
          }
  
          public void RemoveContext(Mobile m)
          {
              EodonPotionContext context = GetContext(m, this.PotionEffect);
  
              if (context != null)
                  RemoveContext(m, context);
          }
  
          public virtual void AddBuff(Mobile m)
          {
              switch (this.PotionEffect)
              {
                  case PotionEffect.Barrab:
                      BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.BarrabHemolymphConcentrate, LabelNumber, 1156738,"100\t10\t10\t5")); break;
                  case PotionEffect.Jukari:
                      BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.JukariBurnPoiltice, LabelNumber, 1156739,"10\t10\t10\t5")); break;
                  case PotionEffect.Kurak:
                      BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.KurakAmbushersEssence, LabelNumber, 1156740,"200")); break;
                  case PotionEffect.Barako:
                      BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.BarakoDraftOfMight, LabelNumber, 1156741,"10\t10\t5\t10")); break;
                  case PotionEffect.Urali:
                      BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.UraliTranceTonic, LabelNumber, 1156742,"10\t10\t10\t5")); break;
                  case PotionEffect.Sakkhra:
                      BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.SakkhraProphylaxis, LabelNumber, 1156743,"10\t10\t5\t10")); break;
              }
          }
  
          public virtual void RemoveBuff(Mobile m)
          {
              switch (this.PotionEffect)
              {
                  case PotionEffect.Barrab:
                      BuffInfo.RemoveBuff(m, BuffIcon.BarrabHemolymphConcentrate); break;
                  case PotionEffect.Jukari:
                      BuffInfo.RemoveBuff(m, BuffIcon.JukariBurnPoiltice); break;
                  case PotionEffect.Kurak:
                      BuffInfo.RemoveBuff(m, BuffIcon.KurakAmbushersEssence); break;
                  case PotionEffect.Barako:
                      BuffInfo.RemoveBuff(m, BuffIcon.BarakoDraftOfMight); break;
                  case PotionEffect.Urali:
                      BuffInfo.RemoveBuff(m, BuffIcon.UraliTranceTonic); break;
                  case PotionEffect.Sakkhra:
                      BuffInfo.RemoveBuff(m, BuffIcon.SakkhraProphylaxis); break;
              }
          }
  
          public static bool IsUnderEffects(Mobile m, PotionEffect effect)
          {
              return GetContext(m, effect) != null;
          }
  
          public static void RemoveEffects(Mobile m, PotionEffect effect)
          {
              RemoveContext(m, GetContext(m, effect));
          }
  
          public static EodonPotionContext GetContext(Mobile m, PotionEffect effect)
          {
              if (m == null)
                  return null;
  
              if (Contexts == null || !Contexts.ContainsKey(m) || Contexts[m] == null)
                  return null;
  
              return Contexts[m].FirstOrDefault(c => c.Type == effect);
          }
  
          public static void RemoveContext(Mobile m, PotionEffect effect)
          {
              RemoveContext(m, GetContext(m, effect));
          }
  
          public static void RemoveContext(Mobile m, EodonPotionContext context)
          {
              if (context == null)
                  return;
  
              if (context.Potion != null)
                  context.Potion.RemoveBuff(m);
  
              if (Contexts.ContainsKey(m))
              {
                  if (Contexts[m] != null && Contexts[m].Contains(context))
                  {
                      Contexts[m].Remove(context);
                  }
  
                  if (Contexts[m] == null || Contexts[m].Count == 0)
                      Contexts.Remove(m);
  
                  if (Contexts.Count == 0)
                      EndTimer();
  
                  m.Delta(MobileDelta.WeaponDamage);
              }
          }
  
          public static void BeginTimer()
          {
              if (Timer == null || !Timer.Running)
              {
                  Timer = Timer.DelayCall(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), OnTick);
                  Timer.Start();
              }
          }
  
          public static void EndTimer()
  		{
  			if(Timer != null)
  			{
                  Timer.Stop();
  				Timer = null;
  			}
  		}
  
          public static void OnTick()
          {
              if (Contexts == null)
                  EndTimer();
              else
              {
                  var dictionary = new Dictionary<Mobile, List<EodonPotionContext>>(Contexts);
  
                  foreach (var kvp in dictionary)
                  {
                      foreach (var context in kvp.Value)
                      {
                          context.OnTick(kvp.Key);
                      }
                  }
  
                  dictionary.Clear();
              }
          }
  
          public static void EventSink_PlayerDeath(PlayerDeathEventArgs e)
          {
              if (Contexts != null)
              {
                  if (e.Mobile != null && Contexts.ContainsKey(e.Mobile))
                      Contexts.Remove(e.Mobile);
  
                  if (Contexts.Count == 0)
                      EndTimer();
              }
          }
  
          public EodonianPotion(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 class BarrabHemolymphConcentrate : EodonianPotion
      {
          [Constructable]
          public BarrabHemolymphConcentrate() : this(1) { }
  
          [Constructable]
          public BarrabHemolymphConcentrate(int amount)
              : base(3846, PotionEffect.Barrab)
          {
  			Hue = 1272;
              Stackable = true;
              Amount = amount;
          }
  
          public override bool CanDoEffects(Mobile m)
          {
              if (MortalStrike.IsWounded(m))
              {
                  m.SendLocalizedMessage(1156869); // You may not use this with a mortal wound!
              }
              else if (m.Poison != null)
              {
                  m.SendLocalizedMessage(1156868); // You may not use this while poisoned!
              }
              else if (Server.Spells.Bushido.Confidence.IsConfident(m))
              {
                  m.SendLocalizedMessage(1156873); // You may not use this while under the effects of confidence!
              }
  
              return base.CanDoEffects(m);
          }
  
          public static int GetHitBuff(Mobile m)
          {
              EodonPotionContext c = GetContext(m, PotionEffect.Barrab);
  
              if (c != null && c.StartTime + TimeSpan.FromMinutes(5) > DateTime.UtcNow)
                  return 10;
  
              return 0;
          }
  
          public static int HPRegenBonus(Mobile m)
          {
              EodonPotionContext c = GetContext(m, PotionEffect.Barrab);
  
              if (c != null && c.StartTime + TimeSpan.FromMinutes(10) > DateTime.UtcNow)
                  return 100;
  
              return 0;
          }
  
          public BarrabHemolymphConcentrate(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);
  
gt:             int version = reader.ReadInt();