context: using System;
  using System.Collections.Generic;
  
  using Mag.Shared.Constants;
  using Mag.Shared.Spells;
  
  namespace Mag.Shared
  {
  	/// <summary>
  	/// Instantiate this object with the item you want info for.
  	/// ToString() this object for the info.
  	/// </summary>
  	public class ItemInfo
  	{
  		private readonly MyWorldObject mwo;
  
  		public ItemInfo(MyWorldObject myWorldObject)
  		{
  			mwo = myWorldObject;
  		}
  
  		public override string ToString()
  		{
  			return ToString(true, true);
  		}
  
  		public string ToString(bool showBuffedValues, bool showValueAndBurden)
  		{
  			System.Text.StringBuilder sb = new System.Text.StringBuilder();
  
  			if (mwo.Values(IntValueKey.MaterialType) > 0)
  			{
  				if (Dictionaries.MaterialInfo.ContainsKey(mwo.Values(IntValueKey.MaterialType)))
  					sb.Append(Dictionaries.MaterialInfo[mwo.Values(IntValueKey.MaterialType)] + " ");
  				else
  					sb.Append("unknown material " + mwo.Values(IntValueKey.MaterialType) + " ");
  			}
  
  			sb.Append(mwo.Name);
  
  			if (mwo.Values((IntValueKey)353) > 0)
  			{
  				if (Dictionaries.MasteryInfo.ContainsKey(mwo.Values((IntValueKey)353)))
  					sb.Append(" (" + Dictionaries.MasteryInfo[mwo.Values((IntValueKey)353)] + ")");
  				else
  					sb.Append(" (Unknown mastery " + mwo.Values((IntValueKey)353) + ")");
  			}
  
  			int set = mwo.Values((IntValueKey)265, 0);
  			if (set != 0)
  			{
  				sb.Append(", ");
  				if (Dictionaries.AttributeSetInfo.ContainsKey(set))
  					sb.Append(Dictionaries.AttributeSetInfo[set]);
  				else
  					sb.Append("Unknown set " + set);
  			}
  
  			if (mwo.Values(IntValueKey.ArmorLevel) > 0)
  				sb.Append(", AL " + mwo.Values(IntValueKey.ArmorLevel));
  
  			if (mwo.Values(IntValueKey.ImbuedEffect) > 0)
  			{
  				sb.Append(",");
  				if ((mwo.Values(IntValueKey.ImbuedEffect) & 1) == 1) sb.Append(" CS");
  				if ((mwo.Values(IntValueKey.ImbuedEffect) & 2) == 2) sb.Append(" CB");
  				if ((mwo.Values(IntValueKey.ImbuedEffect) & 4) == 4) sb.Append(" AR");
  				if ((mwo.Values(IntValueKey.ImbuedEffect) & 8) == 8) sb.Append(" SlashRend");
  				if ((mwo.Values(IntValueKey.ImbuedEffect) & 16) == 16) sb.Append(" PierceRend");
  				if ((mwo.Values(IntValueKey.ImbuedEffect) & 32) == 32) sb.Append(" BludgeRend");
  				if ((mwo.Values(IntValueKey.ImbuedEffect) & 64) == 64) sb.Append(" AcidRend");
  				if ((mwo.Values(IntValueKey.ImbuedEffect) & 128) == 128) sb.Append(" FrostRend");
  				if ((mwo.Values(IntValueKey.ImbuedEffect) & 256) == 256) sb.Append(" LightRend");
  				if ((mwo.Values(IntValueKey.ImbuedEffect) & 512) == 512) sb.Append(" FireRend");
  				if ((mwo.Values(IntValueKey.ImbuedEffect) & 1024) == 1024) sb.Append(" MeleeImbue");
  				if ((mwo.Values(IntValueKey.ImbuedEffect) & 4096) == 4096) sb.Append(" MagicImbue");
  				if ((mwo.Values(IntValueKey.ImbuedEffect) & 8192) == 8192) sb.Append(" Hematited");
  				if ((mwo.Values(IntValueKey.ImbuedEffect) & 536870912) == 536870912) sb.Append(" MagicAbsorb");
  			}
  
  			if (mwo.Values(IntValueKey.NumTimesTinkered) > 0)
  				sb.Append(", Tinks " + mwo.Values(IntValueKey.NumTimesTinkered));
  
  			if (mwo.Values(IntValueKey.MaxDamage_Decal) != 0 && mwo.Values(DoubleValueKey.Variance_Decal) != 0)
  				sb.Append(", " + (mwo.Values(IntValueKey.MaxDamage_Decal) - (mwo.Values(IntValueKey.MaxDamage_Decal) * mwo.Values(DoubleValueKey.Variance_Decal))).ToString("N2") + "-" + mwo.Values(IntValueKey.MaxDamage_Decal));
  			else if (mwo.Values(IntValueKey.MaxDamage_Decal) != 0 && mwo.Values(DoubleValueKey.Variance_Decal) == 0)
  				sb.Append(", " + mwo.Values(IntValueKey.MaxDamage_Decal));
  
  			if (mwo.Values(IntValueKey.ElementalDamageBonus, 0) != 0)
  				sb.Append(", +" + mwo.Values(IntValueKey.ElementalDamageBonus));
  
  			if (mwo.Values(DoubleValueKey.DamageBonus_Decal, 1) != 1)
  				sb.Append(", +" + Math.Round(((mwo.Values(DoubleValueKey.DamageBonus_Decal) - 1) * 100)) + "%");
  
  			if (mwo.Values(DoubleValueKey.ElementalDamageMod, 1) != 1)
  				sb.Append(", +" + Math.Round(((mwo.Values(DoubleValueKey.ElementalDamageMod) - 1) * 100)) + "%vs. Monsters");
  
  			if (mwo.Values(DoubleValueKey.AttackBonus_Decal, 1) != 1)
  				sb.Append(", +" + Math.Round(((mwo.Values(DoubleValueKey.AttackBonus_Decal) - 1) * 100)) + "%a");
  
  			if (mwo.Values(DoubleValueKey.WeaponDefense, 1) != 1)
  				sb.Append(", " + Math.Round(((mwo.Values(DoubleValueKey.WeaponDefense) - 1) * 100)) + "%md");
  
  			if (mwo.Values(DoubleValueKey.WeaponMagicDefense, 1) != 1)
  				sb.Append(", " + Math.Round(((mwo.Values(DoubleValueKey.WeaponMagicDefense) - 1) * 100), 1) + "%mgc.d");
  
  			if (mwo.Values(DoubleValueKey.WeaponMissileDefense, 1) != 1)
  				sb.Append(", " + Math.Round(((mwo.Values(DoubleValueKey.WeaponMissileDefense) - 1) * 100), 1) + "%msl.d");
  
  			if (mwo.Values(DoubleValueKey.ManaConversionMod) != 0)
  				sb.Append(", " + Math.Round((mwo.Values(DoubleValueKey.ManaConversionMod) * 100)) + "%mc");
  
  			if (showBuffedValues && (mwo.ObjectClass == (int)ObjectClass.MeleeWeapon || mwo.ObjectClass == (int)ObjectClass.MissileWeapon || mwo.ObjectClass == (int)ObjectClass.WandStaffOrb))
  			{
  				sb.Append(", (");
  
  				// (Damage)
  				if (mwo.ObjectClass == (int)ObjectClass.MeleeWeapon)
  					sb.Append(mwo.CalcedBuffedTinkedDoT.ToString("N1") + "/" + mwo.GetBuffedIntValueKey((int)IntValueKey.MaxDamage_Decal));
  
  				if (mwo.ObjectClass == (int)ObjectClass.MissileWeapon)
  					sb.Append(mwo.CalcedBuffedMissileDamage.ToString("N1"));
  
  				if (mwo.ObjectClass == (int)ObjectClass.WandStaffOrb)
  					sb.Append(((mwo.GetBuffedDoubleValueKey((int)DoubleValueKey.ElementalDamageMod) - 1) * 100).ToString("N1"));
  
  				// (AttackBonus/MeleeDefenseBonus/ManaCBonus)
  				sb.Append(" ");
  
  				if (mwo.Values(DoubleValueKey.AttackBonus_Decal, 1) != 1)
  					sb.Append(Math.Round(((mwo.GetBuffedDoubleValueKey((int)DoubleValueKey.AttackBonus_Decal) - 1) * 100)).ToString("N1") + "/");
  
  				if (mwo.Values(DoubleValueKey.WeaponDefense, 1) != 1)
  					sb.Append(Math.Round(((mwo.GetBuffedDoubleValueKey((int)DoubleValueKey.WeaponDefense) - 1) * 100)).ToString("N1"));
  
  				if (mwo.Values(DoubleValueKey.ManaConversionMod) != 0)
  					sb.Append("/" + Math.Round(mwo.GetBuffedDoubleValueKey((int)DoubleValueKey.ManaConversionMod) * 100));
  
  				sb.Append(")");
  			}
  
  			if (mwo.Spells.Count > 0)
  			{
  				List<int> sortedSpellIds = new List<int>();
  
  				foreach (var spell in mwo.Spells)
  					sortedSpellIds.Add(spell);
  
  				sortedSpellIds.Sort();
  				sortedSpellIds.Reverse();
  
  				foreach (int spellId in sortedSpellIds)
  				{
  					Spell spell = SpellTools.GetSpell(spellId);
  
  					if (spell == null)
  						continue;
  
  					// If the item is not loot generated, show all spells
  					if (!mwo.IntValues.ContainsKey((int)IntValueKey.MaterialType))
  						goto ShowSpell;
  
  					// Always show Minor/Major/Epic Impen
  					if (spell.Name.Contains("Minor Impenetrability") || spell.Name.Contains("Major Impenetrability") || spell.Name.Contains("Epic Impenetrability") || spell.Name.Contains("Legendary Impenetrability"))
  						goto ShowSpell;
  
  					// Always show trinket spells
  					if (spell.Name.Contains("Augmented"))
  						goto ShowSpell;
  
  					if (mwo.Values(IntValueKey.ResistMagic, 0) != 0)
  					{
  						// Show banes and impen on unenchantable equipment
  						if (spell.Name.Contains(" Bane") || spell.Name.Contains("Impen") || spell.Name.StartsWith("Brogard"))
  							goto ShowSpell;
  					}
  					else
  					{
  						// Hide banes and impen on enchantable equipment
  						if (spell.Name.Contains(" Bane") || spell.Name.Contains("Impen") || spell.Name.StartsWith("Brogard"))
  							continue;
  					}
  
  					//Debug.WriteToChat(spellById.Name + ", Difficulty: " + spellById.Difficulty + ", Family: " + spellById.Family + ", Generation: " + spellById.Generation + ", Type: " + spellById.Type + ", " + spellById.Unknown1 + " " + spellById.Unknown2 + " " + spellById.Unknown3 + " " + spellById.Unknown4 + " " + spellById.Unknown5 + " " + spellById.Unknown6 + " " + spellById.Unknown7 + " " + spellById.Unknown8 + " " + spellById.Unknown9 + " " + spellById.Unknown10);
  					// <{Mag-Tools}>: Major Coordination,				Difficulty: 15,		Family: 267,	Generation: 1, Type: 1,		0	1		1 2572 -2.07525870829232E+20 0 0 0 0 0
  					// <{Mag-Tools}>: Epic Magic Resistance,			Difficulty: 20,		Family: 299,	Generation: 1, Type: 1,		0	1		1 4704 -2.07525870829232E+20 0 0 0 0 0
  					// <{Mag-Tools}>: Epic Life Magic Aptitude,			Difficulty: 20,		Family: 357,	Generation: 1, Type: 1,		0	1		1 4700 -2.07525870829232E+20 0 0 0 0 0
  					// <{Mag-Tools}>: Epic Endurance,					Difficulty: 20,		Family: 263,	Generation: 1, Type: 1,		0	1		1 4226 -2.07525870829232E+20 0 0 0 0 0
  					// <{Mag-Tools}>: Essence Glutton,					Difficulty: 30,		Family: 279,	Generation: 1, Type: 1,		0	0		1 2666 -2.07525870829232E+20 0 0 0 0 0
  
  					// <{Mag-Tools}>: Might of the Lugians,				Difficulty: 300,	Family: 1,		Generation: 1, Type: 1,		0	0		1 2087 -2.07525870829232E+20 0 0 0 0 0
  					// <{Mag-Tools}>: Executor's Blessing,				Difficulty: 300,	Family: 115,	Generation: 1, Type: 1,		0	0		1 2053 -2.07525870829232E+20 0 0 0 0 0
  					// <{Mag-Tools}>: Regeneration Other Incantation,	Difficulty: 400,	Family: 93,		Generation: 1, Type: 1,		5	0.25	1 3982 -2.07525870829232E+20 0 0 0 0 0
  
  					// Focusing stone
  					// <{Mag-Tools}>: Brilliance,						Difficulty: 250,	Family: 15,		Generation: 1, Type: 1,		5	0.25	1 2348 -2.07525870829232E+20 0 0 0 0 0
  					// <{Mag-Tools}>: Concentration,					Difficulty: 100,	Family: 13,		Generation: 1, Type: 1,		0	0		1 2347 -2.07525870829232E+20 0 0 0 0 0
  					// <{Mag-Tools}>: Malediction,						Difficulty: 50,		Family: 284,	Generation: 1, Type: 1,		0	0		1 2346 -2.07525870829232E+20 0 0 0 0 0
  
  					// Weapon buffs
  					// <{Mag-Tools}>: Elysa's Sight,					Difficulty: 300,	Family: 152,	Generation: 1, Type: 1,		25	0		1 2106 -2.07525870829232E+20 0 0 0 0 0 (Attack Skill)
  					// <{Mag-Tools}>: Infected Caress,					Difficulty: 300,	Family: 154,	Generation: 1, Type: 1,		25	0		1 2096 -2.07525870829232E+20 0 0 0 0 0 (Damage)
  					// <{Mag-Tools}>: Infected Spirit Caress,			Difficulty: 300,	Family: 154,	Generation: 1, Type: 1,		25	0		1 3259 -2.07525870829232E+20 0 0 0 0 0 (Damage)
  					// <{Mag-Tools}>: Cragstone's Will,					Difficulty: 300,	Family: 156,	Generation: 1, Type: 1,		25	0		1 2101 -2.07525870829232E+20 0 0 0 0 0 (Defense)
  					// <{Mag-Tools}>: Atlan's Alacrity,					Difficulty: 300,	Family: 158,	Generation: 1, Type: 1,		25	0		1 2116 -2.07525870829232E+20 0 0 0 0 0 (Speed)
  					// <{Mag-Tools}>: Mystic's Blessing,				Difficulty: 300,	Family: 195,	Generation: 1, Type: 1,		25	0		1 2117 -2.07525870829232E+20 0 0 0 0 0 (Mana C)
  					// <{Mag-Tools}>: Vision of the Hunter,				Difficulty: 500,	Family: 325,	Generation: 1, Type: 1,		25	0		1 2968 -2.07525870829232E+20 0 0 0 0 0 (Damage Mod)
  
  					if ((spell.Family >= 152 && spell.Family <= 158) || spell.Family == 195 || spell.Family == 325)
  					{
  						// This is a weapon buff
  
  						// Lvl 6
  						if (spell.Difficulty == 250)
  							continue;
  
  						// Lvl 7
  						if (spell.Difficulty == 300)
  							goto ShowSpell;
  
  						// Lvl 8+
  						if (spell.Difficulty >= 400)
  							goto ShowSpell;
  
  						continue;
  					}
  
  					// This is not a weapon buff.
  
  					// Filter all 1-5 spells
  					if (spell.Name.EndsWith(" I") || spell.Name.EndsWith(" II") || spell.Name.EndsWith(" III") || spell.Name.EndsWith(" IV") || spell.Name.EndsWith(" V"))
  						continue;
  
  					// Filter 6's
  					if (spell.Name.EndsWith(" VI"))
  						continue;
  
  					// Filter 7's
  					if (spell.Difficulty == 300)
  						continue;
  
  					// Filter 8's
  					if (spell.Name.Contains("Incantation"))
  						continue;
  
  				ShowSpell:
  
  					sb.Append(", " + spell.Name);
  				}
  			}
  
  			// Wield Lvl 180
  			if (mwo.Values(IntValueKey.WieldDifficulty) > 0)
  			{
  				// I don't quite understand this.
  				if (mwo.Values(IntValueKey.WieldRequirements) == 7 && mwo.Values(IntValueKey.WieldSkillType) == 1)
  					sb.Append(", Wield Lvl " + mwo.Values(IntValueKey.WieldDifficulty));
  				else
  				{
  					if (Dictionaries.SkillInfo.ContainsKey(mwo.Values(IntValueKey.WieldSkillType)))
  						sb.Append(", " + Dictionaries.SkillInfo[mwo.Values(IntValueKey.WieldSkillType)] + " " + mwo.Values(IntValueKey.WieldDifficulty));
  					else
  						sb.Append(", Unknown skill: " + mwo.Values(IntValueKey.WieldSkillType) + " " + mwo.Values(IntValueKey.WieldDifficulty));
  				}
  			}
  
  			// Summoning Gem
  			if (mwo.Values((IntValueKey)369) > 0)
  				sb.Append(", Lvl " + mwo.Values((IntValueKey)369));
  
  			// Melee Defense 300 to Activate
  			// If the activation is lower than the wield requirement, don't show it.
  			if (mwo.Values(IntValueKey.ItemSkillLevelLimit) > 0 && (mwo.Values(IntValueKey.WieldSkillType) != mwo.Values(IntValueKey.AppraisalItemSkill) || mwo.Values(IntValueKey.WieldDifficulty) < mwo.Values(IntValueKey.ItemSkillLevelLimit)))
  			{
  				if (Dictionaries.SkillInfo.ContainsKey(mwo.Values(IntValueKey.AppraisalItemSkill)))
  					sb.Append(", " + Dictionaries.SkillInfo[mwo.Values(IntValueKey.AppraisalItemSkill)] + " " + mwo.Values(IntValueKey.ItemSkillLevelLimit) + " to Activate");
  				else
  					sb.Append(", Unknown skill: " + mwo.Values(IntValueKey.AppraisalItemSkill) + " " + mwo.Values(IntValueKey.ItemSkillLevelLimit) + " to Activate");
  			}
  
  			// Summoning Gem
  			if (mwo.Values((IntValueKey)366) > 0 && mwo.Values((IntValueKey)367) > 0)
  			{
  				if (Dictionaries.SkillInfo.ContainsKey(mwo.Values((IntValueKey)366)))
  					sb.Append(", " + Dictionaries.SkillInfo[mwo.Values((IntValueKey)366)] + " " + mwo.Values((IntValueKey)367));
  				else
  					sb.Append(", Unknown skill: " + mwo.Values((IntValueKey)366) + " " + mwo.Values((IntValueKey)367));
  			}
  
  			// Summoning Gem
  			if (mwo.Values((IntValueKey)368) > 0 && mwo.Values((IntValueKey)367) > 0)
  			{
  				if (Dictionaries.SkillInfo.ContainsKey(mwo.Values((IntValueKey)368)))
  					sb.Append(", Spec " + Dictionaries.SkillInfo[mwo.Values((IntValueKey)368)] + " " + mwo.Values((IntValueKey)367));
  				else
  					sb.Append(", Unknown skill spec: " + mwo.Values((IntValueKey)368) + " " + mwo.Values((IntValueKey)367));
  			}
  
  			if (mwo.Values(IntValueKey.ItemDifficulty) > 0)
  				sb.Append(", Diff " + mwo.Values(IntValueKey.ItemDifficulty));
  
  			if (mwo.ObjectClass == (int)ObjectClass.Salvage)
  			{
  
gt: 				if (mwo.Values(DoubleValueKey.SalvageWorkmanship_Decal) > 0)