// ASSIGNMENT 4
// Spaceship.java: implementation of a spaceship
// The spaceship is located inside a 10x10 grid.
//   Position (1,1) is at the upper left corner;
//   Position (1,10) is the upper right;
//   Position (10,1) is the lower left;
//   Position (10,10) is the lower right.
// Spaceships use 1.0 ton of fuel to move 1 unit on the grid.

public class Spaceship
{
    // The fuel tank has a maximum capacity
    // Now you know what 'static' and 'final' mean here.
    static final double MAXFUEL = 30.0;
    
    // This lets us indicate that the ship hasn't
    // landed on anything.  It deliberately has
    // "invalid" x and y positions, because it doesn't
    // exist in our space.
    static final Planet noPlanet = new Planet("NoPlanet", -1, -1);
    static final Planet Earth = new Planet("Earth", 1, 1);
    
    // Note these are private variables now:
    // We don't want anyone modifying them! 
    // Keep track of the amount of fuel the spaceship has
    private double tonsOfFuel;
    // Keep track of the current position of the spaceship
    // (Note this is now a Position object)
    private Position pos;
    // New variable: if the Spaceship has landed on a planet,
    // this indicates which one
    private Planet landedOn;
    // New variable: each Spaceship can have a name
    private String name;

    // constructor: create a new Spaceship at 
    // the specified location, with a full fuel tank,
    // and not landed on anything, with no name.
    // assume that x and y are valid location values.
    public Spaceship(int x, int y)
    {
    	// Instead of just assigning, we need to create a new
    	// Position object.
    	pos = new Position(x, y);
			// Starts with a full tank.
			tonsOfFuel = MAXFUEL;
			// Starts out in space, not landed on anything
			landedOn = noPlanet;
			name = "";
    }

/**************************************************************/

	  // -------- You must implement this method --------- //
		// default constructor: create a Spaceship at (5,5)
		// with a full fuel tank, and not landed on anything.
		// Also give it a default name, as above.
    public Spaceship()
    {
    }

/**************************************************************/

	  // -------- You must add a constructor here --------- //
	  // It should take in a Planet, assume that the ship
	  // has landed on that planet, and set the ship's
	  // x and y coordinates (to the same as those of the 
	  // planet it is on).  Again, it gets a full fuel tank.
		// Initialize the name to a default value.	  
	  
	  
	  
	  
	  
	  
	  
/**************************************************************/
	  
	  // -------- You must implement this method --------- //
	  // setName: christen the Spaceship.
	  // Input: a String representing the new name.
	  // Output: none.
	  public void setName(String n)
	  {
	  	// This is a stub. (REMOVE this comment) 
	  }

/**************************************************************/

	  // -------- You must implement this method --------- //
	  // land: land on a Planet.
	  // Input: which Planet to land on.
	  // Output: if this succeeds, return 0.  Otherwise:
	  //   1) If the ship is not in the same location
	  //      as the Planet, return 1.
	  //   2) Landing requires 0.1 tons of fuel.  If
	  //      the ship doesn't have enough fuel, return 2.
	  public int land(Planet p)
	  {
	  	// This is a stub. (REMOVE this comment) 
	  	return 0;
	  }
	  
/**************************************************************/

	  // -------- You must implement this method --------- //
	  // launch: leave the Planet and return to space.
	  // Input: none.
	  // Output: if this succeeds, return 0.  Otherwise:
	  //   1) If the ship is not on a Planet, return 1.
	  //   2) Launching requires 0.5 tons of fuel.  If
	  //      the ship doesn't have enough fuel, return 2.
	  public int launch()
	  {
	  	// This is a stub. (REMOVE this comment) 
	  	return 0;
	  }

/**************************************************************/

	  // -------- You must UPDATE this method --------- //
    // move: move the spaceship 'horiz' units horizontally
    //       and 'vert' units vertically.  Also, decrement
    //       the current fuel level appropriately.
    //       If the specified movement is invalid, do not
    //       update the ship's position or its fuel level.
    // Input: two integers, as described above
    // Output: if this succeeds, return 0.  Otherwise:
    //   1) If the ship has landed on a planet, it cannot
    //      move.  Return 1. 
    //   2) If moving as dictated by 'horiz' and 'vert' would
    //      cause the ship to go outside the boundaries of the
    //      10x10 grid, return 2.
    //      Hint: use isValidPosition().
    //   3) If the ship does not have enough fuel to move
    //      as dictated by 'horiz' and 'vert', return 3.
    public int move(int horiz, int vert)
    {
			// Check for a valid move
			// Note pos is now an instance variable.
			int newX = pos.getX() + horiz;
			int newY = pos.getY() + vert;
			if (!isValidPosition(newX, newY))
			{
	    	// Error!  Out of bounds move.
	    	return 1;
			}
	
			// Check that we have enough fuel to move.
			// First, calculate the diagonal distance we would
			// need to travel, using the Pythagorean theorem:
			double dist = Math.sqrt(horiz*horiz + vert*vert);

			// Since we consume one ton of fuel for every unit
			// traveled, check if this movement would exceed the
			// fuel supply:
			if (dist > tonsOfFuel)
			{
	    	// Error! Not enough fuel.
	    	return 2;
			}

			// Otherwise, move the ship by updating the location:
			// Note pos is now an instance variable.
			pos = new Position(newX, newY);

			// Don't forget to update the fuel level.
			tonsOfFuel -= dist;

			// Return 0 to indicate success.
			return 0;
    }

/**************************************************************/

	  // -------- You must UPDATE this method --------- //
    // hyperjump: jump the ship instantly to position
    //            ('newXPos','newYPos').  This costs 5.0 tons
    //            of fuel, regardless of how far the ship goes.
    // Input: two integers indicating the new position
    // Output: if this succeeds, return 0.  Otherwise:
    //   1) If the ship has landed on a planet, it cannot
    //      move.  Return 1. 
    //   2) If ('newXPos','newYPos') indicates an invalid position
    //      (outside of the 10x10 grid), return 2.
    //      Hint: use isValidPosition().
    //   3) If the ship does not have enough fuel to make
    //      the jump, return 3.
    public int hyperjump(int newXPos, int newYPos)
    {
			// Check for a valid move
			if (!isValidPosition(newXPos, newYPos))
			{
	    	// Error!  Out of bounds move.
	    	return 1;
			}
	
			// Check that we have enough fuel to move.
			if (tonsOfFuel < 5.0)
			{
	    	// Error! Not enough fuel.
	    	return 2;
			}

			// Otherwise, move the ship by updating the location:
			// Note pos is now an instance variable.
			pos = new Position(newXPos, newYPos);

			// Don't forget to update the fuel level.
			tonsOfFuel -= 5.0;

			// Return 0 to indicate success.
			return 0;
    }

/**************************************************************/

		// --------------------------------------------------- //
		// You do not need to change anything below this line. //
		// However, you must read through the implementation.
		// (this is the solution to Assignment 3's Spaceship.)
		// There are also some important changes, which are
		// clearly marked.
		// --------------------------------------------------- //
			  
	  // This is a NEW method.  It replaces the
	  // displayStats() method from before.
    // toString: Used by Java to print the spaceship nicely
    // Input: none
    // Output: a String describing the ship
    public String toString()
    {
			// Note that because Position now has a toString()
			// method, we can just print it out directly!
			return new String("[" + name + ": position " + pos +
												"; " + getFuel() + " tons of fuel]");
    }

    // getFuel: return the current fuel amount.
    // Input: none
    // Output: a double representing the fuel amount.
    // 1 point correctness, 1 point style
    public double getFuel()
    {
			return tonsOfFuel;
    }

    // isValidPosition: check if (x,y) is a valid position
    //                  on the 10x10 grid.
    // Input: two integers representing the position to check
    // Output: true if the position is valid, otherwise false
    public boolean isValidPosition(int x, int y)
    {
			if (x >= 1 && x <= 10 && y >= 1 && y <= 10)
			{
	    	// This is a valid grid position.
	    	return true;
			}
			// You could also have an 'else' statement here.
		 	return false;
    }

    // refuel: fill the ship's tank.  This will only succeed
    //         if the ship has returned to Earth (position (1,1)).
    //         Hint: if you have two variables of type Position,
    //         you can check to see if they are equal in the
    //         same way we do for Strings: use equals().
    // Input: none
    // Output: if this succeeds, return 0.  Otherwise, return 1.
    public int refuel()
    {
			// Check the current location.  If we aren't at Earth,
			// fail (return 1).
			// Note pos is now an instance variable.
			// Also note that you need a getLocation()
			//  method in the Planet class, to return
			//  a Position object.
			if (!pos.equals(Earth.getLocation()))
			{
	    	return 1;
			}
	
			// Fill 'er up!
			tonsOfFuel = MAXFUEL;

			// Indicate success.
			return 0;
    }


    // getLocation: returns the current position of the spaceship,
    // in (x,y) coordinates
    // Input: none
    // Output: a Position object (see Position.java)    
    public Position getLocation()
    {
			// Create a new Position object, setting its x and y
			// values to the current location of the spaceship.
			// Note pos is now an instance variable.
			Position thePos = new Position(pos.getX(), pos.getY());

			// Return this pair of values to the user.
			return thePos;
    }
}
