using System;
using Server.Mobiles;

namespace Server.Items
{
	public abstract class BaseTrap : Item
	{
		public virtual bool PassivelyTriggered{ get{ return false; } }
		public virtual TimeSpan PassiveTriggerDelay{ get{ return TimeSpan.Zero; } }
		public virtual int PassiveTriggerRange{ get{ return -1; } }
		public virtual TimeSpan ResetDelay{ get{ return TimeSpan.Zero; } }
		private DateTime m_WhenDisarmed;
		private DateTime m_WhenSkilled;

		private DateTime m_NextPassiveTrigger, m_NextActiveTrigger;

		public virtual void OnTrigger( Mobile from )
		{
			if ( !TriggerCheck( from ) )
				return;

			if ( DisarmCheck( from ) )
				return;
		}

		public bool TriggerCheck( Mobile from )
		{
			if ( !from.Alive || from is BaseCreature || m_WhenDisarmed > DateTime.Now )
				return false;

			bool skillUp = false;

			if ( Utility.RandomBool() )
			{
				if ( from != LastTriggeredBy || ( from == LastTriggeredBy && m_WhenSkilled < DateTime.Now ) )
					skillUp = true;

				if ( BaseWeapon.CheckDodge( from, skillUp ) )
					return false;
			}

			return true;
		}

		public bool DisarmCheck( Mobile from )
		{
			if ( m_WhenDisarmed > DateTime.Now )
				return true;

			if ( from is PlayerMobile )
			{
				bool disarmed = false;
				double skill = from.Skills[SkillName.RemoveTrap].Base;

				if ( from.Skills[SkillName.RemoveTrap].Value > Utility.RandomMinMax(1,101) )
					disarmed = true;

				if ( from != LastTriggeredBy || ( from == LastTriggeredBy && m_WhenSkilled < DateTime.Now ) )
				{
					// If they cannot pass this skill check, allow them to keep gaining skill
					// Not only pass the kill check, but also gain skill
					// Otherwise, record them so they can't keep gaining over and over on the same trap
					if ( from.CheckSkill( SkillName.RemoveTrap, 0, 120 ) )
					{
						if ( skill != from.Skills[SkillName.RemoveTrap].Base )
						{
							LastTriggeredBy = from;
							m_WhenSkilled = (DateTime.Now).AddMinutes(30.0);
						}
					}
				}

				if ( disarmed )
				{
					if ( this is MushroomTrap )
					{
						from.SendMessage( "You squish the mushroom so its harmless!" );
						from.PlaySound( 0x050 );
					}
					else if ( this is FireColumnTrap && this.ItemID == 0x028F )
					{
						from.SendMessage( "You plug the hole so no further flames will erupt!" );
						from.PlaySound( 0x057 );
					}
					else
					{
						from.SendMessage( "You disabled a trap!" );
						from.PlaySound( 0x241 );
					}

					m_WhenDisarmed = (DateTime.Now).AddMinutes((double)(Utility.RandomMinMax(30,60)));

					return true;
				}
			}

			return false;
		}

		public override bool HandlesOnMovement{ get{ return true; } } // Tell the core that we implement OnMovement

		public virtual int GetEffectHue()
		{
			int hue = this.Hue & 0x3FFF;

			if ( hue < 2 )
				return 0;

			return hue - 1;
		}

		public bool CheckRange( Point3D loc, Point3D oldLoc, int range )
		{
			return CheckRange( loc, range ) && !CheckRange( oldLoc, range );
		}

		public bool CheckRange( Point3D loc, int range )
		{
			return ( (this.Z + 8) >= loc.Z && (loc.Z + 16) > this.Z )
				&& Utility.InRange( GetWorldLocation(), loc, range );
		}

		public override void OnMovement( Mobile m, Point3D oldLocation )
		{
			if ( m_WhenDisarmed > DateTime.Now )
				return;

			base.OnMovement( m, oldLocation );

			if ( m.Location == oldLocation || m is BaseCreature )
				return;

			if ( CheckRange( m.Location, oldLocation, 0 ) && DateTime.Now >= m_NextActiveTrigger )
			{
				m_NextActiveTrigger = m_NextPassiveTrigger = DateTime.Now + ResetDelay;

				OnTrigger( m );
			}
			else if ( PassivelyTriggered && CheckRange( m.Location, oldLocation, PassiveTriggerRange ) && DateTime.Now >= m_NextPassiveTrigger )
			{
				m_NextPassiveTrigger = DateTime.Now + PassiveTriggerDelay;

				OnTrigger( m );
			}
		}

		public BaseTrap( int itemID ) : base( itemID )
		{
			Movable = false;
		}

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

		[CommandProperty( AccessLevel.GameMaster )]
		public DateTime WhenDisarmed
		{
			get
			{
				return m_WhenDisarmed;
			}
			set
			{
				m_WhenDisarmed = value;
			}
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public DateTime WhenSkilled
		{
			get
			{
				return m_WhenSkilled;
			}
			set
			{
				m_WhenSkilled = value;
			}
		}

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

		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );
			writer.Write( (int) 0 ); // version
			writer.Write( (Mobile)LastTriggeredBy);
			writer.Write( m_WhenDisarmed );
			writer.Write( m_WhenSkilled );
		}

		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );
			int version = reader.ReadInt();
			LastTriggeredBy = reader.ReadMobile();
			m_WhenDisarmed = reader.ReadDateTime();
			m_WhenSkilled = reader.ReadDateTime();
		}
	}
}