package de.accso.flexinale.infrastructure;

import de.accso.flexinale.application.Config;
import de.accso.flexinale.application.services.FilmUploadService;
import de.accso.flexinale.application.services.KinoUploadService;
import de.accso.flexinale.application.services.KinoSaalUploadService;
import de.accso.flexinale.application.services.VorfuehrungUploadService;
import de.accso.flexinale.domain.dao.*;
import de.accso.flexinale.domain.services.FilmService;
import de.accso.flexinale.domain.services.KinoService;
import de.accso.flexinale.domain.services.TicketService;
import de.accso.flexinale.domain.services.VorfuehrungService;
import de.accso.flexinale.infrastructure.persistence.*;
import de.accso.flexinale.infrastructure.security.BenutzerDao;
import de.accso.flexinale.infrastructure.security.BenutzerJpaRepository;
import de.accso.flexinale.infrastructure.security.BenutzerJpaRepositoryDelegate;
import de.accso.flexinale.infrastructure.security.services.BenutzerUploadService;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableJpaRepositories({"de.accso.flexinale.infrastructure.persistence",
                        "de.accso.flexinale.infrastructure.security"})
@EnableTransactionManagement
@EntityScan(basePackages={"de.accso.flexinale.infrastructure.persistence",
                          "de.accso.flexinale.infrastructure.security"})
public class FlexinaleSpringFactory {

    @Bean
    public FilmService createFilmService(final FilmDao filmDao,
                                         final TicketDao ticketDao,
                                         final VorfuehrungDao vorfuehrungDao,
                                         final Config config) {
        return new FilmService(filmDao, vorfuehrungDao, ticketDao, config.getMinZeitZwischenVorfuehrungenInMinuten());
    }

    @Bean
    public FilmUploadService createFilmUploadService(final FilmDao filmDao) {
        return new FilmUploadService(filmDao);
    }

    @Bean
    public de.accso.flexinale.application.services.FilmService createApplicationFilmService(final FilmService filmService){
        return new de.accso.flexinale.application.services.FilmService(filmService);
    }

    @Bean
    public FilmDao createFilmDao(final FilmJpaRepository filmJpaRepository) {
        return new FilmJpaRepositoryDelegate(filmJpaRepository);
    }

    // ------------------------------------------------------------------------------------------------

    @Bean
    public KinoService createKinoService(final KinoDao KinoDao) {
        return new KinoService(KinoDao);
    }

    @Bean
    public de.accso.flexinale.application.services.KinoService createApplicationKinoService(final KinoService kinoService){
        return new de.accso.flexinale.application.services.KinoService(kinoService);
    }

    @Bean
    public KinoUploadService createKinoUploadService(final KinoDao kinoDao) {
        return new KinoUploadService(kinoDao);
    }

    @Bean
    public KinoSaalUploadService createKinoSaalUploadService(final KinoSaalDao kinoSaalDao) {
        return new KinoSaalUploadService(kinoSaalDao);
    }

    @Bean
    public KinoDao createKinoDao(final KinoJpaRepository kinoJpaRepository) {
        return new KinoJpaRepositoryDelegate(kinoJpaRepository);
    }

    @Bean
    public KinoSaalDao createKinoSaalDao(final KinoSaalJpaRepository kinoSaalJpaRepository) {
        return new KinoSaalJpaRepositoryDelegate(kinoSaalJpaRepository);
    }

    // ------------------------------------------------------------------------------------------------

    @Bean
    public VorfuehrungService createVorfuehrungService(final VorfuehrungDao vorfuehrungDao) {
        return new VorfuehrungService(vorfuehrungDao);
    }

    @Bean
    public de.accso.flexinale.application.services.VorfuehrungService createApplicationVorfuehrungService(final VorfuehrungService vorfuehrungService){
        return new de.accso.flexinale.application.services.VorfuehrungService(vorfuehrungService);
    }

    @Bean
    public VorfuehrungUploadService createVorfuehrungUploadService(final VorfuehrungDao vorfuehrungDao,
                                                                   final KinoSaalDao kinoSaalDao,
                                                                   final Config config) {
        return new VorfuehrungUploadService(vorfuehrungDao, kinoSaalDao, config);
    }

    @Bean
    public VorfuehrungDao createVorfuehrungDao(final VorfuehrungJpaRepository vorfuehrungJpaRepository) {
        return new VorfuehrungJpaRepositoryDelegate(vorfuehrungJpaRepository);
    }

    // ------------------------------------------------------------------------------------------------

    @Bean
    public KontingentDao createKontingentDao(final KontingentJpaRepository kontingentJpaRepository) {
        return new KontingentJpaRepositoryDelegate(kontingentJpaRepository);
    }

    // ------------------------------------------------------------------------------------------------

    @Bean
    public TicketService createTicketService(final TicketDao ticketDao,
                                             final VorfuehrungDao vorfuehrungDao,
                                             final KontingentDao kontingentDao) {
        return new TicketService(ticketDao, vorfuehrungDao, kontingentDao);
    }

    @Bean
    public de.accso.flexinale.application.services.TicketService createApplicationTicketService(final TicketService ticketService){
        return new de.accso.flexinale.application.services.TicketService(ticketService);
    }

    @Bean
    public TicketDao createTicketDao(final TicketJpaRepository ticketJpaRepository) {
        return new TicketJpaRepositoryDelegate(ticketJpaRepository);
    }

    // ------------------------------------------------------------------------------------------------

    @Bean
    public BenutzerUploadService createBesucherUploadService(final BenutzerDao benutzerDao) {
        return new BenutzerUploadService(benutzerDao);
    }

    @Bean
    public BenutzerDao createBesucherDao(final BenutzerJpaRepository benutzerJpaRepository) {
        return new BenutzerJpaRepositoryDelegate(benutzerJpaRepository);
    }
}
