using System;
using Server;
using Server.Items;
using Server.Mobiles;
using Xanthos.Interfaces;
using Server.Network;
using Server.Misc;
using System.Collections;
using System.Collections.Generic;
using Server.Targeting;

namespace Xanthos.Evo
{
	[CorpseName( "an evolution dolphin corpse" )]
	public class EvoDolphin : BaseEvo, IEvoCreature
	{
		private int m_Absorb;
		private int m_Charge;
		private int m_MaxAbsorb { get { return (this.Stage + 1) * 100000; } }
		private int m_MaxCharge { get { return (this.Stage + 1) * 1000; } }
		
		[CommandProperty(AccessLevel.GameMaster)]
		public int Absorb
		{
			get { return m_Absorb; }
			set
			{
				m_Absorb = value;
				m_Absorb = ( m_Absorb < 1 ) ? 0 : ( ( m_Absorb >  m_MaxAbsorb ) ? m_MaxAbsorb : m_Absorb );
			}
		}
		
		[CommandProperty(AccessLevel.GameMaster)]
		public int Charge
		{
			get { return m_Charge; }
			set
			{
				m_Charge = value;
				m_Charge = ( m_Charge < 1 ) ? 0 : ( ( m_Charge >  m_MaxCharge ) ? m_MaxCharge : m_Charge );
			}
		}
		
		public int MaxAbsorb { get { return m_MaxAbsorb; } }
		public int MaxCharge { get { return m_MaxCharge; } }
		
		public override BaseEvoSpec GetEvoSpec()
		{
			return EvoDolphinSpec.Instance;
		}

		public override BaseEvoEgg GetEvoEgg()
		{
			return null;
		}

		public override WeaponAbility GetWeaponAbility()
		{
			switch ( Utility.Random( 3 ) )
			{
				default:
					case 0: return WeaponAbility.DoubleStrike;
					case 1: return WeaponAbility.ArmorIgnore;
					case 2: return WeaponAbility.BleedAttack;
			}
		}
		
		public override bool AddPointsOnDamage { get { return false; } }
		public override bool AddPointsOnMelee { get { return false; } }
		public override Type GetEvoDustType() { return null; }
		public override bool IsScaredOfScaryThings{ get{ return false; } }
		public override bool IsScaryToPets{ get{ return false; } }
		public override Poison PoisonImmune{ get{ return Poison.Lethal; } }
		
		private DateTime m_NextChargeShield = DateTime.Now;
		private DateTime m_NextAbsorbShield = DateTime.Now;
		
		public override void OnDoubleClick( Mobile from )
		{
			if( Controlled && ControlMaster == from && CanEvokeTarget( from ) )
			{
				from.SendMessage("Vyber mrtvolu kterou chces smazat.");
				from.Target = new MonsterCorpseTarget( this );
         }			
		}
		
		private bool CanEvokeTarget( Mobile from )
		{
            Server.Multis.BaseBoat boat = Server.Multis.BaseBoat.FindBoatAt(this, this.Map);
            
            if ( IsDeadBondedPet || !Alive || !from.Alive || Blessed || !IsInWater() || !from.InRange( this.Location, 7 ) )
               return false;
            else
               return true;
      }
		
		private class MonsterCorpseTarget : Target
		{
			private EvoDolphin m_Dolphin;
			
			public MonsterCorpseTarget( EvoDolphin delfin ) : base( -1, true, TargetFlags.None )
			{
				m_Dolphin = delfin;
			}
			
			protected override void OnTarget( Mobile from, object o )
			{
				if ( o is Corpse )
				{
					Corpse MCcorpse = (Corpse)o;
					
					if ( m_Dolphin == null || m_Dolphin.IsDeadBondedPet ||  !m_Dolphin.Alive || MCcorpse == null || ((Item)MCcorpse).Deleted )
					{
						from.SendMessage("Delfin musi byt nazivu!");
						return;
					}
					else if ( MCcorpse.Channeled )
					{
						from.SendMessage("Zneuctena mrtvola nemuze byt smazana!");
						return;
					}
					else if ( MCcorpse.Items.Count > 0 )
					{
						from.SendMessage("Mrtvola neni prazdna!");
						return;
					}
					if ( MCcorpse.CanLoot( from )/*MCcorpse.Killer == from*/ )
					{
                  MCcorpse.Delete();
                  m_Dolphin.PlaySound( Utility.Random( 0x3A, 3 ) );
                  
                  if ( m_Dolphin.CanEvokeTarget( from ) )
                     from.Target = new MonsterCorpseTarget( m_Dolphin );
					}
					else
						from.SendMessage("Nemuzes smazat mrtvolu, kterou nemuzes lootovat!");
				}
				else
					from.SendMessage("Toto neni mrtvola");
			}
		}
		
		public override bool OnDragDrop( Mobile from, Item dropped )
		{
			PlayerMobile player = from as PlayerMobile;

			if ( this is IEvoGuardian )
				return base.OnDragDrop( from, dropped );
			
			if ( from != ControlMaster )
				return false;
			
			if ( from.Skills[SkillName.Fishing].Value < 75.0 )
			{
				from.SendMessage("Delfin si vezme darek pouze od zkuseneho rybare");
				return false;
			}
			
         if ( dropped is FishCoral || dropped is FishAlbinoAngelfish || dropped is FishBladePlant || dropped is FishAngelfish || 
         dropped is FishBlueCory || dropped is FishBrineShrimp || dropped is FishShrimp || dropped is FishSmallmouthSuckerfish || 
         dropped is FishVesperReefTiger || dropped is FishMinocBlue || dropped is FishNujelmHoney || dropped is FishFishies ||
         dropped is FishRainbowMolly || dropped is FishClownfish || dropped is FishGoldenBroadtail || dropped is FishFandancer ||
         dropped is FishBritainiaCrownFish || dropped is FishJellyfish || dropped is BigFish ||
         dropped is FishSpeckledCrab || dropped is FishSpottedBucaneer || dropped is FishSpottedPuffer || dropped is FishStripedSosarianSwill || 
         dropped is FishSeaHorse || dropped is Fish || dropped is FishBones )
			{
				if ( dropped.Amount > 0 )
				{
					int amount = ( dropped.Amount * ( ( dropped is Fish ) ? 1 : 1000 ) );

					m_Ep += amount;
					PlaySound( 58 );
					PlaySound( 138 );
					Emote("*" + this.Name + " snedl ryby za " + amount.ToString("N0", Auberon.Chat.General.Nfi) + " bodu*");
					dropped.Delete();
					
    				if ( m_Stage < m_FinalStage && m_Ep >= m_NextEpThreshold )
    				{
    					Evolve( false );
    				}
    				
					return true;
				}
			}
			else if ( dropped is WhitePearl )
			{
				if ( dropped.Amount > 0 )
				{
					if ( m_Absorb >= m_MaxAbsorb - dropped.Amount )
					{
						from.SendMessage("Vice perel delfin nechce.");
                  from.SendMessage( "Oklamani smrti: {0}x", m_Absorb / 10 );
						return false;
					}

					m_Absorb += dropped.Amount;
					PlaySound( 139 );
					Emote("*" + this.Name + " prijal " + dropped.Amount + " bilych perel*");
					from.SendMessage( "Oklamani smrti: {0}x", m_Absorb / 10 );
					dropped.Delete();
					return true;
				}
			}
			
			return base.OnDragDrop( from, dropped );
		}
		
		public override bool OnBeforeDeath()
		{
			if ( IsBonded && !Deleted && m_Absorb > 9 && DateTime.Now > m_NextAbsorbShield )
         {
            m_Absorb -= 10;
            Emote("*" + this.Name + " oklamal smrt*");
				this.FixedParticles( 0x376A, 9, 32, 5008, EffectLayer.Waist );
				this.PlaySound( 139 );
				m_NextAbsorbShield = DateTime.Now + TimeSpan.FromMinutes( 2.0 );
				this.Hits = ( this.HitsMaxSeed / 2 );
				return false;
         }
			
			return base.OnBeforeDeath();
		}
		
		public override void OnGotMeleeAttack( Mobile attacker )
		{
			base.OnGotMeleeAttack( attacker );

			if ( this.IsBonded && 0.1 > Utility.RandomDouble() )
			{
				Effects.PlaySound( this.Location, this.Map, 0x207 );
				ZoogiVejce.EffectCircle( this.Location, this.Map, 4, 0x376A );
				
				foreach ( Mobile mobile in this.Map.GetMobilesInRange( this.Location, 4 ) )
				{
					if ( mobile == null || mobile.Deleted || mobile.Blessed || !mobile.Alive )
						continue;
					
					if ( mobile is BaseCreature && !((BaseCreature)mobile).Controlled && !mobile.IsDeadBondedPet )
					{
						((BaseCreature)mobile).Pacify( this, DateTime.Now + TimeSpan.FromSeconds( 6.0 ) ); // TODO check
					}
				}
			}
		}
		
      public virtual void AlterSpellDamageTo(Mobile to, ref int damage)
      {
          damage += 1 + (int)(damage * 0.75);
      }
      
		public override void AlterMeleeDamageFrom( Mobile from, ref int damage )
		{
    		if ( from is SumPoisonElemental )
    		   damage = 0;
    		else if ( from is SaltwaterElemental || from is Leviathan )
            damage -= 1 + (int)(damage * 0.75);
		}
      
		public override void OnThink()
		{
			if( Utility.RandomDouble() < .005 ) // slim chance to jump
			{
            Server.Multis.BaseBoat boat = Server.Multis.BaseBoat.FindBoatAt(this, this.Map);
            
            if ( !IsDeadBondedPet && Hits > 2 && Alive && !Blessed && !IsInWater() && boat == null ) // ( boat == null && !SpecialFishingNet.FullValidation( this.Map, this.X, this.Y ) )
            {
               this.Hits /= 2;
               this.PlaySound( 142 );
            }
            else
            {
      			if( Utility.RandomBool() )
      				Animate( 3, 16, 1, true, false, 0 );
      			else
      				Animate( 4, 20, 1, true, false, 0 );
            }
         }

			base.OnThink();
		}

    	public bool IsInWater()
    	{
    		Map map = this.Map;
    		
         if ( map == null || map == Map.Internal || Deleted )
    			return false;
    
			Tile landTile = map.Tiles.GetLandTile( this.X, this.Y );
			Tile[] tiles = map.Tiles.GetStaticTiles( this.X, this.Y, true );

			bool hasWater = false;

			if ( landTile.Z == this.Z && ((landTile.ID >= 168 && landTile.ID <= 171) || (landTile.ID >= 310 && landTile.ID <= 311)) )
				hasWater = true;

			int z = this.Z;

			//int landZ = 0, landAvg = 0, landTop = 0;

			//map.GetAverageZ( tx, ty, ref landZ, ref landAvg, ref landTop );

			//if ( !landTile.Ignored && top > landZ && landTop > z )
			//	return false;

			for ( int i = 0; i < tiles.Length; ++i )
			{
				Tile tile = tiles[i];
				bool isWater = ( tile.ID >= 0x5796 && tile.ID <= 0x57B2 );

				if ( tile.Z == this.Z && isWater )
					hasWater = true;
				else if ( tile.Z >= this.Z && !isWater )
					return false;
			}

			if ( !hasWater )
				return false;
				
			return true;
    	}

		public EvoDolphin( string name ) : base( name, AIType.AI_Mage, 0.01 )
		{
         SpeechHue = Utility.RandomDyedHue();
         EmoteHue = Utility.RandomDyedHue();
         Body = 0x97;
			BaseSoundID = 0x8A;
			CanSwim = true;
			CantWalk = true;
		}

		public EvoDolphin( Serial serial ) : base( serial )
		{
		}
		
		public override void Serialize(GenericWriter writer)
		{
			base.Serialize(writer);

			writer.Write( (int)0 );
			
			writer.Write( m_Absorb );
			writer.Write( m_Charge );
		}

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

			int version = reader.ReadInt();
			
			m_Absorb = reader.ReadInt();
			m_Charge = reader.ReadInt();
		}
	}
}
