import junit.framework.TestCase;

/**
 * A test class for the Driver class.
 */
public class DriverTester extends TestCase {
  
  //-------- Constructors (3) ---------------------------------------
  /**
   * Test whether the constructor and the getter methods work properly.
   */
  public void testConstructor1AndGetters() {
    Driver d = new Driver("John Doe", 35, 532.00);
    
    assertEquals("John Doe", d.getName());
    assertEquals(35, d.getAge());
    assertEquals(532.00, d.getMoney());
    assertEquals(0.0, d.getInsurance());
    assertEquals(0, d.getDemeritPoints());
    assertNull(d.getCar());
  }

  /**
   * Test whether the constructor and the getter methods work properly.
   */
  public void testConstructor2AndGetters() {
    Car c = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 15532.00, c);
    
    assertEquals("John Doe", d.getName());
    assertEquals(35, d.getAge());
    assertEquals(15532.00, d.getMoney());
    assertEquals(485.73, d.getInsurance());
    assertEquals(0, d.getDemeritPoints());
    assertEquals(c, d.getCar());
    assertEquals("APS 101", d.getCar().getLicensePlate());
  }
  
  /**
   * Test whether the constructor and the getter methods work properly.
   */
  public void testConstructor3AndGetters() {
    Car c = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 15532.00, c, "MyCar RULZ!");
    
    assertEquals("John Doe", d.getName());
    assertEquals(35, d.getAge());
    assertEquals(15532.00, d.getMoney());
    assertEquals(485.73, d.getInsurance());
    assertEquals(0, d.getDemeritPoints());
    assertEquals(c, d.getCar());
    assertEquals("MyCar RULZ!", d.getCar().getLicensePlate());
  }

  //-------- Getters (7) ---------------------------------------  
  /**
   * Test getName
   */
  public void testGetName() {    
    Driver d = new Driver("John Doe", 35, 532.00);
    assertEquals("John Doe", d.getName());
  }

  /**
   * Test getAge
   */
  public void testGetAge() {    
    Driver d = new Driver("John Doe", 35, 532.00);
    assertEquals(35, d.getAge());
  }

  /**
   * Test getMoney
   */
  public void testGetMoney() {    
    Driver d = new Driver("John Doe", 35, 532.00);    
    assertEquals(532.00, d.getMoney());
  }

  /**
   * Test getDemeritPoints
   */
  public void testGetDemeritPoints() {    
    Driver d = new Driver("John Doe", 35, 532.00);    
    assertEquals(0, d.getDemeritPoints());
  }

  /**
   * Test getInsurance
   */
  public void testGetInsurance() {    
    Car c = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 15532.00, c);
    assertEquals(485.73, d.getInsurance());
  }
    
  /**
   * Test getCar
   */
  public void testGetCar() {    
    Car c = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 15532.00, c);
    assertEquals(c, d.getCar());
  }
  
  /**
   * Test getLicensePlate
   */
  public void testGetLicensePlate() {    
    Car c = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 15532.00, c, "MyCar RULZ");
    assertEquals("MyCar RULZ", d.getCar().getLicensePlate());  
  }  
  

  //-------- Methods (25) ---------------------------------------
  /**
   * Test hasCar
   */
  public void testHasCar() {
    Car c = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 15532.00, c);
    
    assertNotNull(d.getCar());
    assertTrue(d.hasCar());
  }

  /**
   * Test inDebt
   */
  public void testInDebt() {
    Driver d = new Driver("John Doe", 35, -517.33);
    assertTrue(d.inDebt());
  }

  /**
   * Test inDebt2
   */
  public void testInDebt2() {
    Car crtcar = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 517.33, crtcar);
    assertFalse(d.inDebt());
    d.payInsurance();
    assertFalse(d.inDebt());
    d.receiveParkingTicket(90.3);
    assertTrue(d.inDebt());
  }  
  
  /**
   * Test canAfford
   */
  public void testCanAfford() {
    Car c = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 14999.33);
    assertFalse(d.canAfford(c));
  }

  /**
   * Test canAfford2
   */
  public void testCanAfford2() {
    Car oldcar = new Car(2003, "Toyota", "Landcruiser", "blue", 12000.0);
    Car newcar = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 14999.99, oldcar);
    assertFalse(d.canAfford(newcar));
    d.makeMoney(1000.01);
    assertTrue(d.canAfford(newcar));    
    d.receiveParkingTicket(690);
    assertTrue(d.canAfford(newcar));    
    d.payInsurance();
    assertFalse(d.canAfford(newcar));   
  }
  
  /**
   * Test repaint
   */
  public void testRepaintCar() {
    Car c = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 14999.33, c);
    d.repaintCar("blue");
    
    assertEquals("blue", d.getCar().getColour());
  }  

  /**
   * Test updateInsurance
   */
  public void testUpdateInsurance() {
    Car c = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 14999.33, c);

    d.updateInsurance();
    assertEquals(485.73, d.getInsurance());
  }

  /**
   * Test growOlder
   */
  public void testGrowOlder() {
    Car c = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 14999.33, c);
  
    d.growOlder();
    assertEquals(36, d.getAge());
    assertEquals(481.91, d.getInsurance());
  }

  /**
   * Test receiveSpeedingTicket
   */
  public void testSTicket() {
    Car c = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 14999.33, c);
  
    d.receiveSpeedingTicket(3);
    assertEquals(3, d.getDemeritPoints());    
    assertEquals(785.73, d.getInsurance());
  }

  /**
   * Test clean record
   */
  public void testCleanRecord() {
    Car c = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 14999.33, c);

    d.receiveSpeedingTicket(2);
    assertEquals(2, d.getDemeritPoints());

    d.cleanRecord();
    assertEquals(0, d.getDemeritPoints());
    assertEquals(485.73, d.getInsurance());
  }
  
  /**
   * Test receiveParkingTicket
   */
  public void testPTicket() {
    Car c = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 14999.33, c);
  
    d.receiveParkingTicket(500);
    assertEquals(14499.33, d.getMoney());    
  }  

  /**
   * Test make money
   */
  public void testMakeMoney() {
    Car c = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 14999.33, c);
  
    d.makeMoney(1000.11);
    assertEquals(15999.44, d.getMoney());    
  } 

  /**
   * Test pay insurance
   */
  public void testPayInsurance() {
    Car c = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 14999.33, c);
  
    d.payInsurance();
    assertEquals(14513.6, d.getMoney());    
  } 

  /**
   * Test sell car
   */
  public void testSellCar() {
    Car c = new Car(2005, "Honda", "Civic", "red", 15000.0);
    Driver d = new Driver("John Doe", 35, 14999.33, c);
  
    d.sellCar();
    assertFalse(d.hasCar());
    assertEquals(26249.33, d.getMoney());    
    assertEquals(0.0, d.getInsurance());    
    assertEquals(1, Driver.getNumberOfUsedCars());    
  }
  
  /**
   * Test buy car
   */
  public void testBuyCar() {
    Car c = new Car(2005, "Honda", "Civic", "red", 10000.0);
    Driver d = new Driver("John Doe", 35, 14999.33);
  
    d.buyCar(c, "N3W C4R");
    assertTrue(d.hasCar());
    assertEquals(4999.33, d.getMoney());    
    assertEquals("N3W C4R", d.getCar().getLicensePlate());    
    assertEquals(c, d.getCar());    
    assertEquals(323.82, d.getInsurance());    
  }
  
  /**
   * Test car info
   */
  public void testCarInfo() {
    Car c = new Car(2005, "Honda", "Civic", "red", 10000.0);
    Driver d = new Driver("John Doe", 35, 14999.99, c);
  
    c.setLicensePlate("C001 C4R");
    assertEquals("2005 Honda Civic, red, License plate: C001 C4R", d.carInfo());    
  }

  /**
   * Test driver info
   */
  public void testDriverInfo() {
    Driver d = new Driver("John Doe", 35, 14999.99);  
    assertEquals("John Doe, 35 years old, $14999 in the bank", d.driverInfo());
  }

  /**
   * Test compare cars
   */
  public void testCompareCars(){
    Car c = new Car(2005, "Honda", "Civic", "red", 10000.0);
    Car c1 = new Car(2006, "BMW", "M3", "silver", 13000.0);
    Car c2 = new Car(2005, "Honda", "Civic", "red", 10000.0);

    assertFalse(Driver.compareCars(c, c1));   
    assertTrue (Driver.compareCars(c, c2));    
  }

  /**
   * Test used cars 1
   */
  public void testNumberOfUsedCars() {
    assertEquals(1, Driver.getNumberOfUsedCars());    
  }

  /**
   * Test used cars 2
   */
  public void testUsedCars() {
    Car c1 = new Car(2005, "Honda", "Civic", "blue", 15000.0);
    Car c2 = new Car(2007, "Mitsubishi", "Evo", "red", 20000.0);
    Driver d1 = new Driver("John Doe", 35, 250000, c1);
    Driver d2 = new Driver("Jack Jones", 25, 50000, c2);
    d1.sellCar();
    d1.buyCar(c2, "EVO");
    d2.sellCar();
    d2.buyCar(c1, "CIVIC");

    assertEquals(3, Driver.getNumberOfUsedCars());    
  }

  /**
   * Test bankers round
   */
  public void testBankersRound() {    
    assertEquals(3.51, Driver.bankersRound(3.513));    
    assertEquals(3.52, Driver.bankersRound(3.519));     
  }

  /**
   * Test bankers round2
   */
  public void testBankersRound2() {
    assertEquals(9.60, Driver.bankersRound(9.595));    
    assertEquals(9.59, Driver.bankersRound(9.585));    
    assertEquals(9.57, Driver.bankersRound(9.575));    
    assertEquals(9.56, Driver.bankersRound(9.565));    
    assertEquals(9.56, Driver.bankersRound(9.555));    
    assertEquals(9.54, Driver.bankersRound(9.545));    
    assertEquals(9.54, Driver.bankersRound(9.535));    
    assertEquals(9.52, Driver.bankersRound(9.525));    
    assertEquals(9.52, Driver.bankersRound(9.515)); 
    assertEquals(9.51, Driver.bankersRound(9.505)); 
  }
  
  /**
   * Test complex 1
   */
  public void test33() {
    Car c1 = new Car(2005, "Honda", "Civic", "blue", 15000.0);
    Car c2 = new Car(2007, "Mitsubishi", "Evo", "red", 20000.0);
    Driver d = new Driver("John Doe", 35, 5000.0, c1);

    d.makeMoney(3800.5);
    d.sellCar();
    assertTrue(d.canAfford(c2));
    d.buyCar(c2, "I've got a cooler car");
    assertEquals(50.5, d.getMoney());
    assertEquals("I've got a cooler car", d.getCar().getLicensePlate());
    assertEquals(4, Driver.getNumberOfUsedCars());    
  }

  /**
   * Test complex 2
   */
  public void test34() {
    Car c1 = new Car(2005, "Honda", "Civic", "blue", 15000.0);
    Driver d = new Driver("John Doe", 35, 2000.0, c1);

    d.payInsurance();
    d.receiveParkingTicket(500);
    d.receiveSpeedingTicket(8);
    d.growOlder();
    d.payInsurance();
    assertTrue(d.inDebt());

    d.sellCar();
    assertFalse(d.hasCar());
    assertEquals(10982.36, d.getMoney());
  }
  

  /**
   * Test complex 3
   */
  public void test35() {
    Car c1 = new Car(2005, "FORD", "Focus", "blue", 15000.0);
    Car c2 = new Car(2007, "BMW", "M5", "silver", 20000.0);
    Driver d = new Driver("John Doe", 35, 2000.0, c2, "Best Motor on Wheels");

    d.payInsurance();
    d.receiveParkingTicket(500);
    d.receiveSpeedingTicket(8);
    d.growOlder();
    d.payInsurance();
    assertTrue(d.inDebt());

    d.sellCar();
    assertFalse(d.hasCar());
    assertEquals(14409.81, d.getMoney());

    d.makeMoney(800.09);
    assertTrue(d.canAfford(c1));
    d.buyCar(c1, "Fix Or Repair Daily");
  }
}
