context: using System;
  using System.Collections;
  using System.Linq;
  
  using Server;
  using Server.Network;
  using Server.Engines.Craft;
  using Server.Engines.Imbuing;
  using Server.Factions;
  using Server.Mobiles;
  
  namespace Server.Items
  {
  	public interface IArcaneEquip
  	{
  		bool IsArcane { get; }
  		int CurArcaneCharges { get; set; }
  		int MaxArcaneCharges { get; set; }
  	}
  
  	public abstract class BaseClothing : Item, IDyable, IScissorable, IFactionItem, ICraftable, IMagicalItem, ICloth, IWearableDurability, ISkillBonuses, IResistances, IAbsorption, IImbuable, IArtifactRarity
  	{
  		#region Factions
  		private FactionItem m_FactionState;
  
  		public FactionItem FactionItemState
  		{
  			get { return m_FactionState; }
  			set
  			{
  				m_FactionState = value;
  
  				if ( m_FactionState == null )
  				{
  					Hue = 0;
  				}
  
  				LootType = ( m_FactionState == null ? LootType.Regular : LootType.Blessed );
  			}
  		}
  		#endregion
  
  		protected CraftResource m_Resource;
  
  		private Mobile m_Crafter;
  		private bool m_Exceptional;
  		private bool m_PlayerConstructed;
  
  		private bool m_Altered;
  
  		private AosAttributes m_AosAttributes;
  		private AosArmorAttributes m_ClothingAttributes;
  		private SkillBonuses m_SkillBonuses;
  		private AosElementAttributes m_Resistances;
  		private AbsorptionAttributes m_AbsorptionAttributes;
  
  		public virtual bool AllowMaleWearer { get { return true; } }
  		public virtual bool AllowFemaleWearer { get { return true; } }
  
  		public virtual int StrengthReq { get { return 10; } }
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public Mobile Crafter
  		{
  			get { return m_Crafter; }
  			set { m_Crafter = value; InvalidateProperties(); }
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public bool Exceptional
  		{
  			get { return m_Exceptional; }
  			set { m_Exceptional = value; InvalidateProperties(); }
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public bool PlayerConstructed
  		{
  			get { return m_PlayerConstructed; }
  			set { m_PlayerConstructed = value; }
  		}
  
  		public virtual CraftResource DefaultResource { get { return CraftResource.None; } }
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public CraftResource Resource
  		{
  			get { return m_Resource; }
  			set
  			{
  				m_Resource = value;
  				Hue = CraftResources.GetHue( m_Resource );
  				InvalidateProperties();
  			}
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public AosAttributes Attributes
  		{
  			get { return m_AosAttributes; }
  			set
  			{
  			}
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public AosArmorAttributes ClothingAttributes
  		{
  			get { return m_ClothingAttributes; }
  			set
  			{
  			}
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public SkillBonuses SkillBonuses
  		{
  			get { return m_SkillBonuses; }
  			set
  			{
  			}
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public AosElementAttributes Resistances
  		{
  			get { return m_Resistances; }
  			set
  			{
  			}
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public AbsorptionAttributes AbsorptionAttributes
  		{
  			get { return m_AbsorptionAttributes; }
  			set
  			{
  			}
  		}
  
  		public virtual bool CanLoseDurability { get { return m_HitPoints >= 0 && m_MaxHitPoints > 0; } }
  
  		public virtual int InitMinHits { get { return 0; } }
  		public virtual int InitMaxHits { get { return 0; } }
  
  		public virtual bool CanFortify { get { return false; } }
  		public virtual bool Brittle { get { return false; } }
  		public virtual bool CannotBeRepaired { get { return false; } }
  
  		private int m_MaxHitPoints;
  		private int m_HitPoints;
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public int MaxHitPoints
  		{
  			get { return m_MaxHitPoints; }
  			set
  			{
  				m_MaxHitPoints = value;
  				InvalidateProperties();
  			}
  		}
  
  		[CommandProperty( AccessLevel.GameMaster )]
  		public int HitPoints
  		{
  			get { return m_HitPoints; }
  			set
  			{
  				if ( value != m_HitPoints && MaxHitPoints > 0 )
  				{
  					m_HitPoints = value;
  
  					if ( m_HitPoints < 0 )
  					{
  						Delete();
  					}
  					else if ( m_HitPoints > MaxHitPoints )
  					{
  						m_HitPoints = MaxHitPoints;
  					}
  
  					InvalidateProperties();
  				}
  			}
  		}
  
  		public virtual int BasePhysicalResistance { get { return 0; } }
  		public virtual int BaseFireResistance { get { return 0; } }
  		public virtual int BaseColdResistance { get { return 0; } }
  		public virtual int BasePoisonResistance { get { return 0; } }
  		public virtual int BaseEnergyResistance { get { return 0; } }
  
  		public override int PhysicalResistance { get { return BasePhysicalResistance + m_Resistances.Physical; } }
  		public override int FireResistance { get { return BaseFireResistance + m_Resistances.Fire; } }
  		public override int ColdResistance { get { return BaseColdResistance + m_Resistances.Cold; } }
  		public override int PoisonResistance { get { return BasePoisonResistance + m_Resistances.Poison; } }
  		public override int EnergyResistance { get { return BaseEnergyResistance + m_Resistances.Energy; } }
  
  		public virtual int ArtifactRarity { get { return 0; } }
  
  		public virtual int BaseStrBonus { get { return 0; } }
  		public virtual int BaseDexBonus { get { return 0; } }
  		public virtual int BaseIntBonus { get { return 0; } }
  
  		public virtual bool CanBeBlessed { get { return true; } }
  
  		public int ComputeStatBonus( StatType type )
  		{
  			if ( type == StatType.Str )
  			{
  				return BaseStrBonus + Attributes.BonusStr;
  			}
  			else if ( type == StatType.Dex )
  			{
  				return BaseDexBonus + Attributes.BonusDex;
  			}
  			else
  			{
  				return BaseIntBonus + Attributes.BonusInt;
  			}
  		}
  
  		public virtual void AddStatBonuses( Mobile parent )
  		{
  			if ( parent == null )
  			{
  				return;
  			}
  
  			int strBonus = ComputeStatBonus( StatType.Str );
  			int dexBonus = ComputeStatBonus( StatType.Dex );
  			int intBonus = ComputeStatBonus( StatType.Int );
  
  			if ( strBonus == 0 && dexBonus == 0 && intBonus == 0 )
  			{
  				return;
  			}
  
  			string modName = this.Serial.ToString();
  
  			if ( strBonus != 0 )
  			{
  				parent.AddStatMod( new StatMod( StatType.Str, modName + "Str", strBonus, TimeSpan.Zero ) );
  			}
  
  			if ( dexBonus != 0 )
  			{
  				parent.AddStatMod( new StatMod( StatType.Dex, modName + "Dex", dexBonus, TimeSpan.Zero ) );
  			}
  
  			if ( intBonus != 0 )
  			{
  				parent.AddStatMod( new StatMod( StatType.Int, modName + "Int", intBonus, TimeSpan.Zero ) );
  			}
  		}
  
  		public virtual int OnHit( int damageTaken )
  		{
  			int Absorbed = 2; // TODO: verify
  
  			damageTaken -= Absorbed;
  			if ( damageTaken < 0 )
  			{
  				damageTaken = 0;
  			}
  
  			if ( 25 > Utility.Random( 100 ) ) // 25% chance to lower durability
  			{
  				if ( m_ClothingAttributes.SelfRepair > Utility.Random( 10 ) )
  				{
  					HitPoints += 2;
  				}
  				else
  				{
  					int wear = Utility.Random( 2 );
  
  					if ( wear > 0 && m_MaxHitPoints > 0 )
  					{
  						if ( m_HitPoints >= wear )
  						{
  							HitPoints -= wear;
  							wear = 0;
  						}
  						else
  						{
  							wear -= HitPoints;
  							HitPoints = 0;
  						}
  
  						if ( wear > 0 )
  						{
  							if ( m_MaxHitPoints > wear )
  							{
  								MaxHitPoints -= wear;
  
  								if ( Parent is Mobile )
  									( (Mobile) Parent ).LocalOverheadMessage( MessageType.Regular, 0x3B2, 1061121 ); // Your equipment is severely damaged.
  							}
  							else
  							{
  								Delete();
  							}
  						}
  					}
  				}
  			}
  
  			return damageTaken;
  		}
  
  		public override void OnAdded( object parent )
  		{
  			Mobile mob = parent as Mobile;
  
  			if ( mob != null )
  			{
  				m_SkillBonuses.AddTo( mob );
  
  				AddStatBonuses( mob );
  				mob.CheckStatTimers();
  			}
  
  			base.OnAdded( parent );
  		}
  
  		public override void OnRemoved( object parent )
  		{
  			Mobile mob = parent as Mobile;
  
  			if ( mob != null )
  			{
  				m_SkillBonuses.Remove();
  
  				string modName = this.Serial.ToString();
  
  				mob.RemoveStatMod( modName + "Str" );
  				mob.RemoveStatMod( modName + "Dex" );
  				mob.RemoveStatMod( modName + "Int" );
  
  				mob.CheckStatTimers();
  			}
  
  			base.OnRemoved( parent );
  		}
  
  		public BaseClothing( int itemID, Layer layer )
  			: this( itemID, layer, 0 )
  		{
  		}
  
  		public BaseClothing( int itemID, Layer layer, int hue )
  			: base( itemID )
  		{
  			Layer = layer;
  			Hue = hue;
  
  			m_Resource = DefaultResource;
  
  			m_AosAttributes = new AosAttributes( this );
  			m_ClothingAttributes = new AosArmorAttributes( this );
  			m_SkillBonuses = new SkillBonuses( this );
  			m_Resistances = new AosElementAttributes( this );
  			m_AbsorptionAttributes = new AbsorptionAttributes( this );
  
  			m_HitPoints = m_MaxHitPoints = Utility.RandomMinMax( InitMinHits, InitMaxHits );
  		}
  
  		public BaseClothing( Serial serial )
  			: base( serial )
  		{
  		}
  
  		public override void OnAfterDuped( Item newItem )
  		{
  			// TODO: Copy Attributes
  		}
  
  		public static void ValidateMobile( Mobile m )
  		{
  			if ( m.AccessLevel >= AccessLevel.GameMaster )
  				return;
  
  			foreach ( var clothing in m.GetEquippedItems().OfType<BaseClothing>() )
  			{
  				if ( !clothing.AllowMaleWearer && m.Body.IsMale )
  				{
  					if ( clothing.AllowFemaleWearer )
  						m.SendLocalizedMessage( 1010388 ); // Only females can wear this.
  					else
  						m.SendMessage( "You may not wear this." );
  
  					m.AddToBackpack( clothing );
  				}
  				else if ( !clothing.AllowFemaleWearer && m.Body.IsFemale )
  				{
  					if ( clothing.AllowMaleWearer )
  						m.SendMessage( "Only males can wear this." );
  					else
  						m.SendMessage( "You may not wear this." );
  
  					m.AddToBackpack( clothing );
  				}
  			}
  		}
  
  		public override bool AllowEquipedCast( Mobile from )
  		{
  			if ( base.AllowEquipedCast( from ) )
  			{
  				return true;
  			}
  
  			return ( m_AosAttributes.SpellChanneling != 0 );
  		}
  
  		public override bool CheckPropertyConfliction( Mobile m )
  		{
  			if ( base.CheckPropertyConfliction( m ) )
  			{
  				return true;
  			}
  
  			if ( Layer == Layer.Pants )
  			{
  				return ( m.FindItemOnLayer( Layer.InnerLegs ) != null );
  			}
  
  			if ( Layer == Layer.Shirt )
  			{
  				return ( m.FindItemOnLayer( Layer.InnerTorso ) != null );
  			}
  
  			return false;
  		}
  
  		private string GetNameString()
  		{
  			string name = this.Name;
  
  			if ( name == null )
  			{
  				name = String.Format( "#{0}", LabelNumber );
  			}
  
  			return name;
  		}
  
  		public override LocalizedText GetNameProperty()
  		{
  			int oreType;
  
  			if ( Hue == 0 )
  			{
  				oreType = 0;
  			}
  			else
  			{
  				switch ( m_Resource )
  				{
  					case CraftResource.DullCopper:
  						oreType = 1053108;
  						break; // dull copper
  					case CraftResource.ShadowIron:
  						oreType = 1053107;
  						break; // shadow iron
  					case CraftResource.Copper:
  						oreType = 1053106;
  						break; // copper
  					case CraftResource.Bronze:
  						oreType = 1053105;
  						break; // bronze
  					case CraftResource.Gold:
  						oreType = 1053104;
  						break; // golden
  					case CraftResource.Agapite:
  						oreType = 1053103;
  						break; // agapite
  					case CraftResource.Verite:
  						oreType = 1053102;
  						break; // verite
  					case CraftResource.Valorite:
  						oreType = 1053101;
  						break; // valorite
  					case CraftResource.SpinedLeather:
  						oreType = 1061118;
  						break; // spined
  					case CraftResource.HornedLeather:
  						oreType = 1061117;
  						break; // horned
  					case CraftResource.BarbedLeather:
  						oreType = 1061116;
  						break; // barbed
  					case CraftResource.RedScales:
  						oreType = 1060814;
  						break; // red
  					case CraftResource.YellowScales:
  						oreType = 1060818;
  						break; // yellow
  					case CraftResource.BlackScales:
  						oreType = 1060820;
  						break; // black
  					case CraftResource.GreenScales:
  						oreType = 1060819;
  						break; // green
  					case CraftResource.WhiteScales:
  						oreType = 1060821;
  						break; // white
  					case CraftResource.BlueScales:
  						oreType = 1060815;
  						break; // blue
  					default:
  						oreType = 0;
  						break;
  				}
  			}
  
  			if ( oreType != 0 )
  			{
  				return new LocalizedText( 1053099, "#{0}\t{1}", oreType, GetNameString() ); // ~1_oretype~ ~2_armortype~
  			}
  			else if ( Name == null )
  			{
  				return new LocalizedText( LabelNumber );
  			}
  			else
  			{
  				return new LocalizedText( Name );
  			}
  		}
  
  		public virtual void GetSetArmorPropertiesFirst( ObjectPropertyList list )
  		{
  		}
  
  		public virtual void GetSetArmorPropertiesSecond( ObjectPropertyList list )
  		{
  		}
  
  		public override void GetProperties( ObjectPropertyList list )
  		{
  			base.GetProperties( list );
  
  			if ( m_Exceptional )
  				list.Add( 1060636 ); // exceptional
  
  			if ( m_Crafter != null )
  				list.Add( 1050043, m_Crafter.Name ); // crafted by ~1_NAME~
  
  			if ( m_Altered )
  				list.Add( 1111880 ); // Altered
  
  			#region Factions
  			if ( m_FactionState != null )
  			{
  				list.Add( 1041350 ); // faction item
  			}
  			#endregion
  
  			GetSetArmorPropertiesFirst( list );
  
  			m_SkillBonuses.GetProperties( list );
  
  			int prop;
  
  			if ( ( prop = ArtifactRarity ) > 0 )
  				list.Add( 1061078, prop.ToString() ); // artifact rarity ~1_val~
  
  			if ( ( prop = m_AbsorptionAttributes.KineticEater ) != 0 )
  				list.Add( 1113597, prop.ToString() ); // Kinetic Eater ~1_Val~%
  
  			if ( ( prop = m_AbsorptionAttributes.FireEater ) != 0 )
  				list.Add( 1113593, prop.ToString() ); // Fire Eater ~1_Val~%
  
  			if ( ( prop = m_AbsorptionAttributes.ColdEater ) != 0 )
  				list.Add( 1113594, prop.ToString() ); // Cold Eater ~1_Val~%
  
  			if ( ( prop = m_AbsorptionAttributes.PoisonEater ) != 0 )
  				list.Add( 1113595, prop.ToString() ); // Poison Eater ~1_Val~%
  
  			if ( ( prop = m_AbsorptionAttributes.EnergyEater ) != 0 )
  				list.Add( 1113596, prop.ToString() ); // Energy Eater ~1_Val~%
  
  			if ( ( prop = m_AbsorptionAttributes.DamageEater ) != 0 )
  				list.Add( 1113598, prop.ToString() ); // Damage Eater ~1_Val~%
  
  			if ( ( prop = m_AbsorptionAttributes.KineticResonance ) != 0 )
  				list.Add( 1113695, prop.ToString() ); // Kinetic Resonance ~1_val~%
  
  			if ( ( prop = m_AbsorptionAttributes.FireResonance ) != 0 )
  				list.Add( 1113691, prop.ToString() ); // Fire Resonance ~1_val~%
  
  			if ( ( prop = m_AbsorptionAttributes.ColdResonance ) != 0 )
  				list.Add( 1113692, prop.ToString() ); // Cold Resonance ~1_val~%
  
  			if ( ( prop = m_AbsorptionAttributes.PoisonResonance ) != 0 )
  				list.Add( 1113693, prop.ToString() ); // Poison Resonance ~1_val~%
  
  			if ( ( prop = m_AbsorptionAttributes.EnergyResonance ) != 0 )
  				list.Add( 1113694, prop.ToString() ); // Energy Resonance ~1_val~%
  
  			if ( ( prop = m_AosAttributes.WeaponDamage ) != 0 )
  				list.Add( 1060401, prop.ToString() ); // damage increase ~1_val~%
  
  			if ( ( prop = m_AosAttributes.DefendChance ) != 0 )
  				list.Add( 1060408, prop.ToString() ); // defense chance increase ~1_val~%
  
  			if ( ( prop = m_AosAttributes.BonusDex ) != 0 )
  
gt: 				list.Add( 1060409, prop.ToString() ); // dexterity bonus ~1_val~