/** {@inheritDoc} */
  public void updateData(Event e) throws BusinessException {
    Event dbEntry = eventDAO.retrieve(e.getId());

    // Sets event data
    dbEntry.setEventData(e);
    notificationFacade.createNotificationForEventChange(e.getId());

    // Updates scheduling and checks weather forecasts
    updateScheduling(dbEntry, e.getStart(), e.getEnd());

    eventDAO.update(dbEntry);
  }
  public void cancel(int eventID) throws BusinessException {
    Event e = eventDAO.retrieve(eventID);

    e.cancel();

    notificationFacade.createNotificationForEventCancel(eventID);
  }
  private boolean updateScheduling(Event e, LocalDateTime start, LocalDateTime end)
      throws InvalidInputException, NotFoundException {
    boolean schedulingChanged = false;
    Event.validateScheduling(start, end);

    if (e.setScheduling(start, end)) {
      schedulingChanged = true;

      eventDAO.update(e);
      eventDAO.flush();

      updateWeatherForecastsAsync(e);
    }

    return schedulingChanged;
  }
  @Override
  public boolean isParticipant(int eventID, int userID) throws NotFoundException {
    Event e = eventDAO.findAndRefresh(eventID);

    if (e == null) throw new NotFoundException();

    return e.isParticipant(userID);
  }
  @Override
  public void addInvited(int eventID, int userID) throws BusinessException {
    Event e = eventDAO.retrieve(eventID);
    User u = userDAO.retrieve(userID);

    if (!e.addInvited(u)) {
      throw new BusinessException(InvalidInputException.USER_ALREADY_INVITED);
    }
  }
  @Override
  public void checkEventsSchedule() {
    List<Event> events = eventDAO.findPlanned();

    for (Event e : events) {
      if (e.getStart().isBefore(LocalDateTime.now())) {
        e.setStatus(EventStatus.CONCLUDED);
      }
    }
  }
  public void toggleParticipant(int eventID, int userID) throws BusinessException {
    Event e = eventDAO.retrieve(eventID);
    User u = userDAO.retrieve(userID);

    if (e.isParticipant(u)) {
      e.removeParticipant(u);
    } else {
      e.addParticipant(u);
    }
  }
  @Override
  public void addInvitedList(int eventID, String listInvited) throws BusinessException {
    List<String> usernames =
        RegExUtils.decomposeMultiple(
            listInvited, REXEX_PATTERN_INVITED_USER, REXEX_PATTERN_INVITED_USER_GROUP);

    Event e = eventDAO.retrieve(eventID);

    for (String username : usernames) {
      addInvited(e, username);
    }
  }
  public List<Event> mask(List<Event> events) {
    List<Event> result = new ArrayList<Event>();

    // Make sure the events are detached
    for (Event e : events) {
      eventDAO.detach(e);

      result.add(mask(e));
    }

    return result;
  }
  @Override
  public List<Event> search(String eventName) {
    List<Event> events = new ArrayList<Event>();

    // TODO implement properly
    Event found = eventDAO.findByName(eventName);
    if (found != null) {
      events.add(found);
    }

    return events;
  }
  public Event create(Event e, int userID) throws InvalidInputException, NotFoundException {
    User creator = userDAO.retrieve(userID);

    Event toSave = new Event(e);

    toSave.setCreator(creator);
    creator.getCreatedEvents().add(toSave);

    if (!toSave.validForSave()) {
      throw new InvalidInputException(InvalidInputException.EVENT_CREATION_INVALID);
    }

    eventDAO.save(toSave);
    return toSave;
  }
  @Override
  public List<WeatherForecastBase> askSuggestedChange(int eventID) throws NotFoundException {
    Event e = eventDAO.retrieve(eventID);

    if (!needsSuggestedScheduling(e)) {
      return null;
    }

    try {
      return weatherForecastFacade.askSuggestion(eventID);
    } catch (InvalidInputException ex) {
      Logger.getLogger(EventFacadeImplementation.class.getName()).log(Level.SEVERE, null, ex);
    }

    return null;
  }
  public Event create(Event e) throws BusinessException {
    User creator = userManager.getLoggedUser();
    Event savedEvent;

    if (creator == null) {
      throw new InvalidInputException(InvalidInputException.EVENT_CREATION_NO_LOGGED_USER);
    }

    try {
      savedEvent = create(e, creator.getId());
      eventDAO.flush();

      updateWeatherForecastsAsync(savedEvent);
    } catch (NotFoundException notFoundException) {
      throw new BusinessException(BusinessException.EVENT_CREATION_INTERNAL_PROCESSING);
    }

    return savedEvent;
  }
  /** {@inheritDoc} */
  public UserEventVisibility getVisibilityOverEvent(int userID, int eventID)
      throws NotFoundException {
    Event event = eventDAO.retrieve(eventID);
    User user = userDAO.retrieve(userID);

    if (event.getCreator().getId() == user.getId()) {
      return UserEventVisibility.CREATOR;
    }

    if (event.isInvited(user)) {
      return UserEventVisibility.VIEWER;
    }

    if (event.isPrivateEvent()) {
      return UserEventVisibility.NO_VISIBILITY;
    } else {
      return UserEventVisibility.VIEWER;
    }
  }
  public void addParticipant(int eventID, int userID) throws BusinessException {
    Event e = eventDAO.retrieve(eventID);
    User u = userDAO.retrieve(userID);

    e.addParticipant(u);
  }
 public Event find(int eventID) {
   return eventDAO.findAndRefresh(eventID);
 }
  @Override
  public void addInvited(int eventID, String username) throws BusinessException {
    Event e = eventDAO.retrieve(eventID);

    addInvited(e, username);
  }
  @Override
  public boolean isSuggestedChangeAvailable(int eventID) throws NotFoundException {
    Event e = eventDAO.retrieve(eventID);

    return isInSuggestedChangeRange(e) && e.isSuggestedChangeAvailable();
  }
 private List<Event> getPlannedEvents() {
   return eventDAO.findPlanned();
 }
  /** {@inheritDoc} */
  public boolean updateScheduling(int eventID, LocalDateTime start, LocalDateTime end)
      throws BusinessException {
    Event e = eventDAO.retrieve(eventID);

    return updateScheduling(e, start, end);
  }
  public void updateWeatherForecasts(int eventID) throws InvalidInputException, NotFoundException {
    Event e = eventDAO.retrieve(eventID);

    updateWeatherForecasts(e);
  }