/** {@inheritDoc} */
 @Override
 public void close() {
   try {
     if (selectAll != null) selectAll.close();
     if (selectAllRoomEnd != null) selectAllRoomEnd.close();
     if (selectAllRoomStart != null) selectAllRoomStart.close();
     if (selectId != null) selectId.close();
     if (selectTwoRooms != null) selectTwoRooms.close();
   } catch (SQLException e) {
     Log.error(e);
   }
 }
  /**
   * Gives each lesson a staff member and classroom on a per subject basis, taking into account the
   * distances between each lesson for each member of staff.
   *
   * @return Nothing.
   */
  @Override
  public Void call() {
    // get all subjects
    List<Subject> subjects;
    List<Distance> distances;
    StringBuilder failedLog = new StringBuilder();

    try {
      subjects = daoManager.getSubjectDao().getAll();
    } catch (DataAccessException e) {
      updateMessage(
          "Failed to access subject data due to the error ["
              + e
              + "]\n"
              + "Please restart the timetabler and send the logs to your system administrator if this occurs again.");
      return null;
    } catch (DataConnectionException e) {
      DataExceptionHandler.handleJavaFx(e, null, true);
      return null;
    }
    try {
      distances = daoManager.getDistanceDao().getAll();
    } catch (DataAccessException e) {
      updateMessage(
          "Failed to access distance data due to the error ["
              + e
              + "]\n"
              + "Please restart the timetabler and send the logs to your system administrator if this occurs again.");
      return null;
    } catch (DataConnectionException e) {
      DataExceptionHandler.handleJavaFx(e, null, true);
      return null;
    }

    try {
      subjects.forEach(
          subject -> {
            updateMessage("Timetabling [" + subject.name + ']');
            // for current subject find periods where multiple classes are taught during the same
            // period for this subject
            // The id of the top list is the id of the period as it is static data
            List<Set<LessonPlan>> overloadedPeriod;
            overloadedPeriod = findOverloadedPeriods(subject, 31);
            Log.verbose("Found [" + overloadedPeriod.size() + "] overloaded periods");

            List<LessonPlan> lessonPlans = null;
            List<Staff> staff = null;
            List<Classroom> classrooms = null;

            try {
              // get all lessonPlans for this subject
              lessonPlans = daoManager.getLessonPlanDao().getAllBySubject(subject);
            } catch (DataAccessException e) {
              failedLog
                  .append("Could not access the lesson data!\nThe error was [")
                  .append(e)
                  .append(
                      "]\nPlease restart the timetabler and send the logs to your system administrator")
                  .append(" if this occurs again.");
              Log.error(e);
              throw new LambdaBreakException();
            } catch (DataConnectionException e) {
              DataExceptionHandler.handleJavaFx(e, null, true);
              throw new LambdaBreakException();
            }

            try {
              // get all staff who teach the subject
              staff = daoManager.getStaffDao().getAllBySubject(subject);
            } catch (DataAccessException e) {
              failedLog
                  .append("Could not access the staff data!\nThe error was [")
                  .append(e)
                  .append(
                      "]\nPlease restart the timetabler and send the logs to your system administrator")
                  .append(" if this occurs again.");
              Log.error(e);
              throw new LambdaBreakException();
            } catch (DataConnectionException e) {
              DataExceptionHandler.handleJavaFx(e, null, true);
              throw new LambdaBreakException();
            }

            try {
              classrooms = daoManager.getClassroomDao().getAll();
            } catch (DataConnectionException e) {
              failedLog
                  .append("Could not access the classroom data!\nThe error was [")
                  .append(e)
                  .append(
                      "]\nPlease restart the timetabler and send the logs to your system administrator")
                  .append(" if this occurs again.");
              Log.error(e);
              throw new LambdaBreakException();
            } catch (DataAccessException e) {
              DataExceptionHandler.handleJavaFx(e, null, true);
              throw new LambdaBreakException();
            }

            Log.verbose(
                "Found ["
                    + classrooms.size()
                    + "] classrooms and ["
                    + lessonPlans.size()
                    + "] lessons and ["
                    + staff.size()
                    + "] staff");

            // put staff into lessonPlans for this subject, avoiding teacher being scheduled twice
            // for same period.
            putStaffIntoLessonPlan(lessonPlans, staff, overloadedPeriod);

            // Get the data needed for the final part of timetabling
            List<Distance> subjectDistance =
                distances
                    .parallelStream()
                    .filter(distance -> distance.startRoom.subject.equals(subject))
                    .collect(Collectors.toList());
            List<Classroom> subjectRooms =
                classrooms
                    .parallelStream()
                    .filter(classroom -> classroom.subject.equals(subject))
                    .collect(Collectors.toList());
            // Put classrooms into lessonPlans for this subject.
            // putLessonPlansIntoClassrooms(lessonPlans, subjectRooms, subjectDistance);
            lessonPlans.forEach(
                lessonPlan -> {
                  try {
                    daoManager.getLessonPlanDao().update(lessonPlan);
                  } catch (DataAccessException | DataUpdateException e) {
                    failedLog
                        .append("Could not update the lesson data!\nThe error was [")
                        .append(e)
                        .append(
                            "]\nPlease restart the timetabler and send the logs to your system administrator")
                        .append(" if this occurs again.");
                    Log.error(e);
                    throw new LambdaBreakException();
                  } catch (DataConnectionException e) {
                    DataExceptionHandler.handleJavaFx(e, null, true);
                    throw new LambdaBreakException();
                  }
                });
          });
    } catch (LambdaBreakException e) {
      if (failedLog.length() > 0) {
        updateMessage(failedLog.toString());
      }
      return null;
    }

    updateMessage("Done");
    return null;
  }