package JAKJ . RedstoneInMotion ;

public class MotiveSpectreEntity extends TileEntity
{
	public int DisplayList ;

	public int TicksExisted ;

	public static final int MotionDuration = 20 ;

	public static final double Velocity = 1 / ( ( double ) MotionDuration ) ;

	public Directions Motion ;

	public int DriveX ;
	public int DriveY ;
	public int DriveZ ;

	public BlockRecordSet Body ;

	public NbtList PendingBlockUpdates ;

	@Override
	public void updateEntity ( )
	{
		TicksExisted ++ ;

		for ( CapturedEntity Entity : CapturedEntities )
		{
			Entity . Update ( ) ;
		}

		if ( worldObj . isRemote )
		{
			return ;
		}

		if ( Motion == null )
		{
			WorldUtil . SetBlock ( worldObj , xCoord , yCoord , zCoord , 0 , 0 ) ;

			return ;
		}

		if ( TicksExisted < MotionDuration )
		{
			return ;
		}

		WorldUtil . SneakySetBlock ( worldObj , xCoord , yCoord , zCoord , 0 , 0 , null ) ;

		for ( BlockRecord Record : Body )
		{
			Record . Shift ( Motion ) ;

			// Record . Push ( this ) ;

			WorldUtil . SneakySetBlock ( worldObj , Record . X , Record . Y , Record . Z , Record . Id , Record . Meta , null ) ;
		}

		for ( BlockRecord Record : Body )
		{
			Block . Get ( Record . Id ) . onBlockAdded ( worldObj , Record . X , Record . Y , Record . Z ) ;

			if ( Record . EntityRecord != null )
			{
				Record . Entity = net . minecraft . tileentity . TileEntity . createAndLoadEntity ( Record . EntityRecord ) ;

				worldObj . setBlockTileEntity ( Record . X , Record . Y , Record . Z , Record . Entity ) ;
			}
		}

		( ( CarriageDriveEntity ) worldObj . getBlockTileEntity ( DriveX , DriveY , DriveZ ) ) . ToggleActivity ( ) ;

		WorldUtil . NotifyBlocks ( worldObj , xCoord , yCoord , zCoord , Blocks . MotiveSpectre . GetId ( ) , 0 ) ;

		for ( BlockRecord Record : Body )
		{
			WorldUtil . NotifyBlocks ( worldObj , Record . X , Record . Y , Record . Z , 0 , Record . Id ) ;
		}

		int PendingBlockUpdateCount = PendingBlockUpdates . tagCount ( ) ;

		for ( int Index = 0 ; Index < PendingBlockUpdateCount ; Index ++ )
		{
			net . minecraft . nbt . NBTTagCompound PendingBlockUpdateRecord = ( net . minecraft . nbt . NBTTagCompound ) PendingBlockUpdates . tagAt ( Index ) ;

			worldObj . scheduleBlockUpdateFromLoad
			(
				PendingBlockUpdateRecord . getInteger ( "X" ) + Motion . DeltaX ,
				PendingBlockUpdateRecord . getInteger ( "Y" ) + Motion . DeltaY ,
				PendingBlockUpdateRecord . getInteger ( "Z" ) + Motion . DeltaZ ,

				PendingBlockUpdateRecord . getInteger ( "Id" ) ,

				PendingBlockUpdateRecord . getInteger ( "Delay" ) ,

				PendingBlockUpdateRecord . getInteger ( "Foo" )
			) ;
		}
	}

	@Override
	public void Finalize ( )
	{
		if ( ! worldObj . isRemote )
		{
			return ;
		}

		TicksExisted = MotionDuration ;

		for ( CapturedEntity Entity : CapturedEntities )
		{
			Entity . Update ( ) ;
		}

		if ( DisplayList != 0 )
		{
			org . lwjgl . opengl . GL11 . glDeleteLists ( DisplayList , 1 ) ;
		}
	}

	@Override
	public void WriteToNbt ( NbtCompound TagCompound , boolean ToClient )
	{
		if ( Motion == null )
		{
			return ;
		}

		TagCompound . setInteger ( "Motion" , Motion . ordinal ( ) ) ;

		if ( ToClient )
		{
			NbtList CapturedEntityRecords = new NbtList ( ) ;

			for ( CapturedEntity Entity : CapturedEntities )
			{
				NbtCompound CapturedEntityRecord = new NbtCompound ( ) ;

				CapturedEntityRecord . setInteger ( "Id" , Entity . Entity . entityId ) ;

				CapturedEntityRecord . setDouble ( "InitialX" , Entity . InitialX ) ;
				CapturedEntityRecord . setDouble ( "InitialY" , Entity . InitialY ) ;
				CapturedEntityRecord . setDouble ( "InitialZ" , Entity . InitialZ ) ;

				CapturedEntityRecords . appendTag ( CapturedEntityRecord ) ;
			}

			TagCompound . setTag ( "CapturedEntities" , CapturedEntityRecords ) ;

			TagCompound . setTag ( "Body" , Body . GenerateTagList ( true ) ) ;
		}
		else
		{
			TagCompound . setInteger ( "DriveX" , DriveX ) ;
			TagCompound . setInteger ( "DriveY" , DriveY ) ;
			TagCompound . setInteger ( "DriveZ" , DriveZ ) ;

			TagCompound . setTag ( "Body" , Body . GenerateTagList ( false ) ) ;

			TagCompound . setTag ( "PendingBlockUpdates" , PendingBlockUpdates ) ;
		}
	}

	@Override
	public void ReadFromNbt ( NbtCompound TagCompound , boolean FromServer )
	{
		Motion = Directions . values ( ) [ TagCompound . getInteger ( "Motion" ) ] ;

		Body = new BlockRecordSet ( TagCompound . getTagList ( "Body" ) ) ;

		if ( FromServer )
		{
			CapturedEntities . clear ( ) ;

			for ( NbtCompound EntityRecord : TagCompound . getTagList ( "CapturedEntities" ) )
			{
				net . minecraft . entity . Entity Entity = worldObj . getEntityByID ( EntityRecord . getInteger ( "Id" ) ) ;

				if ( Entity == null )
				{
					continue ;
				}

				CapturedEntities . add ( new CapturedEntity ( Entity , EntityRecord . getDouble ( "InitialX" ) , EntityRecord . getDouble ( "InitialY" ) , EntityRecord . getDouble ( "InitialZ" ) ) ) ;
			}
		}
		else
		{
			DriveX = TagCompound . getInteger ( "DriveX" ) ;
			DriveY = TagCompound . getInteger ( "DriveY" ) ;
			DriveZ = TagCompound . getInteger ( "DriveZ" ) ;

			PendingBlockUpdates = TagCompound . getTagList ( "PendingBlockUpdates" ) ;
		}
	}

	public MotiveSpectreEntity ( )
	{
	}

	public class CapturedEntity
	{
		public net . minecraft . entity . Entity Entity ;

		public double InitialX ;
		public double InitialY ;
		public double InitialZ ;

		boolean WasOnGround ;

		boolean WasAirBorne ;

		public CapturedEntity ( net . minecraft . entity . Entity Entity )
		{
			this ( Entity , Entity . posX , Entity . posY , Entity . posZ ) ;
		}

		public CapturedEntity ( net . minecraft . entity . Entity Entity , double InitialX , double InitialY , double InitialZ )
		{
			this . Entity = Entity ;

			this . InitialX = InitialX ;
			this . InitialY = InitialY ;
			this . InitialZ = InitialZ ;

			WasOnGround = Entity . onGround ;

			WasAirBorne = Entity . isAirBorne ;

			Update ( ) ;
		}

		public void SetPosition ( double OffsetX , double OffsetY , double OffsetZ )
		{
			Entity . setPosition ( InitialX + OffsetX , InitialY + OffsetY + Entity . yOffset , InitialZ + OffsetZ ) ;
		}

		public void Update ( )
		{
			Entity . fallDistance = 0 ;

			if ( TicksExisted == MotionDuration )
			{
				Entity . motionX = 0 ;
				Entity . motionY = 0 ;
				Entity . motionZ = 0 ;

				SetPosition ( Motion . DeltaX , Motion . DeltaY , Motion . DeltaZ ) ;

				Entity . prevPosX = Entity . posX ;
				Entity . prevPosY = Entity . posY ;
				Entity . prevPosZ = Entity . posZ ;

				Entity . onGround = WasOnGround ;

				Entity . isAirBorne = WasAirBorne ;

				return ;
			}

			Entity . onGround = false ;

			Entity . isAirBorne = true ;

			Entity . motionX = Velocity * Motion . DeltaX ;
			Entity . motionY = Velocity * Motion . DeltaY ;
			Entity . motionZ = Velocity * Motion . DeltaZ ;

			SetPosition ( Entity . motionX * TicksExisted , Entity . motionY * TicksExisted , Entity . motionZ * TicksExisted ) ;

			Entity . prevPosX = Entity . posX - Entity . motionX ;
			Entity . prevPosY = Entity . posY - Entity . motionY ;
			Entity . prevPosZ = Entity . posZ - Entity . motionZ ;
		}
	}

	public java . util . ArrayList < CapturedEntity > CapturedEntities = new java . util . ArrayList < CapturedEntity > ( ) ;

	public static boolean CapturePlayerEntities = true ;
	public static boolean CaptureOtherLivingEntities = true ;
	public static boolean CaptureItemEntities = true ;
	public static boolean CaptureOtherEntities = true ;

	public MotiveSpectreEntity ( CarriagePackage Package )
	{
		Motion = Package . MotionDirection ;

		Body = Package . Blocks ;

		DriveX = Package . DriveRecord . X ;
		DriveY = Package . DriveRecord . Y ;
		DriveZ = Package . DriveRecord . Z ;

		if ( ! Package . DriveIsAnchored )
		{
			DriveX += Motion . DeltaX ;
			DriveY += Motion . DeltaY ;
			DriveZ += Motion . DeltaZ ;
		}

		PendingBlockUpdates = Package . PendingBlockUpdates ;

		{
			net . minecraft . util . AxisAlignedBB EntityCaptureBox = net . minecraft . util . AxisAlignedBB . getBoundingBox
			(
				Package . MinX - 5 , Package . MinY - 5 , Package . MinZ - 5 , Package . MaxX + 5 , Package . MaxY + 5 , Package . MaxZ + 5
			) ;

			java . util . List EntitiesFound = Package . World . getEntitiesWithinAABB ( net . minecraft . entity . Entity . class , EntityCaptureBox ) ;

			for ( Object EntityObject : EntitiesFound )
			{
				net . minecraft . entity . Entity Entity = ( net . minecraft . entity . Entity ) EntityObject ;

				BlockRecord PositionCheck = new BlockRecord ( ( int ) Math . floor ( Entity . posX ) , ( int ) Math . floor ( Entity . posY ) , ( int ) Math . floor ( Entity . posZ ) ) ;

				if ( ! Body . contains ( PositionCheck ) )
				{
					PositionCheck . Y -- ;

					if ( ! Body . contains ( PositionCheck ) )
					{
						PositionCheck . Y -- ;

						if ( ! Body . contains ( PositionCheck ) )
						{
							Entity = null ;
						}
					}
				}

				if ( Entity == null )
				{
					continue ;
				}

				if ( Entity instanceof net . minecraft . entity . player . EntityPlayer )
				{
					if ( ! CapturePlayerEntities )
					{
						continue ;
					}
				}
				else if ( Entity instanceof net . minecraft . entity . EntityLiving )
				{
					if ( ! CaptureOtherLivingEntities )
					{
						continue ;
					}
				}
				else if ( Entity instanceof net . minecraft . entity . item . EntityItem )
				{
					if ( ! CaptureItemEntities )
					{
						continue ;
					}
				}
				else if ( ! CaptureOtherEntities )
				{
					continue ;
				}

				CapturedEntities . add ( new CapturedEntity ( ( net . minecraft . entity . Entity ) Entity ) ) ;
			}
		}
	}

	@Override
	public net . minecraft . util . AxisAlignedBB getRenderBoundingBox ( )
	{
		return ( INFINITE_EXTENT_AABB ) ;
	}
}
