context: using System;
  using Server;
  using Server.Targeting;
  using Server.Mobiles;
  using Server.Network;
  using Server.Items;
  using Server.Gumps;
  using System.Collections;
  using System.Collections.Generic;
  using Server.ContextMenus;
  using Server.Commands;
  using Server.Factions;
  using Server.Engines.Craft;
  using System.Linq;
  
  namespace Server.SkillHandlers
  {
      public class Imbuing
      {
          public static void Initialize()
          {
              //LoadImbuingDefinitions();
  
              SkillInfo.Table[(int)SkillName.Imbuing].Callback = new SkillUseCallback(OnUse);
  
              CommandSystem.Register("GetTotalWeight", AccessLevel.GameMaster, new CommandEventHandler(GetTotalWeight_OnCommand));
              CommandSystem.Register("GetTotalMods", AccessLevel.GameMaster, new CommandEventHandler(GetTotalMods_OnCommand));
          }
  
          private static Dictionary<Mobile, ImbuingContext> m_ContextTable = new Dictionary<Mobile, ImbuingContext>();
          public static Dictionary<Mobile, ImbuingContext> ContextTable { get { return m_ContextTable; } }
  
          public static TimeSpan OnUse(Mobile from)
          {
              if (!from.Alive)
                  from.SendLocalizedMessage(500949); //You can't do that when you're dead.
              else
              {
                  from.CloseGump(typeof(ImbuingGump));
                  from.SendGump(new ImbuingGump(from));
              }
  
              return TimeSpan.FromSeconds(1.0);
          }
  
          public static ImbuingContext GetContext(Mobile m)
          {
              if (!m_ContextTable.ContainsKey(m))
              {
                  ImbuingContext context = new ImbuingContext(m);
                  m_ContextTable[m] = context;
                  return context;
              }
  
              return m_ContextTable[m];
          }
  
          public static void AddContext(Mobile from, ImbuingContext context)
          {
              m_ContextTable[from] = context;
          }
  
          public static bool CanImbueItem(Mobile from, Item item)
          {
              if (item == null || !item.IsChildOf(from.Backpack))
                  from.SendLocalizedMessage(1079575);  // The item must be in your backpack to imbue it.
              else if (item.LootType == LootType.Blessed || item.LootType == LootType.Newbied)
                  from.SendLocalizedMessage(1080438);  // You cannot imbue a blessed item.
              else if (item is BaseWeapon && Spells.Mysticism.EnchantSpell.IsUnderSpellEffects(from, (BaseWeapon)item))
                  from.SendLocalizedMessage(1080130);  // You cannot imbue an item that is currently enchanted.
              else if (item is BaseWeapon && ((BaseWeapon)item).FocusWeilder != null)
                  from.SendLocalizedMessage(1080444);  //You cannot imbue an item that is under the effects of the ninjitsu focus attack ability.
              else if (IsSpecialItem(item))
                  from.SendMessage("You cannot imbue an item with such strange magical properties.");
              else if (item is IFactionItem && ((IFactionItem)item).FactionItemState != null)
                  from.SendLocalizedMessage(1114312); // You cannot imbue faction items.
              else if (item is BaseJewel && !(item is BaseRing) && !(item is BaseBracelet))
                  from.SendLocalizedMessage(1079576); // You cannot imbue this item.
              else if (IsInNonImbueList(item.GetType()))
                  from.SendLocalizedMessage(1079576); // You cannot imbue this item.
              else if (item is BaseWeapon && ((BaseWeapon)item).TimesImbued >= 20)
                  from.SendMessage("This item has been modified too many times and cannot be imbued any further.");
              else if (item is BaseArmor && ((BaseArmor)item).TimesImbued >= 20)
                  from.SendMessage("This item has been modified too many times and cannot be imbued any further.");
              else if (item is BaseJewel && ((BaseJewel)item).TimesImbued >= 20)
                  from.SendMessage("This item has been modified too many times and cannot be imbued any further.");
              else if (item is BaseHat && ((BaseHat)item).TimesImbued >= 20)
                  from.SendMessage("This item has been modified too many times and cannot be imbued any further.");
              else
                  return true;
  
              return false;
          }
  
          public static bool OnBeforeImbue(Mobile from, Item item, int mod, int value)
          {
              return OnBeforeImbue(from, item, mod, value, Imbuing.GetTotalMods(item, mod), ImbuingGumpC.MaxProps, Imbuing.GetTotalWeight(item, mod), Imbuing.GetMaxWeight(item));
          }
  
          public static bool OnBeforeImbue(Mobile from, Item item, int mod, int value, int totalprops, int maxprops, int totalitemweight, int maxweight)
          {
              if (totalprops >= maxprops || totalitemweight > maxweight)
              {
                  from.SendLocalizedMessage(1079772); // You cannot imbue this item with any more item properties.
                  from.CloseGump(typeof(ImbuingGumpC));
                  return false;
              }
  
              return true;
          }
  
          public static bool CanUnravelItem(Mobile from, Item item, bool message = true)
          {
              if (!item.IsChildOf(from.Backpack))
              {
                  if(message)
                      from.SendLocalizedMessage(1080424);  // The item must be in your backpack to magically unravel it.
              }
              else if (item.LootType == LootType.Blessed || item.LootType == LootType.Newbied)
              {
                  if (message)
                      from.SendLocalizedMessage(1080421);  // You cannot unravel the magic of a blessed item.
              }
              else if (item is BaseWeapon && Spells.Mysticism.EnchantSpell.IsUnderSpellEffects(from, (BaseWeapon)item))
              {
                  if (message)
                      from.SendLocalizedMessage(1080427);  // You cannot magically unravel an item that is currently enchanted.
              }
              else if (item is BaseWeapon && ((BaseWeapon)item).FocusWeilder != null)
              {
                  if (message)
                      from.SendLocalizedMessage(1080445); //You cannot magically unravel an item that is under the effects of the ninjitsu focus attack ability.
              }
              else if (item is IFactionItem && ((IFactionItem)item).FactionItemState != null)
              {
                  if (message)
                      from.SendLocalizedMessage(1112408); // You cannot magically unravel a faction reward item.
              }
              else
                  return true;
              return false;
          }
  
          public static bool IsSpecialItem(Item item)
          {
              if (item == null)
                  return true;
  
              if (IsSpecialImbuable(item))
                  return false;
  
  			if (item.IsArtifact)
  				return true;
  
              if (RunicReforging.GetArtifactRarity(item) > 0)
                  return true;
  
  			if (item.GetType() == typeof(SilverRing) || item.GetType() == typeof(SilverBracelet))
  				return false;
  
              foreach (CraftSystem system in CraftSystem.Systems)
              {
                  CraftItem crItem = null;
                  
                  if(system != null && system.CraftItems != null)
                      crItem = system.CraftItems.SearchFor(item.GetType());
  
                  if (crItem != null)
                      return false;
              }
  
              return true;
          }
  
          private static bool IsSpecialImbuable(Item item)
          {
              foreach (Type type in _SpecialImbuable)
                  if (item.GetType() == type)
                      return true;
  
              return false;
          }
  
          private static Type[] _SpecialImbuable =
          {
              typeof(ClockworkLeggings), typeof(GargishClockworkLeggings)
          };
  
          public static double GetSuccessChance(Mobile from, Item item, int totalItemWeight, int propWeight, out double dif)
          {
              double suc = 0;     // display difficulty
              double bonus = 0;   // bonuses
  
              ImbuingContext context = GetContext(from);
              double skill = from.Skills[SkillName.Imbuing].Value;
  
              // - Racial Bonus - SA ONLY -
              if (from.Race == Race.Gargoyle)
                  bonus = 10;
  
              // Queen Soul Forge Bonus
              if (context.Imbue_SFBonus > 0)
                  bonus += context.Imbue_SFBonus;
  
              bonus += GetQualityBonus(item);
              bonus /= 100;
  
              double resultWeight = totalItemWeight + propWeight;
  
              if (resultWeight <= 500)
              {
                  dif = (((resultWeight) / 22) * (1)) + ((resultWeight) / 8);
                  suc = ((skill - dif) * 1);
              }
              else
              {
                  dif = ((((resultWeight) - 500) / 75) * (1)) + (((resultWeight) - 500) / 64);
                  suc = ((skill - (dif + 64)) * 1) + bonus;
              }
  
              suc += suc * bonus;
  
              if (suc < 0)
                  suc = 0;
  
              if (suc > 100 && from.AccessLevel == AccessLevel.Player) //display purposes
                  suc = 100;
  
              suc = Math.Round(suc, 2);
  
              return suc;
          }
  
          public static int GetQualityBonus(Item item)
          {
              if (item is BaseWeapon)
              {
                  if (((BaseWeapon)item).Quality == WeaponQuality.Exceptional)
                      return 20;
  
                  if (((BaseWeapon)item).PlayerConstructed)
                      return 10;
              }
              else if (item is BaseArmor)
              {
                  if (((BaseArmor)item).Quality == ArmorQuality.Exceptional)
                      return 20;
  
                  if (((BaseArmor)item).PlayerConstructed)
                      return 10;
              }
              else if (item is BaseHat)
              {
                  if (((BaseHat)item).Quality == ClothingQuality.Exceptional)
                      return 20;
  
                  if (((BaseHat)item).PlayerConstructed)
                      return 10;
              }
              else if (item is BaseJewel)
              {
              }
  
              return 0;
          }
  
          /// <summary>
          /// Imbues Item with selected mod
          /// </summary>
          /// <param name="from">Player Imbuing</param>
          /// <param name="i">Item to be imbued</param>
          /// <param name="mod">mod to be imbued, see m_Table</param>
          /// <param name="value">value for mod</param>
          public static void ImbueItem(Mobile from, Item i, int mod, int value)
          {
              if (!CheckSoulForge(from, 1))
                  return;
  
              ImbuingContext context = Imbuing.GetContext(from);
  
              context.LastImbued = i;
              context.Imbue_Mod = mod;
              context.Imbue_ModInt = value;
  
              if (!Imbuing.Table.ContainsKey(mod))
                  return;
  
              ImbuingDefinition def = Imbuing.Table[mod];
              Type gem = def.GemRes;
              Type primary = def.PrimaryRes;
              Type special = def.SpecialRes;
              context.Imbue_ModVal = def.Weight;
  
              int itemRef = ImbuingGump.GetItemRef(i);
              int gemAmount = GetGemAmount(i, mod, value);
              int primResAmount = GetPrimaryAmount(i, mod, value);
              int specResAmount = GetSpecialAmount(i, mod, value);
  
              if (from.AccessLevel == AccessLevel.Player && 
                  (from.Backpack == null || from.Backpack.GetAmount(gem) < gemAmount || 
                  from.Backpack.GetAmount(primary) < primResAmount || 
                  from.Backpack.GetAmount(special) < specResAmount))
                  from.SendLocalizedMessage(1079773); //You do not have enough resources to imbue this item.     
              else
              {
                  int maxWeight = GetMaxWeight(i);
                  context.Imbue_IWmax = maxWeight;
  
                  int totalItemWeight = GetTotalWeight(i, mod);
                  int totalItemMods = GetTotalMods(i, mod);
                  int maxint = GetMaxIntensity(i, def);
  
                  int propweight = (int)(((double)def.Weight / (double)maxint) * value);
  
                  if ((totalItemWeight + propweight) > maxWeight)
                  {
                      from.SendLocalizedMessage(1079772); // You cannot imbue this item with any more item properties.
                      from.CloseGump(typeof(ImbuingGumpC));
                      return;
                  }
  
                  double difficulty = 0;
                  double success = GetSuccessChance(from, i, (int)totalItemWeight, propweight, out difficulty);
  
                  from.CheckSkill(SkillName.Imbuing, difficulty - 50, difficulty + 50);
  
                  success /= 100;
  
                  from.Backpack.ConsumeTotal(primary, primResAmount);
  
                  if (i is BaseWeapon) ((BaseWeapon)i).TimesImbued += 1;
  
gt:                 if (i is BaseArmor) ((BaseArmor)i).TimesImbued += 1;