package encapsulation;

class Vehicle {

	private final char type;
	private final char fuel;
	private String registrationNumber;

	Vehicle(char type, char fuel, String registrationNumber) {
		this.type = type;
		this.fuel = fuel;
		this.setRegistrationNumber(registrationNumber);
	}

	public char getVehicleType() {
		return this.type;
	}

	public char getFuelType() {
		return this.fuel;
	}

	public String getRegistrationNumber() {
		return this.registrationNumber;
	}

	public void setRegistrationNumber(String registrationNumber) {
		if (!checkRegistrationNumber(registrationNumber))
			throw new IllegalArgumentException("Could not parse registration number.");

		if (!checkFuelType(this.fuel, registrationNumber))
			throw new IllegalArgumentException("This registration number is not valid for a vehicle with this type of fuel. The fuel type has to be given in upper case.");

		if (!checkVehicleType(this.type, registrationNumber))
			throw new IllegalArgumentException("This registration number is not valid for a vehicle of this type.");

		this.registrationNumber = registrationNumber;
	}

	/**
	 * Test whether or not the registration number is syntactically valid.
	 *
	 * @return Whether or not the test was passed
	 */
	private static boolean checkRegistrationNumber(String registrationNumber) {
		return registrationNumber.matches("[A-Z]{2}\\d{4,5}");
	}

	/**
	 * Test whether or not the registration number is valid based on the fuel type.
	 *
	 * @return Whether or not the test was passed
	 */
	private static boolean checkFuelType(char fuel, String registrationNumber) {
		switch(fuel) {
			case 'H':
				return registrationNumber.matches("HY\\d+");
			case 'E':
				return registrationNumber.matches("(?:EL|EK)\\d+");
      case 'D':
      case 'G':
				return registrationNumber.matches("(?!EL|EK|HY)[A-Z]{2}\\d+");
			default:
        return false;
    }
	}

	/**
	 * Test whether or not the registration number is valid based on the vehicle type.
	 *
	 * @return Whether or not the test was passed
	 */
	private static boolean checkVehicleType(char type, String registrationNumber) {
		switch(type) {
		  case 'C':
				return registrationNumber.matches("[A-Z]{2}\\d{5}");
		  case 'M':
				return registrationNumber.matches("(?!HY)[A-Z]{2}\\d{4}");
		  default:
				return false;
		}
	}
}
