/**
 * license: GPLv3
 * lodge.reservationsystem
*/
package lodge.reservationsystem;

import java.time.LocalTime;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;

import lodge.data.Address;
import lodge.data.KitchenTypeEnum;
import lodge.reservation.Reservation;

public final class HotelReservation extends Reservation{

  public HotelReservation() {
    super();
    this.setType('H');
    this.setNumberOfBeds(2);
    this.setNumberOfBeds(2);
    this.setNumberOfBedRooms(1);
    this.setNumberOfBathRooms(1);
    this.setNumberOfFloors(1);
    this.setKitchen(KitchenTypeEnum.Kitchenette);
  }
  
  public static Reservation copy(String reservationType) {
    return new HotelReservation();    
  }

  public HotelReservation(final Address physical_address) {
    super();
    this.setType('H');
    this.setNumberOfBeds(2);
    this.setNumberOfBeds(2);
    this.setNumberOfBedRooms(1);
    this.setNumberOfBathRooms(1);
    this.setNumberOfFloors(1);
    this.setKitchen(KitchenTypeEnum.Kitchenette);
    this.setPhysical_address(
        new Address(physical_address.getStreet(), physical_address.getCity(), physical_address.getState(),
            physical_address.getZip()));
  }

  @Override
  public final String ReservationType() {
    return "HotelReservation";
  }

  @Override
  public boolean checkValid() throws IllegalArgumentException {
    if (getNumberOfBathRooms() != 1) {
      throw new IllegalArgumentException("not valid, Baths");
    }
    if (getNumberOfBedRooms() != 1) {
      throw new IllegalArgumentException("not valid, BedRooms");
    }
    if (getNumberOfBeds() != 2) {
      throw new IllegalArgumentException("not valid, Beds");
    }
    if (getPhysical_address() == null) {
      throw new IllegalArgumentException(String.format("not valid, physical_address %s", this.getReservation_number()));
    }
    if (getMailing_address() == null) {
      throw new IllegalArgumentException(String.format("not valid, mailing_address: %s", this.getReservation_number()));
    }
    return true;
  }

  @Override
  public float getPricePerNight() {
    return 0.0f;
  }

  // calculate and return the reservation's price
  // Hotel price plus additional flat fee of $50 plus $10 for kitchenette
  @Override
  public float calculatePrice() {
    ZonedDateTime enddt = getReservation_end_date().truncatedTo(ChronoUnit.DAYS);
    ZonedDateTime startdt = getReservation_start_date().truncatedTo(ChronoUnit.DAYS);
    long days = ChronoUnit.DAYS.between(startdt, enddt);

    ZonedDateTime checkOutTime = enddt.with(LocalTime.of(12, 0));
    if (getReservation_end_date().isBefore(checkOutTime)) {
      days = days - 1;
    }

    float calcprice = (getSquareFeet() > 900.0f) ? 120.0f + 15.0f : 120.0f;
    if (getKitchen() == KitchenTypeEnum.FullKitchen) {
      calcprice = calcprice + 10.0f;
    }
    calcprice = calcprice * days;
    calcprice = calcprice + 50.0f;
    return calcprice;
  }
}
