/*****************************************************************************/
/*                                                                           */
/*             Car Pool: Car Pool Vehicle Tracker Support Class              */
/*                                                                           */
/*                       October 1999, Jacob Lundberg                        */
/*                                                                           */
/*****************************************************************************/

// cars in a CarPool are get'ed and returned by color.

class car
  {
  public car prev;
  public car next;
  public car prevSame;
  public car nextSame;
  public int carNumber;
  public int carColor;
  public boolean available;

  // Construct a head.
  public car()
    {
    prev = this;
    next = this;
    prevSame = this;
    nextSame = this;
    carNumber = -1;
    carColor = -1;
    available = false;
    }

  // Construct a normal node.
  public car( int num, int col )
    {
    prev = null;
    next = null;
    prevSame = null;
    nextSame = null;
    carNumber = num;
    carColor = col;
    available = true;
    }

  // Call this on head to count total cars.
  public int count()
    {
    int increment = 1;
    if( carNumber < 0 )
      --increment;
    if( next == null || next.carNumber < 0 )
      return increment;
    else
      return next.count() + increment;
    }

  // Call this on a color chain to count same-colored cars.
  public int countSame()
    {
    int increment = 1;
    if( carNumber < 0 )
      --increment;
    if( nextSame == null || nextSame.carNumber < 0 )
      return increment;
    else
      return nextSame.countSame() + increment;
    }

  // Find a car by its number; called on head.
  public car find( int num )
    {
    if( carNumber == num )
      return this;
    else if( next == null || next.carNumber < 0 )
      return null;
    else
      return next.find( num );
    }

  // Find a car by number and color; called on head; faster.
  public car find( int num, int col )
    {
    if( carNumber == num )
      return this;
    else if( nextSame == null || nextSame.carNumber < 0 )
      return null;
    else
      return nextSame.find( num, col );
    }
  }

class CarPool
  {
  // One head.
  private car head;
  // Three car colors are assumed.
  // The user may create more by adding more 'new car()' entries.
  private car[] colors = { new car(), new car(), new car() };

  public CarPool()
    {
    head = new car();
    System.out.println( "CarPool: Contructed new CarPool." );
    }

  public boolean addCar( int num, int col )
    {
    // Make sure the car isn't a duplicate.
    if( head.find( num ) != null )
      {
      System.out.println( "CarPool: Can't add. Car " + num + " already exists." );
      return false;
      }

    // Insert the car into the primary chain.
    car newCar = new car( num, col );
    newCar.prev = head.prev;
    newCar.next = head;
    head.prev.next = newCar;
    head.prev = newCar;

    // Insert the car into the right color chain.
    newCar.prevSame = colors[newCar.carColor].prevSame;
    newCar.nextSame = colors[newCar.carColor];
    colors[newCar.carColor].prevSame.nextSame = newCar;
    colors[newCar.carColor].prevSame = newCar;
    System.out.println( "CarPool: Added car " + head.prev.carNumber + ", color " + head.prev.carColor + "." );
    return true;
    }

  // Delete a car by number.
  public car delCar( int num )
    {
    car findCar = head.find( num );
    if( findCar == null )
      {
      System.out.println( "CarPool: Can't delete. Car " + num + " doesn't exist." ); 
      return null;
      }
    findCar.prevSame.nextSame = findCar.nextSame;
    findCar.nextSame.prevSame = findCar.prevSame;
    findCar.prev.next = findCar.next;
    findCar.next.prev = findCar.prev;
    System.out.println( "CarPool: Deleted car " + findCar.carNumber + ", color " + findCar.carColor + "." );
    return findCar;
    }

  // Delete a car by number and color; faster.
  public car delCar( int num, int col )
    {
    car findCar = colors[col].find( num, col );
    if( findCar == null )
      {
      System.out.println( "CarPool: Can't delete. Car " + num + ", color " + col + " doesn't exist." ); 
      return null;
      }
    findCar.prevSame.nextSame = findCar.nextSame;
    findCar.nextSame.prevSame = findCar.prevSame;
    findCar.prev.next = findCar.next;
    findCar.next.prev = findCar.prev;
    System.out.println( "CarPool: Deleted car " + findCar.carNumber + ", color " + findCar.carColor + "." );
    return findCar;
    }

  // Check a car out of the pool.
  public int getCar( int color )
    {
    car Car = colors[color];
    while( Car.nextSame != null && Car.nextSame.carNumber >= 0 )
      {
      Car = Car.nextSame;
      if( Car.available == true )
        {
        Car.available = false;
        System.out.println( "CarPool: Checked out car " + Car.carNumber + ", color " + Car.carColor + "." ); 
        return Car.carNumber;
        }
      }
    System.out.println( "CarPool: Can't get. Car color " + color + " doesn't exist or all checked out." ); 
    return -1;
    }

  // Check a car into the pool.
  public boolean returnCar( int num )
    {
    car Car = head.find( num );
    if( Car == null )
      {
      System.out.println( "CarPool: Can't return. Car " + num + " doesn't exist." ); 
      return false;
      }
    Car.available = true;
    System.out.println( "CarPool: Returned car " + num + ", color " + Car.carColor + "." ); 
    return true;
    }

  // Count the total number of cars in a CarPool.
  public int countCars()
    {
    int count = head.count();
    System.out.println( "CarPool: Number of cars total counted to be " + count + "." );
    return count;
    }

  // Count the number of cars of a given color in a CarPool.
  public int countCars( int col )
    {
    int count = colors[col].countSame();
    System.out.println( "CarPool: Number of cars in color " + col + " counted to be " + count + "." );
    return count;
    }
  }

