package org.synyx.urlaubsverwaltung.application.application;

import org.synyx.urlaubsverwaltung.application.vacationtype.VacationCategory;
import org.synyx.urlaubsverwaltung.person.Person;

import java.time.Duration;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;

/**
 * This service provides access to the {@link Application} entities. Except for saving, the access is read-only.
 * Business interactions are found in
 * {@link ApplicationInteractionService}.
 */
public interface ApplicationService {

    /**
     * Gets an {@link Application} by its primary key.
     *
     * @param id to get the {@link Application} by.
     * @return optional {@link Application} for the given id
     */
    Optional<Application> getApplicationById(Integer id);

    /**
     * Saves a new {@link Application}.
     *
     * @param application to be saved
     * @return the saved {@link Application}
     */
    Application save(Application application);

    /**
     * Gets all {@link Application}s with vacation time between startDate x and endDate y for the given person.
     *
     * @param startDate {@link LocalDate}
     * @param endDate   {@link LocalDate}
     * @param person    {@link Person}
     * @return all {@link Application}s of the given person with vacation time between startDate x and endDate y
     */
    List<Application> getApplicationsForACertainPeriodAndPerson(LocalDate startDate, LocalDate endDate, Person person);

    /**
     * TODO
     *
     * @param startDate
     * @param endDate
     * @param person
     * @param statuses
     * @param vacationCategory
     * @return filteres {@link Application}s by status of the given person with vacation category between startDate x and endDate y
     */
    List<Application> getApplicationsForACertainPeriodAndPersonAndVacationCategory(LocalDate startDate, LocalDate endDate, Person person, List<ApplicationStatus> statuses, VacationCategory vacationCategory);

    /**
     * Gets all {@link Application}s with vacation time between startDate x and endDate y for the given state.
     *
     * @param startDate {@link LocalDate}
     * @param endDate   {@link LocalDate}
     * @param status    {@link ApplicationStatus}
     * @return all {@link Application}s with the given state and vacation time between startDate x and endDate y
     */
    List<Application> getApplicationsForACertainPeriodAndState(LocalDate startDate, LocalDate endDate, ApplicationStatus status);

    /**
     * Gets all {@link Application}s where the applicant for an upcoming application should be notified
     *
     * @param from     defines the start as {@link LocalDate} of a period that should be considered
     * @param to       defines the end as {@link LocalDate} of a period that should be considered
     * @param statuses {@link ApplicationStatus} that should be filtered for
     * @return all {@link Application}s where the given params match and
     */
    List<Application> getApplicationsWhereApplicantShouldBeNotifiedAboutUpcomingApplication(LocalDate from, LocalDate to, List<ApplicationStatus> statuses);

    /**
     * Gets all {@link Application}s where the replacement should be notified.
     *
     * @param from     defines the start as {@link LocalDate} of a period that should be considered
     * @param to       defines the end as {@link LocalDate} of a period that should be considered
     * @param statuses {@link ApplicationStatus} that should be filtered for
     * @return all {@link Application}s where the given params match and
     */
    List<Application> getApplicationsWhereHolidayReplacementShouldBeNotified(LocalDate from, LocalDate to, List<ApplicationStatus> statuses);

    /**
     * Gets all {@link Application}s with vacation time between startDate x and endDate y for the given person and
     * state.
     *
     * @param startDate {@link LocalDate}
     * @param endDate   {@link LocalDate}
     * @param person    {@link Person}
     * @param status    {@link ApplicationStatus}
     * @return all {@link Application}s of the given person with vacation time between startDate x and endDate y and
     * with a certain state
     */
    List<Application> getApplicationsForACertainPeriodAndPersonAndState(LocalDate startDate, LocalDate endDate, Person person, ApplicationStatus status);

    /**
     * Get all {@link Application} with specific states
     *
     * @return all {@link Application}
     */
    List<Application> getForStates(List<ApplicationStatus> statuses);

    /**
     * Get all {@link Application} with specific states since
     *
     * @return all {@link Application}
     */
    List<Application> getForStatesSince(List<ApplicationStatus> statuses, LocalDate since);

    /**
     * Get all {@link Application} with specific states and persons
     *
     * @return all {@link Application}
     */
    List<Application> getForStatesAndPerson(List<ApplicationStatus> statuses, List<Person> persons);

    /**
     * Get all {@link Application} with specific states and persons
     *
     * @return all {@link Application}
     */
    List<Application> getForStatesAndPersonSince(List<ApplicationStatus> statuses, List<Person> persons, LocalDate since);

    /**
     * Get all {@link Application}s with specific states and persons for the given date range
     *
     * @param statuses {@link ApplicationStatus} to filter
     * @param persons  {@link Person}s to consider
     * @param start    start date (inclusive)
     * @param end      end date (inclusive)
     * @return list of all matching {@link Application}s
     */
    List<Application> getForStatesAndPerson(List<ApplicationStatus> statuses, List<Person> persons, LocalDate start, LocalDate end);

    /**
     * Get the total hours of overtime reduction for a certain person.
     *
     * @param person to get the total hours of overtime reduction for
     * @return the total overtime reduction of a person, never {@code null}
     */
    Duration getTotalOvertimeReductionOfPerson(Person person);

    /**
     * Get a list of all active replacements of the given person and that are active at the given date
     * <p>
     * A active replacement is a replacement that will end after the given date
     *
     * @param holidayReplacement of the application
     * @param date               that will indicate when a replacement is active or not
     * @return List of applications where the given person is the active replacement
     */
    List<Application> getForHolidayReplacement(Person holidayReplacement, LocalDate date);
}

@@ -1485,12 +1485,133 @@
   * 
-TODO
+Gets all %7B@link Application%7Ds with vacation time between startDate x and endDate y for the given status and vacation category
 %0A   
@@ -1633,24 +1633,42 @@
 am startDate
+ %7B@link LocalDate%7D
 %0A     * @par
@@ -1677,16 +1677,34 @@
  endDate
+ %7B@link LocalDate%7D
 %0A     * 
@@ -1716,16 +1716,31 @@
 m person
+ %7B@link Person%7D
 %0A     * 
@@ -1758,39 +1758,146 @@
 uses
-%0A     * @param vacationCategory
+ %7B@link ApplicationStatus%7D that should be filtered for%0A     * @param vacationCategory %7B@link VacationCategory%7D that should be filtered for
 %0A   
@@ -1914,17 +1914,16 @@
 n filter
-e
 s %7B@link

Improve javadoc