/**
   * Lazy initialization of the assignment map. For each ambulance that is currently being displayed
   * (the current CRUD page, represented by the attribute entities), checks if there's an active
   * assignment and stores the appropriate information (driver name, or "unassigned", properly
   * internationalized) to the assignment map.
   */
  private void initCurrentAssignments() {
    logger.log(Level.INFO, "Initializing current drivers map for {0} entities.", entities.size());
    currentAssignments = new TreeMap<Long, String>();
    for (Ambulance ambulance : entities) {
      // Retrieves the current assignment (if any) for this ambulance.
      DriverAssignment assignment = null;
      try {
        assignment = getCrudService().retrieveActiveAssignment(ambulance);
      } catch (AmbulanceHasMultipleCurrentDriverAssignmentsException e) {
        logger.log(
            Level.SEVERE,
            "There has been an error while retrieving the active assignment of ambulance # "
                + ambulance.getNumber()
                + " (id "
                + ambulance.getId()
                + ")",
            e);
        addGlobalI18nMessage(
            "msgs",
            FacesMessage.SEVERITY_ERROR,
            "manageAmbulances.error.assignmentError",
            ambulance.getNumber());
      }

      // Displays the status depending if the ambulance is active or not.
      currentAssignments.put(
          ambulance.getId(),
          getI18nMessage(
              "msgs",
              (assignment == null)
                  ? "manageAmbulances.text.currentDriver.none"
                  : assignment.getDriver().getName()));
    }
  }
  /**
   * Called from a link in the ambulance table, selects an ambulance (through its id) and view the
   * current (active) assignment, if any. Redirects to the assignments page, which allows the
   * administrator to end the current assignment or change it, or even start a new one if the
   * ambulance is not currently assigned.
   *
   * <p>This method executes a scenario in the service class.
   *
   * @param id The id of the selected ambulance.
   * @return The path to the assignments page.
   */
  public String manageAssignments(Long id) {
    // Retrieve the selected ambulance.
    selectedEntity = getCrudService().retrieve(id);
    logger.log(
        Level.INFO,
        "Selected ambulance # {0} (id {1}). Opening assignments page.",
        new Object[] {selectedEntity.getNumber(), id});

    // Clear the assignment history (possibly of another ambulance).
    allAssignments = null;

    // Retireve the current assignment (if any) for this ambulance.
    try {
      currentAssignment = getCrudService().retrieveActiveAssignment(selectedEntity);
    } catch (AmbulanceHasMultipleCurrentDriverAssignmentsException e) {
      logger.log(
          Level.SEVERE,
          "There has been an error while retrieving the active assignment of ambulance # "
              + selectedEntity.getNumber()
              + " (id "
              + selectedEntity.getId()
              + ")",
          e);
      addGlobalI18nMessage(
          "msgs",
          FacesMessage.SEVERITY_ERROR,
          "manageAmbulances.error.assignmentError",
          selectedEntity.getNumber());
      return null;
    }

    // If there is no current assignment for the ambulance, create a new one for the new assignment
    // form.
    free = currentAssignment == null;
    if (free) {
      currentAssignment = new DriverAssignment();
      currentAssignment.setBeginDate(new Date(System.currentTimeMillis()));
    }

    return ASSIGNMENTS_PAGE;
  }
  /**
   * Called from the assignment page's form, sends the data on the end of the current assignment
   * and/or the beginning of a new one and changes the driver assigned to the ambulance.
   *
   * <p>This method executes a scenario in the service class.
   */
  public void changeAssignment() {
    // Only change an assignment if the driver actually changed.
    if ((driverId != null)
        && (currentAssignment.getDriver() != null)
        && (driverId.equals(currentAssignment.getDriver().getId()))) {
      logger.log(
          Level.WARNING,
          "Assigning ambulance # {0} (id {1}) with the same driver. Current assignment's driver's ID: {3}, supplied ID: {4}.",
          new Object[] {
            selectedEntity.getNumber(),
            selectedEntity.getId(),
            currentAssignment.getDriver().getId(),
            driverId
          });
      addGlobalI18nMessage(
          "msgs",
          FacesMessage.SEVERITY_WARN,
          "manageAmbulances.warn.sameDriverAssignment",
          currentAssignment.getDriver().getName());
    } else {
      Employee driver = (driverId == null) ? null : employeeDAO.retrieveById(driverId);

      try {
        // If the driver was specified, create a new assignment, possibly ending a current
        // assignment.
        if (driver != null) {
          logger.log(
              Level.INFO,
              "Assigning ambulance # {0} (id {1}). Driver: {2}.",
              new Object[] {selectedEntity.getNumber(), selectedEntity.getId(), driver.getName()});
          currentAssignment = getCrudService().assignAmbulance(selectedEntity, driver);
          free = false;
          addGlobalI18nMessage(
              "msgs", FacesMessage.SEVERITY_INFO, "manageAmbulances.info.assignmentStarted");
        }
        // If not, end the current assignment.
        else {
          logger.log(
              Level.INFO,
              "Ending current assignment for ambulance # {0} (id {1}).",
              new Object[] {selectedEntity.getNumber(), selectedEntity.getId()});
          getCrudService().endCurrentAssignment(selectedEntity);
          currentAssignment = null;
          free = true;
          addGlobalI18nMessage(
              "msgs", FacesMessage.SEVERITY_INFO, "manageAmbulances.info.assignmentEnded");
        }
      } catch (AmbulanceHasMultipleCurrentDriverAssignmentsException e) {
        logger.log(
            Level.SEVERE,
            "There has been an error while assigning a driver to ambulance # "
                + selectedEntity.getNumber()
                + " (id "
                + selectedEntity.getId()
                + ")",
            e);
        addGlobalI18nMessage(
            "msgs",
            FacesMessage.SEVERITY_ERROR,
            "manageAmbulances.error.assignmentError",
            selectedEntity.getNumber());
        driverId = null;
      } catch (AmbulanceHasNoCurrentDriverAssignmentsException e) {
        logger.log(
            Level.SEVERE,
            "There has been an error while assigning a driver to ambulance # "
                + selectedEntity.getNumber()
                + " (id "
                + selectedEntity.getId()
                + ")",
            e);
        addGlobalI18nMessage(
            "msgs",
            FacesMessage.SEVERITY_ERROR,
            "manageAmbulances.error.assignmentError",
            selectedEntity.getNumber());
        driverId = null;
      } catch (EmployeeIsNotDriverException e) {
        logger.log(
            Level.SEVERE,
            "There has been an error while assigning a driver to ambulance # "
                + selectedEntity.getNumber()
                + " (id "
                + selectedEntity.getId()
                + "): the specified employee ("
                + driver.getLogin()
                + ") is not a driver!",
            e);
        addGlobalI18nMessage(
            "msgs",
            FacesMessage.SEVERITY_ERROR,
            "manageAmbulances.error.assignmentErrorNotDriver",
            driver.getName(),
            selectedEntity.getNumber());
        driverId = null;
      }
    }
  }