package org.springframework.prospring.ticket.service;

import org.springframework.prospring.ticket.domain.*;
import org.springframework.prospring.ticket.domain.support.*;
import org.springframework.prospring.ticket.service.payment.*;

/**
 * Reprezentuje cały system kasowy. Zapewnia usługi o następujących możliwościach:<br/>
 *
 * - wyszukiwanie dostępnych miejsc<br/>
 * - dokonywanie rezerwacji<br/>
 * - zarządzanie płatnościami<br/>
 * - inne usługi związane z procesem rezerwacji.
 */
public interface BoxOffice {

    /**
     * Zwraca listę spektakli danego przedstawienia wraz z informacjami o dostępnych miejscach.
     * @param show Przedstawienie.
     * @return Lista spektakli wraz z informacjami o dostępnych miejscach.
     */
    public PerformanceWithAvailability[] getAvailabilityForPerformances(Show show);

    /**
     * Przydziela miejsca dla spektaklu. Rezerwacja o określonych danych szczegółowych jest tworzona
     * na podstawie podanego żądania rezerwacji. Rezerwacja jest tworzona dla użytkownika na pewien okres 
     * czasu, by pozwolić użytkownikowi na dokończenie procesu płatności.
     *
     * @param request Żądanie rezerwacji.
     * @return Nowa rezerwacja.
     * @throws RequestedSeatNotAvailableException Zgłaszany gdy żądane miejsca nie są dostępne.
     * @throws NotEnoughSeatsException Zgłaszany gdy nie ma tylu miejsc ilu zażądał użytkownik.
     */
    public Reservation allocateSeats(ReservationRequest request)
            throws RequestedSeatNotAvailableException, NotEnoughSeatsException;

    /**
     * Realizuje zamówienie biletów na podstawie żądania zakupu.
     *
     * @param purchaseRequest Żądanie zakupu.
     * @return Pomyślnie przeprowadzone zamówienie.
     * @throws PaymentException Zgłaszany gdy podczas realizacji płatności pojawiły się jakiekolwiek błędy.
     * @throws RequestedSeatNotAvailableException Zgłaszany gdy podczas zamawiania, którekolwiek z żądanych miejsc
     * nie było już dostępne.
     */
    public Purchase purchaseTickets(PurchaseRequest purchaseRequest)
        throws PaymentException, CreditCardValidationException, RequestedSeatNotAvailableException;

    /**
     * Sprawdza czy miejsca skojarzone z podanymi szczegółami rezerwacji wciąż są dostępne.
     * @param booking Szczegóły rezerwacji.
     * @return True jeśli miejsca wciąż są dostępne, false w przeciwnym przypadku.
     */
    public boolean areSeatsStillAvailable(Booking booking);

    /**
     * Zwraca dostępne miejsca podanej kategorii na podany spektak.
     * @param performance Spektakl.
     * @param seatClass Kategoria miejsc.
     * @return Dostępne miejsca podanej klasy na wskazny spektakl.
     */
    public Seat[] getAvailableSeats(Performance performance, SeatClass seatClass);

    /**
     * Zwraca ilość dostępnych miejsc podanej klasy na podany spektakl.
     * @param performance Spektakl.
     * @param seatClass Kategoria miejsc.
     * @return Ilość miejsc podanej kategorii na wskazny spektakl.
     */
    public int getAvailableSeatsCount(Performance performance, SeatClass seatClass);

    /**
     * Zwraca grupę cenową skojarzoną z podanym identyfikatorem.
     * @param priceBandId Identyfikator grupy cenowej.
     * @return Grupa cenowa o podanym identyfikatorze.
     */
    public PriceBand getPriceBand(long priceBandId);

    /**
     * Anuluje rezerwację.
     * @param booking Rezerwacja jaką należy anulować.
     */
    public void cancelBooking(Booking booking);

    /**
     * Zwraca rezerwację o podanym identyfikatorze.
     * @param bookingId Identyfikator rezerwacji.
     * @return Rezerwacja o podanym identyfikatorze.
     */
    public Booking getBooking(long bookingId);

    /**
     * Zwraca zarezerwowane miejsca skojarzone z daną rezerwacją.
     * @param booking Szczegółowe dane rezerwacji.
     * @return Zarezerwowane miejsca.
     */
    public Seat[] getBookedSeats(Booking booking);

    /**
     * Zwraca spektakl skojarzony z daną rezerwacją.
     * @param booking Szczegółowe dane rezerwacji.
     * @return Skojarzony spektakl.
     */
    public Performance getPerformanceOfBooking(Booking booking);
}