using System;
using Server;

namespace Server.Items
{
    public abstract class BaseSpawner : Item, ISpawner
    {
        private Mobile m_TrackedMobile;
        public bool UnlinkOnTaming { get { return true; } } 
        public Point3D HomeLocation { get { return this.Location; } }
        public int HomeRange { get { return 5; } }

        public void Remove( ISpawnable spawn )
        {
            if ( !this.Deleted )
                this.Delete();
        }

        public BaseSpawner() : base( 0x6519 )
        {
            Name = "spawn ref";
            Visible = false;
            Movable = false;
            
            Timer.DelayCall( TimeSpan.FromSeconds( 1.0 ), new TimerCallback( ExecuteSpawn ) );
        }

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

        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
            writer.Write( (int) 0 );
            
            writer.Write( m_TrackedMobile ); 
        }

        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
            int version = reader.ReadInt();
            m_TrackedMobile = reader.ReadMobile();

            if ( m_TrackedMobile != null && !m_TrackedMobile.Deleted && m_TrackedMobile.Alive )
            {
                if ( m_TrackedMobile is ISpawnable )
                {
                    ((ISpawnable)m_TrackedMobile).Spawner = this;
                }
            }
            else
            {
                Timer.DelayCall( TimeSpan.FromSeconds( 1.0 ), new TimerCallback( this.Delete ) );
            }
        }

        private void ExecuteSpawn()
		{
			if ( !this.Deleted && this.Map != null && this.Map != Map.Internal )
			{
				Point3D savedLocation = this.Location;
				Map savedMap = this.Map;

				// --- REGION SAFETY CHECK ---
				Region reg = Region.Find( savedLocation, savedMap );
				if ( reg is Server.Regions.TownRegion ||
					 reg is Server.Regions.GuardedRegion ||
                     reg is Server.Regions.DungeonRegion ||
                     reg is Server.Regions.FarmRegion ||
					 reg is Server.Regions.HouseRegion )
				{
					this.Delete();
					return;
				}
				// ---------------------------

				m_TrackedMobile = Server.SpawnList.RandomSpawn( this, savedLocation, savedMap );
				
				if ( m_TrackedMobile != null )
				{
					if ( m_TrackedMobile is ISpawnable )
					{
						((ISpawnable)m_TrackedMobile).Spawner = this;
					}

					// --- NEW SCATTER LOGIC ---
					int scatterRange = 25; // Default fallback range
					
					// 1. Look down at our feet to find the parent spawner and borrow its HomeRange!
					foreach ( Item item in savedMap.GetItemsInRange( savedLocation, 0 ) )
					{
						if ( item is ISpawner )
						{
							scatterRange = ((ISpawner)item).HomeRange;
							break;
						}
					}

					Point3D spawnPoint = savedLocation;

					// 2. Try up to 15 times to find a valid tile within that range
					for ( int i = 0; i < 15; i++ )
					{
						int x = savedLocation.X + Utility.RandomMinMax( -scatterRange, scatterRange );
						int y = savedLocation.Y + Utility.RandomMinMax( -scatterRange, scatterRange );
						int z = savedMap.GetAverageZ( x, y );
						Point3D testPoint = new Point3D( x, y, z );

						// If this is the water proxy, specifically seek out water tiles using your SpawnList system
						if ( this is SpawnWater )
						{
							if ( Server.SpawnList.GetTerrain( savedMap, testPoint, x, y ) == Server.Terrain.Water )
							{
								spawnPoint = testPoint;
								break; // Found a valid water spot!
							}
						}
						// If it's a land proxy, ensure the mob doesn't accidentally spawn in the ocean
						else 
						{
							if ( savedMap.CanFit( x, y, z, 16, false, false ) )
							{
								spawnPoint = testPoint;
								break; // Found a valid land spot!
							}
						}
					}
					// -------------------------

					// Move the mob to the scattered location instead of the center
					m_TrackedMobile.MoveToWorld( spawnPoint, savedMap );
					
					this.Internalize(); 
				}
				else
				{
					this.Delete();
				}
			}
			else if ( !this.Deleted )
			{
				this.Delete();
			}
		}
    }
	public class SpawnAnimals : BaseSpawner
	{
		[Constructable]
		public SpawnAnimals(){} public SpawnAnimals( Serial serial ) : base( serial ){} public override void Serialize( GenericWriter writer ){ base.Serialize( writer ); writer.Write( (int) 0 ); } public override void Deserialize( GenericReader reader ){ base.Deserialize( reader ); int version = reader.ReadInt(); }
	}

	public class SpawnBirds : BaseSpawner
	{
		[Constructable]
		public SpawnBirds(){} public SpawnBirds( Serial serial ) : base( serial ){} public override void Serialize( GenericWriter writer ){ base.Serialize( writer ); writer.Write( (int) 0 ); } public override void Deserialize( GenericReader reader ){ base.Deserialize( reader ); int version = reader.ReadInt(); }
	}

	public class SpawnCritters : BaseSpawner
	{
		[Constructable]
		public SpawnCritters(){} public SpawnCritters( Serial serial ) : base( serial ){} public override void Serialize( GenericWriter writer ){ base.Serialize( writer ); writer.Write( (int) 0 ); } public override void Deserialize( GenericReader reader ){ base.Deserialize( reader ); int version = reader.ReadInt(); }
	}

	public class Spawn_A : BaseSpawner
	{
		[Constructable]
		public Spawn_A(){} public Spawn_A( Serial serial ) : base( serial ){} public override void Serialize( GenericWriter writer ){ base.Serialize( writer ); writer.Write( (int) 0 ); } public override void Deserialize( GenericReader reader ){ base.Deserialize( reader ); int version = reader.ReadInt(); }
	}

	public class Spawn_B : BaseSpawner
	{
		[Constructable]
		public Spawn_B(){} public Spawn_B( Serial serial ) : base( serial ){} public override void Serialize( GenericWriter writer ){ base.Serialize( writer ); writer.Write( (int) 0 ); } public override void Deserialize( GenericReader reader ){ base.Deserialize( reader ); int version = reader.ReadInt(); }
	}

	public class Spawn_C : BaseSpawner
	{
		[Constructable]
		public Spawn_C(){} public Spawn_C( Serial serial ) : base( serial ){} public override void Serialize( GenericWriter writer ){ base.Serialize( writer ); writer.Write( (int) 0 ); } public override void Deserialize( GenericReader reader ){ base.Deserialize( reader ); int version = reader.ReadInt(); }
	}

	public class Spawn_D : BaseSpawner
	{
		[Constructable]
		public Spawn_D(){} public Spawn_D( Serial serial ) : base( serial ){} public override void Serialize( GenericWriter writer ){ base.Serialize( writer ); writer.Write( (int) 0 ); } public override void Deserialize( GenericReader reader ){ base.Deserialize( reader ); int version = reader.ReadInt(); }
	}

	public class Spawn_E : BaseSpawner
	{
		[Constructable]
		public Spawn_E(){} public Spawn_E( Serial serial ) : base( serial ){} public override void Serialize( GenericWriter writer ){ base.Serialize( writer ); writer.Write( (int) 0 ); } public override void Deserialize( GenericReader reader ){ base.Deserialize( reader ); int version = reader.ReadInt(); }
	}
public class SpawnWater : BaseSpawner
	{
		[Constructable]
		public SpawnWater(){} public SpawnWater( Serial serial ) : base( serial ){} public override void Serialize( GenericWriter writer ){ base.Serialize( writer ); writer.Write( (int) 0 ); } public override void Deserialize( GenericReader reader ){ base.Deserialize( reader ); int version = reader.ReadInt(); }
	}
}
