// Calculate How many time
  public List<TestingCenterTimeSlots> generateTimeSlots(Exam exam) {
    TestingCenterInfo tci = tcr.findByTerm(tcr.getCurrentTerm().getTermId());
    int gap = tci.getGap();
    int examDuration = exam.getDuration();
    int openMinutes = (int) ChronoUnit.MINUTES.between(tci.getOpen(), tci.getClose());

    // Ensure time chunk devides 30
    int timeChuck =
        (examDuration + gap) % 30 == 0 ? examDuration : 30 * ((examDuration + gap) / 30 + 1);

    LocalTime endTime = exam.getEndDateTime().toLocalTime();
    LocalTime beginTime = exam.getStartDateTime().toLocalTime();
    LocalTime openTime = tci.getOpen();
    LocalTime closeTime = tci.getClose();
    LocalDate beginDate = exam.getStartDateTime().toLocalDate();
    LocalDate endDate = exam.getEndDateTime().toLocalDate();

    beginTime = adjustTime(beginTime); // Exam Begin Time
    endTime = adjustTime(endTime); // Exam End Time

    // Calculate Duration According to different day.
    int startDayDuration = (int) ChronoUnit.MINUTES.between(beginTime, closeTime);
    int dayLast = (int) ChronoUnit.DAYS.between(beginDate, endDate) - 1;
    int endDayDuration = (int) ChronoUnit.MINUTES.between(openTime, endTime);

    int startDayChucks = startDayDuration / timeChuck;
    int endDayChucks = endDayDuration / timeChuck;
    int regularDayChuncks = dayLast >= 0 ? (dayLast * openMinutes) / timeChuck : 0;
    int dailyChuncks = openMinutes / timeChuck;

    LocalDate dateCursor = beginDate;
    LocalTime timeCursor = beginTime;
    List<TestingCenterTimeSlots> timeSlotses = new ArrayList<>();
    if (startDayChucks > 0) {
      for (int i = 0; i < startDayChucks; i++) {
        LocalDateTime slotsBegin = dateCursor.atTime(timeCursor);
        LocalDateTime slotsEnd = dateCursor.atTime(timeCursor.plusMinutes(examDuration));

        TestingCenterTimeSlots t =
            new TestingCenterTimeSlots(
                exam.getExamId(),
                slotsBegin,
                slotsEnd,
                tci.getNumSeats(),
                tci.getNumSetAsideSeats());
        timeSlotses.add(t);

        timeCursor = timeCursor.plusMinutes(timeChuck);
      }
    }
    if (regularDayChuncks > 0) {

      for (int i = 0; i < dayLast; i++) {
        dateCursor = dateCursor.plusDays(1);
        timeCursor = adjustTime(openTime);

        for (int j = 0; j < dailyChuncks; j++) {
          LocalDateTime slotsBegin = dateCursor.atTime(timeCursor);
          LocalDateTime slotsEnd = dateCursor.atTime(timeCursor.plusMinutes(examDuration));

          TestingCenterTimeSlots t =
              new TestingCenterTimeSlots(
                  exam.getExamId(),
                  slotsBegin,
                  slotsEnd,
                  tci.getNumSeats(),
                  tci.getNumSetAsideSeats());
          timeSlotses.add(t);

          timeCursor = timeCursor.plusMinutes(timeChuck);
        }
      }
    }
    if (endDayChucks > 0) {
      dateCursor = dateCursor.plusDays(1);
      timeCursor = adjustTime(openTime);

      for (int i = 0; i < endDayChucks; i++) {
        LocalDateTime slotsBegin = dateCursor.atTime(timeCursor);
        LocalDateTime slotsEnd = dateCursor.atTime(timeCursor.plusMinutes(examDuration));

        TestingCenterTimeSlots t =
            new TestingCenterTimeSlots(
                exam.getExamId(),
                slotsBegin,
                slotsEnd,
                tci.getNumSeats(),
                tci.getNumSetAsideSeats());
        timeSlotses.add(t);

        timeCursor = timeCursor.plusMinutes(timeChuck);
      }
    }
    return timeSlotses;
  }