using System;
using Server.Items;
using Server.Network;

namespace Server.Mobiles
{
	[CorpseName( "a plague beast lord corpse" )]
	public class PlagueBeastLord : BaseCreature, ICarvable, IScissorable
	{
		public override Poison PoisonImmune { get { return Poison.Lethal; } }

		private Mobile m_OpenedBy;

		[CommandProperty( AccessLevel.GameMaster )]
		public Mobile OpenedBy
		{
			get { return m_OpenedBy; }
			set { m_OpenedBy = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public bool IsBleeding
		{
			get
			{
				Container pack = Backpack;

				if ( pack != null )
				{
					for ( int i = 0; i < pack.Items.Count; i++ )
					{
						PlagueBeastBlood blood = pack.Items[ i ] as PlagueBeastBlood;

						if ( blood != null && !blood.Patched )
							return true;
					}
				}

				return false;
			}
		}

		private DecayTimer m_Timer;

		[Constructable]
		public PlagueBeastLord() : base( AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4 )
		{
			Name = "a plague beast lord";
			Body = 775;
			BaseSoundID = 679;
			SpeechHue = 0x3B2;

			SetStr( 500 );
			SetDex( 100 );
			SetInt( 30 );

			SetHits( 1800 );

			SetDamage( 20, 25 );

			SetDamageType( ResistanceType.Physical, 50 );
			SetDamageType( ResistanceType.Fire, 25 );
			SetDamageType( ResistanceType.Poison, 25 );

			SetResistance( ResistanceType.Physical, 45, 55 );
			SetResistance( ResistanceType.Fire, 40, 50 );
			SetResistance( ResistanceType.Cold, 25, 35 );
			SetResistance( ResistanceType.Poison, 75, 85 );
			SetResistance( ResistanceType.Energy, 25, 35 );

			SetSkill( SkillName.Tactics, 100 );
			SetSkill( SkillName.Wrestling, 100 );

			Fame = 2000;
			Karma = -2000;

			VirtualArmor = 50;
		}

		public override void OnDoubleClick( Mobile from )
		{
			if ( IsAccessibleTo( from ) )
			{
				if ( m_OpenedBy != null && Backpack != null )
					Backpack.DisplayTo( from );
				else
					PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1071917, from.NetState ); // * You attempt to tear open the amorphous flesh, but it resists *
			}
		}

		public override bool OnDragDrop( Mobile from, Item dropped )
		{
			if ( IsAccessibleTo( from ) && ( dropped is PlagueBeastInnard || dropped is PlagueBeastGland ) )
				return base.OnDragDrop( from, dropped );

			return false;
		}

		public override void OnDeath( Container c )
		{
			base.OnDeath( c );
			
			for ( int i = c.Items.Count - 1; i >= 0; i-- )
				c.Items[ i ].Delete();
		}

		public override void OnDelete()
		{
			if ( m_OpenedBy != null && m_OpenedBy.Holding is PlagueBeastInnard )
				m_OpenedBy.Holding.Delete();

			if ( Backpack != null )
			{
				for ( int i = Backpack.Items.Count - 1; i >= 0; i-- )
					Backpack.Items[ i ].Delete();

				Backpack.Delete();
			}

			base.OnDelete();
		}

		public override void OnMovement( Mobile m, Point3D oldLocation )
		{
			base.OnMovement( m, oldLocation );

			if ( Backpack != null && IsAccessibleTo( m ) && m.InRange( oldLocation, 3 ) && !m.InRange( this, 3 ) )
				Backpack.SendRemovePacket();
		}

		public override bool CheckNonlocalLift( Mobile from, Item item )
		{
			return true;
		}

		public override bool CheckNonlocalDrop( Mobile from, Item item, Item target )
		{
			return true;
		}

		public override bool IsSnoop( Mobile from )
		{
			return false;
		}

		public override int GetIdleSound()
		{
			return 0x1BF;
		}

		public override int GetAttackSound()
		{
			return 0x1C0;
		}

		public override int GetHurtSound()
		{
			return 0x1C1;
		}

		public override int GetDeathSound()
		{
			return 0x1C2;
		}

		public virtual void OnParalyzed( Mobile from )
		{
			FightMode = FightMode.None;
			Frozen = true;
			Blessed = true;
			Combatant = null;
			Hue = 0x480;
			from.Combatant = null;
			from.Warmode = false;

			m_Timer = new DecayTimer( this );
			m_Timer.Start();

			Timer.DelayCall( TimeSpan.Zero, new TimerCallback( BroadcastMessage ) );
		}

		private void BroadcastMessage()
		{
			PublicOverheadMessage( MessageType.Regular, 0x3B2, 1071920 ); // * The plague beast's amorphous flesh hardens and becomes immobilized *
		}

		public virtual bool IsAccessibleTo( Mobile check )
		{
			if ( check.AccessLevel >= AccessLevel.GameMaster )
				return true;

			if ( !InRange( check, 2 ) )
				PrivateOverheadMessage( MessageType.Label, 0x3B2, 500446, check.NetState ); // That is too far away.
			else if ( m_OpenedBy != null && m_OpenedBy != check )
				PrivateOverheadMessage( MessageType.Label, 0x3B2, 500365, check.NetState ); // That is being used by someone else
			else if ( Frozen )
				return true;

			return false;
		}

		public virtual void Carve( Mobile from, Item item )
		{
			if ( m_OpenedBy == null && IsAccessibleTo( from ) )
			{
				m_OpenedBy = from;
				
				if ( m_Timer == null )
					m_Timer = new DecayTimer( this );
				
				if ( !m_Timer.Running )
					m_Timer.Start();

				m_Timer.StartDissolving();

				PlagueBeastBackpack pack = new PlagueBeastBackpack();
				AddItem( pack );
				pack.Initialize();

				foreach ( NetState state in GetClientsInRange( 12 ) )
				{
					Mobile m = state.Mobile;

					if ( m != null && m.Player && m != from )
						PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1071919, from.Name, m.NetState ); // * ~1_VAL~ slices through the plague beast's amorphous tissue *
				}

				from.LocalOverheadMessage( MessageType.Regular, 0x21, 1071904 ); // * You slice through the plague beast's amorphous tissue *
				Timer.DelayCall<Mobile>( TimeSpan.Zero, new TimerStateCallback<Mobile>( pack.Open ), from );
			}
		}

		public virtual bool Scissor( Mobile from, Scissors scissors )
		{
			if ( IsAccessibleTo( from ) )
				scissors.PublicOverheadMessage( MessageType.Regular, 0x3B2, 1071918 );  // You can't cut through the plague beast's amorphous skin with scissors!

			return false;
		}

		public void Unfreeze()
		{
			FightMode = FightMode.Closest;
			Frozen = false;
			Blessed = false;

			if ( m_OpenedBy == null )
				Hue = 0;
		}

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

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

			writer.WriteEncodedInt( 0 ); // version

			writer.Write( m_OpenedBy );

			if ( m_Timer != null )
			{
				writer.Write( (bool) true );
				writer.Write( (int) m_Timer.Count );
				writer.Write( (int) m_Timer.Deadline );
			}
			else
				writer.Write( (bool) false );
		}

		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );

			int version = reader.ReadEncodedInt();

			m_OpenedBy = reader.ReadMobile();

			if ( reader.ReadBool() )
			{
				int count = reader.ReadInt();
				int deadline = reader.ReadInt();

				m_Timer = new DecayTimer( this, count, deadline );
				m_Timer.Start();
			}

			if ( FightMode == FightMode.None )
				Frozen = true;
		}

		private class DecayTimer : Timer
		{
			private PlagueBeastLord m_Lord;
			private int m_Count;
			private int m_Deadline;

			public int Count
			{
				get { return m_Count; }
			}

			public int Deadline
			{
				get { return m_Deadline; }
			}

			public DecayTimer( PlagueBeastLord lord ) : this( lord, 0, 120 )
			{
			}

			public DecayTimer( PlagueBeastLord lord, int count, int deadline ) : base( TimeSpan.Zero, TimeSpan.FromSeconds( 1 ) )
			{
				m_Lord = lord;
				m_Count = count;
				m_Deadline = deadline;
			}

			protected override void OnTick()
			{
				if ( m_Lord == null || m_Lord.Deleted )
				{
					Stop();
					return;
				}

				if ( m_Count + 15 == m_Deadline )
				{
					if ( m_Lord.OpenedBy != null )
						m_Lord.PublicOverheadMessage( MessageType.Regular, 0x3B2, 1071921 ); // * The plague beast begins to bubble and dissolve! *

					m_Lord.PlaySound( 0x103 );
				}
				else if ( m_Count + 10 == m_Deadline )
				{
					m_Lord.PlaySound( 0x21 );
				}
				else if ( m_Count + 5 == m_Deadline )
				{
					m_Lord.PlaySound( 0x1C2 );
				}
				else if ( m_Count == m_Deadline )
				{
					m_Lord.Unfreeze();

					if ( m_Lord.OpenedBy != null )
						m_Lord.Kill();

					Stop();
				}
				else if ( m_Count % 15 == 0 )
					m_Lord.PlaySound( 0x1BF );

				m_Count++;
			}

			public void StartDissolving()
			{
				m_Deadline = Math.Min( m_Count + 60, m_Deadline );
			}
		}
	}
}
