//
import java.io.*;
import java.util.StringTokenizer;

class Board
{
	int	xSize;
	int	ySize;
	int	iCurrent;
	int	jCurrent;
	int	iStop;
	int	jStop;
	int	east;
	int	north;
	int	west;
	int	south;
	int	direction;	// Change to an enumerated type?
	int routeLayer1[][];

	Board( int xSizeIn, int ySizeIn )
	{
		int	i = xSizeIn;
		int	j = ySizeIn;
		
		xSize = xSizeIn;
		ySize = ySizeIn;

		System.out.print("Construct Board.\n");
		
		System.out.print("Allocate grid array, " + xSize + " by " + ySize + ".\n");
		routeLayer1 = new int[xSize][ySize];

		for ( i=0; i<xSize; i++ )
			for( j=0; j<ySize; j++ )
			{
				routeLayer1[i][j] = 0;
			}


	}

	int Read()
	{
		System.out.print("Read Board from file.\n");
		System.out.print("(Not implemented yet.)\n");
		return(1);
	}

	int Write( String boardOutFileName ) throws Exception
	{
		int	i = xSize;
		int	j = ySize;
		FileOutputStream boardOutFile = new FileOutputStream( boardOutFileName );

		System.out.print("Write Board to file\n");
		System.out.print("(Not implemented yet.)\n");
		System.out.print("Display board w/ text.\n");

		System.out.print("routeLayer1:\n");
		System.out.print("( X, Y ): ( " + xSize + ", " + ySize + " )\n" );
		boardOutFile.write( xSize );
		boardOutFile.write( ySize );
		for ( j = ( ySize - 1 ); j >= 0; j-- )
		{
			for( i = 0; i < xSize; i++ )
			{
				System.out.print( routeLayer1[i][j] );
				boardOutFile.write( routeLayer1[i][j] );
			}
			System.out.println();
		}

		return(1);
	}

	int Route( int iStart, int jStart, int iStopIn, int jStopIn )
	{
		iCurrent = iStart;
		jCurrent = jStart;
		iStop = iStopIn;
		jStop = jStopIn;
		double	angleToTarget;

		
		System.out.print("Route Board\n");

		// Clear stop point to make it routable.
		// Will reset to pin code (5) when done routing this net.
		System.out.print("Set routeLayer1[iStop][jStop] = 0 for routing.\n");
		routeLayer1[iStop][jStop] = 0;

		while( ( ( iStop - iCurrent ) != 0 ) || ( ( jStop - jCurrent ) != 0 ) )
		{

			// Try to get value for grid to the east.
			try
			{
				east = routeLayer1[( iCurrent + 1 )][jCurrent];
			}
			catch( ArrayIndexOutOfBoundsException e )
			{
				System.out.print("East ( " + ( iCurrent + 1 )  + ", " + jCurrent + " ) is out of bounds\n");
				// Give east a value indicating it is out of bounds and unrouteable
				east = 7;
			}

			// Try to get value for grid to the north.
			try
			{
				north = routeLayer1[iCurrent][( jCurrent + 1 )];
			}
			catch( ArrayIndexOutOfBoundsException e )
			{
				System.out.print("North ( " + iCurrent + ", " + ( jCurrent + 1 ) + " ) is out of bounds\n");
				// Give north a value indicating it is out of bounds and unrouteable
				north = 7;
			}

			// Try to get value for grid to the west.
			try
			{
				west = routeLayer1[( iCurrent - 1 )][jCurrent];
			}
			catch( ArrayIndexOutOfBoundsException e )
			{
				System.out.print("West ( " + ( iCurrent - 1 )  + ", " + jCurrent + " ) is out of bounds\n");
				// Give west a value indicating it is out of bounds and unrouteable
				west = 7;
			}

			// Try to get value for grid to the south.
			try
			{
				south = routeLayer1[iCurrent][( jCurrent - 1 )];
			}
			catch( ArrayIndexOutOfBoundsException e )
			{
				System.out.print("South ( " + iCurrent + ", " + ( jCurrent - 1 ) + " ) is out of bounds\n");
				// Give east a value indicating it is out of bounds and unrouteable
				south = 7;
			}

			angleToTarget = Math.atan2( ( jStop - jCurrent ), ( iStop - iCurrent ) );

			direction = GetDirectionToTarget( angleToTarget );

			switch( direction )
			{
				case 1: // East North East
					if ( east == 0 ) GoEast();
					else if ( north == 0 ) GoNorth();
					else if ( south == 0 ) GoSouth();
					else if ( west == 0 ) GoWest();
					else GoBack();
					break;
				case 2: // North North East
					if ( north == 0 ) GoNorth();
					else if ( east == 0 ) GoEast();
					else if ( west == 0 ) GoWest();
					else if ( south == 0 ) GoSouth();
					else GoBack();
					break;
				case 3: // North North West
					if ( north == 0 ) GoNorth();
					else if ( west == 0 ) GoWest();
					else if ( east == 0 ) GoEast();
					else if ( south == 0 ) GoSouth();
					else GoBack();
					break;
				case 4: // West North West
					if ( west == 0 ) GoWest();
					else if ( north == 0 ) GoNorth();
					else if ( south == 0 ) GoSouth();
					else if ( east == 0 ) GoEast();
					else GoBack();
					break;
				case 5: // West South West
					if ( west == 0 ) GoWest();
					else if ( south == 0 ) GoSouth();
					else if ( north == 0 ) GoNorth();
					else if ( east == 0 ) GoEast();
					else GoBack();
					break;
				case 6: // South South West
					if ( south == 0 ) GoSouth();
					else if ( west == 0 ) GoWest();
					else if ( east == 0 ) GoEast();
					else if ( north == 0 ) GoNorth();
					else GoBack();
					break;
				case 7: // South South East
					if ( south == 0 ) GoSouth();
					else if ( east == 0 ) GoEast();
					else if ( west == 0 ) GoWest();
					else if ( north == 0 ) GoNorth();
					else GoBack();
					break;
				case 8: // East South East
					if ( east == 0 ) GoEast();
					else if ( south == 0 ) GoSouth();
					else if ( north == 0 ) GoNorth();
					else if ( west == 0 ) GoWest();
					else GoBack();
					break;
				default:
					System.out.print("ERROR: Direction to target not found:" + direction + ".\n");
			}
		}
		
		// Change stop point back to code for pin (or wire end).
		System.out.print("Set routeLayer1[iStop][jStop] = 5(pin/end wire).\n");
		routeLayer1[iStop][jStop] = 5;
		
		return(1);
	}
	
	int GetDirectionToTarget( double angleToTarget )
	{
		int direction = 0;
		
		if ( ( angleToTarget <= ( Math.PI / 4 ) ) && ( angleToTarget > 0 ) ) direction = 1;
		else if ( ( angleToTarget <= ( Math.PI / 2 ) ) && ( angleToTarget > ( Math.PI / 4 ) ) ) direction = 2;
		else if ( ( angleToTarget <= ( 3 * Math.PI / 4 ) ) && ( angleToTarget > ( Math.PI / 2 ) ) ) direction = 3;
		else if ( ( angleToTarget <= Math.PI ) && ( angleToTarget > ( 3 * Math.PI / 4 ) ) ) direction = 4;
		else if ( ( angleToTarget >= -Math.PI ) && ( angleToTarget < -( 3 * Math.PI / 4 ) ) ) direction = 5;
		else if ( ( angleToTarget >= -( 3 * Math.PI / 4 ) ) && ( angleToTarget < -( Math.PI / 2 ) ) ) direction = 6;
		else if ( ( angleToTarget >= -( Math.PI / 2 ) ) && ( angleToTarget < -( Math.PI / 4 ) ) ) direction = 7;
		else if ( ( angleToTarget >= -( Math.PI / 4 ) ) && ( angleToTarget <= 0 ) ) direction = 8;
		else
		{
			System.out.print("ERROR: Angle to target not found:" + angleToTarget + ".\n");
		}
		
		
		return( direction );
	
	}

	int GoEast()
	{
		System.out.print("Going East.\n");
		routeLayer1[iCurrent][jCurrent] = 1;
		iCurrent++;
	
		return ( 1 );
	}
	
	int GoNorth()
	{
		System.out.print("Going North.\n");
		routeLayer1[iCurrent][jCurrent] = 2;
		jCurrent++;
	
		return ( 1 );
	}
	
	int GoWest()
	{
		System.out.print("Going West.\n");
		routeLayer1[iCurrent][jCurrent] = 3;
		iCurrent--;
	
		return ( 1 );
	}
	
	int GoSouth()
	{
		System.out.print("Going South.\n");
		routeLayer1[iCurrent][jCurrent] = 4;
		jCurrent--;
	
		return ( 1 );
	}
	
	int GoBack()
	{
		System.out.print("Going Back.\n");
		routeLayer1[iCurrent][jCurrent] = 6;
		
		if ( west == 1 ) GoBackWest();
		else if ( south == 2 ) GoBackSouth();
		else if ( east == 3 ) GoBackEast();
		else if ( north == 4 ) GoBackNorth();
		else
		{
			System.out.print("No way back -- this route has failed\n");
			// Set (iCurrent,jCurrent) to (iStop,jStop) to quit this route
			iCurrent = iStop;
			jCurrent = jStop;
		}
	
		return ( 1 );
	}
	
	int GoBackEast()
	{
		System.out.print("Going East.\n");
		iCurrent++;
	
		return ( 1 );
	}
	
	int GoBackNorth()
	{
		System.out.print("Going North.\n");
		jCurrent++;
		return ( 1 );
	}
	
	int GoBackWest()
	{
		System.out.print("Going West.\n");
		iCurrent--;
		return ( 1 );
	}
	
	int GoBackSouth()
	{
		System.out.print("Going South.\n");
		jCurrent--;
		return ( 1 );
	}
	
}

