package ru.yandex.canvas.configs;

import java.util.concurrent.Executor;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.Validator;
import org.springframework.web.servlet.HandlerExceptionResolver;

import ru.yandex.canvas.controllers.CreativesBatchesController;
import ru.yandex.canvas.controllers.CreativesController;
import ru.yandex.canvas.controllers.DirectController;
import ru.yandex.canvas.controllers.DisclaimersController;
import ru.yandex.canvas.controllers.FilesController;
import ru.yandex.canvas.controllers.InBannerPreviewController;
import ru.yandex.canvas.controllers.PresetsController;
import ru.yandex.canvas.controllers.RootController;
import ru.yandex.canvas.controllers.RtbHostController;
import ru.yandex.canvas.controllers.StockController;
import ru.yandex.canvas.controllers.TurboFilesController;
import ru.yandex.canvas.controllers.UserFilesController;
import ru.yandex.canvas.controllers.UserTurboFilesController;
import ru.yandex.canvas.controllers.UsersController;
import ru.yandex.canvas.controllers.html5.Html5BatchesController;
import ru.yandex.canvas.controllers.html5.Html5CreativeController;
import ru.yandex.canvas.controllers.html5.Html5DirectController;
import ru.yandex.canvas.controllers.html5.SourceController;
import ru.yandex.canvas.controllers.video.DiagnosticsController;
import ru.yandex.canvas.controllers.video.PythonRedirect;
import ru.yandex.canvas.controllers.video.StockVideoController;
import ru.yandex.canvas.controllers.video.VideoAdditionCreatorService;
import ru.yandex.canvas.controllers.video.VideoAdditionsController;
import ru.yandex.canvas.controllers.video.VideoAdditionsSurveyController;
import ru.yandex.canvas.controllers.video.VideoCreativesController;
import ru.yandex.canvas.controllers.video.VideoDirectController;
import ru.yandex.canvas.controllers.video.VideoFilesController;
import ru.yandex.canvas.controllers.video.VideoFilesModifyingController;
import ru.yandex.canvas.controllers.video.VideoMotionController;
import ru.yandex.canvas.controllers.video.VideoPresetsController;
import ru.yandex.canvas.controllers.video.VideoStockFilesSearchController;
import ru.yandex.canvas.model.html_builder.InBannerHtmlCreativeWriter;
import ru.yandex.canvas.model.validation.Html5SizeValidator;
import ru.yandex.canvas.repository.html5.BatchesRepository;
import ru.yandex.canvas.repository.video.VideoFilesRepository;
import ru.yandex.canvas.service.AuthService;
import ru.yandex.canvas.service.CreativesService;
import ru.yandex.canvas.service.DirectService;
import ru.yandex.canvas.service.DisclaimersService;
import ru.yandex.canvas.service.FileService;
import ru.yandex.canvas.service.MigrationService;
import ru.yandex.canvas.service.MongoMonitorService;
import ru.yandex.canvas.service.PresetsService;
import ru.yandex.canvas.service.ScreenshooterService;
import ru.yandex.canvas.service.SessionParams;
import ru.yandex.canvas.service.StillageService;
import ru.yandex.canvas.service.StockService;
import ru.yandex.canvas.service.UserFileService;
import ru.yandex.canvas.service.UserStockService;
import ru.yandex.canvas.service.direct.CreativeUploadHelperFacade;
import ru.yandex.canvas.service.direct.VideoAdditionDirectUploadHelper;
import ru.yandex.canvas.service.html5.Html5BatchesService;
import ru.yandex.canvas.service.html5.Html5CreativesService;
import ru.yandex.canvas.service.html5.Html5SourcesService;
import ru.yandex.canvas.service.idea.IdeasService;
import ru.yandex.canvas.service.rtbhost.helpers.VideoMotionService;
import ru.yandex.canvas.service.screenshooters.CreativesScreenshooterHelperService;
import ru.yandex.canvas.service.screenshooters.Html5ScreenshooterHelperService;
import ru.yandex.canvas.service.screenshooters.VideoAdditionScreenshooterHelperService;
import ru.yandex.canvas.service.video.AudioService;
import ru.yandex.canvas.service.video.AudioServiceInterface;
import ru.yandex.canvas.service.video.CreativesGenerationService;
import ru.yandex.canvas.service.video.InBannerVideoFilesService;
import ru.yandex.canvas.service.video.MovieServiceInterface;
import ru.yandex.canvas.service.video.PackshotServiceInterface;
import ru.yandex.canvas.service.video.StaticPreviewService;
import ru.yandex.canvas.service.video.VideoAdditionValidationService;
import ru.yandex.canvas.service.video.VideoAdditionsService;
import ru.yandex.canvas.service.video.VideoCreativesService;
import ru.yandex.canvas.service.video.VideoLimitsService;
import ru.yandex.canvas.service.video.VideoPresetsService;
import ru.yandex.canvas.service.video.VideoPreviewUrlBuilder;
import ru.yandex.canvas.service.video.VideoSoundTrackService;
import ru.yandex.canvas.service.video.files.StockMoviesService;
import ru.yandex.canvas.service.video.files.VideoCategoriesService;

/**
 * @author skirsanov
 */
@Configuration
public class WebConfig {

    @Bean
    public FilesController filesController(FileService fileService,
                                           StockService stockService,
                                           IdeasService ideasService,
                                           @Value("${FILE_API_INTERNAL_TOKEN}") String fileApiInternalToken,
                                           SessionParams sessionParams) {
        return new FilesController(fileService, stockService, ideasService, fileApiInternalToken, sessionParams);
    }

    @Bean
    public UserFilesController userFilesController(
            UserFileService userFileService,
            UserStockService userStockService, AuthService authService
    ) {
        return new UserFilesController(userFileService, userStockService, authService);
    }

    @Bean
    public TurboFilesController turboFilesController(FileService fileService) {
        return new TurboFilesController(fileService);
    }

    @Bean
    public UserTurboFilesController userTurboFilesController(UserFileService userFileService, AuthService authService) {
        return new UserTurboFilesController(userFileService, authService);
    }

    @Bean
    public ErrorAttributes errorAttributes() {
        return new MessageOverridingErrorAttributes();
    }

    @Bean
    public HandlerExceptionResolver exceptionResolver() {
        return new MessageAwareResponseStatusExceptionResolver();
    }

    @Bean
    public CreativesController creativesController(CreativesService creativesService,
                                                   AuthService authService, ScreenshooterService screenshooterService,
                                                   CreativesScreenshooterHelperService screenshooterHelperService) {
        return new CreativesController(creativesService, authService, screenshooterService, screenshooterHelperService);
    }

    @Bean
    public CreativesBatchesController creativesBatchesController(CreativesService creativesService,
                                                                 MigrationService migrationService,
                                                                 SessionParams sessionParams,
                                                                 PresetsService presetsService,
                                                                 AuthService authService) {
        return new CreativesBatchesController(creativesService, migrationService, sessionParams, presetsService,
                authService);
    }

    @Bean
    public RootController rootController(MongoMonitorService mongoMonitorService, AuthService authService) {
        return new RootController(mongoMonitorService, authService);
    }

    @Bean
    public PresetsController presetsController(PresetsService presetsService,
                                               SessionParams sessionParams, AuthService authService) {
        return new PresetsController(presetsService, sessionParams, authService);
    }

    @Bean
    public DisclaimersController disclaimersController(DisclaimersService disclaimersService, DirectService directService, SessionParams sessionParams) {
        return new DisclaimersController(disclaimersService, directService, sessionParams);
    }

    @Bean
    public UsersController usersController(AuthService authService) {
        return new UsersController(authService);
    }

    @Bean
    public DirectController directController(DirectService directService,
                                             CreativesService creativesService,
                                             Executor executor, AuthService authService,
                                             VideoPresetsService videoPresetsService,
                                             PresetsService canvasPresetsService,
                                             CreativeUploadHelperFacade creativeUploadHelperFacade) {
        return new DirectController(directService, creativesService, executor, authService, videoPresetsService,
                canvasPresetsService, creativeUploadHelperFacade);
    }

    @Bean
    public RtbHostController rtbHostController(CreativesService creativesService) {
        return new RtbHostController(creativesService);
    }

    @Bean
    public StockController stockController(StockService stockService) {
        return new StockController(stockService);
    }

    @Bean
    public SourceController sourceController(Html5SourcesService html5SourcesService, AuthService authService,
                                             SessionParams sessionParams) {
        return new SourceController(html5SourcesService, authService, sessionParams);
    }

    @Bean
    public Html5BatchesController html5BatchesController(Html5BatchesService html5BatchesService,
                                                         Html5SourcesService html5SourcesService,
                                                         AuthService authService, SessionParams sessionParams,
                                                         Html5SizeValidator html5SizeValidator,
                                                         DirectService directService) {
        return new Html5BatchesController(html5BatchesService, html5SourcesService, authService, sessionParams,
                html5SizeValidator, directService);
    }

    @Bean
    public Html5DirectController html5DirectController(AuthService authService,
                                                       Html5CreativesService html5CreativesService) {
        return new Html5DirectController(authService, html5CreativesService);
    }

    @Bean
    public Html5CreativeController html5CreativeController(
            BatchesRepository batchesRepository,
            Html5SourcesService sourcesService,
            Html5CreativesService html5CreativesService,
            ScreenshooterService screenshooterService,
            SessionParams sessionParams,
            DirectService directService,
            Html5ScreenshooterHelperService html5ScreenshooterHelperService,
            AuthService authService) {
        return new Html5CreativeController(batchesRepository, sourcesService, html5CreativesService,
                screenshooterService, authService, sessionParams, directService, html5ScreenshooterHelperService);
    }

    @Bean
    public VideoAdditionCreatorService videoAdditionCreatorService(VideoAdditionsService videoAdditionsService,
                                                                   VideoAdditionValidationService videoAdditionValidationService,
                                                                   VideoCreativesService videoCreativesService,
                                                                   VideoPresetsService videoPresetsService) {
        return new VideoAdditionCreatorService(videoAdditionsService, videoAdditionValidationService,
                videoCreativesService, videoPresetsService);
    }

    @Bean
    public VideoAdditionsController videoAdditionsController(AuthService authService,
                                                             VideoAdditionsService videoAdditionsService,
                                                             StillageService stillageService,
                                                             VideoCreativesService videoCreativesService,
                                                             VideoPresetsService videoPresetsService,
                                                             VideoAdditionCreatorService videoAdditionCreatorService,
                                                             SessionParams sessionParams,
                                                             StaticPreviewService staticPreviewService,
                                                             VideoPreviewUrlBuilder videoPreviewUrlBuilder,
                                                             DirectService directService) {
        return new VideoAdditionsController(authService, videoAdditionsService,
                stillageService, videoCreativesService,
                videoAdditionCreatorService, videoPresetsService, sessionParams, staticPreviewService,
                videoPreviewUrlBuilder, directService);
    }

    @Bean
    public VideoAdditionsSurveyController videoAdditionsSurveyController(AuthService authService,
                                                                         VideoAdditionCreatorService videoAdditionCreatorService,
                                                                         SessionParams sessionParams) {
        return new VideoAdditionsSurveyController(videoAdditionCreatorService, authService,
                sessionParams);
    }

    @Bean
    public VideoPresetsController videoPresetsController(VideoPresetsService videoPresetsService,
                                                         SessionParams sessionParams,
                                                         VideoLimitsService videoLimitsService,
                                                         DirectService directService) {
        return new VideoPresetsController(videoPresetsService, sessionParams, videoLimitsService, directService);
    }

    @Bean
    public VideoDirectController videoDirectController(AuthService authService,
                                                       VideoCreativesService videoCreativesService,
                                                       CreativesGenerationService creativesGenerationService,
                                                       VideoAdditionDirectUploadHelper videoAdditionDirectUploadHelper) {
        return new VideoDirectController(authService, videoCreativesService, creativesGenerationService,
                videoAdditionDirectUploadHelper);
    }

    @Bean
    public VideoMotionController videoMotionController(AuthService authService,
                                                       VideoMotionService videoMotionService) {
        return new VideoMotionController(authService, videoMotionService);
    }

    @Bean
    public VideoCreativesController videoCreativesController(
            VideoAdditionsService videoAdditionsService,
            VideoCreativesService videoCreativesService,
            StillageService stillageService,
            ScreenshooterService screenshooterService,
            VideoAdditionScreenshooterHelperService videoAdditionScreenshooterHelperService,
            StaticPreviewService staticPreviewService,
            AuthService authService) {
        return new VideoCreativesController(videoAdditionsService, videoCreativesService, stillageService,
                videoAdditionScreenshooterHelperService, screenshooterService, staticPreviewService, authService);
    }

    @Bean
    public VideoFilesController videoFilesController(PythonRedirect pythonRedirect,
                                                     StockMoviesService stockMoviesService, AuthService authService,
                                                     VideoFilesRepository videoFilesRepository,
                                                     MovieServiceInterface movieService,
                                                     PackshotServiceInterface packshotService,
                                                     AudioService audioService,
                                                     VideoSoundTrackService videoSoundTrackService,
                                                     SessionParams sessionParams,
                                                     DirectService directService,
                                                     InBannerVideoFilesService inBannerService) {
        return new VideoFilesController(stockMoviesService, authService, videoFilesRepository, movieService,
                packshotService, audioService, videoSoundTrackService, sessionParams, inBannerService, directService);

    }

    @Bean
    public VideoFilesModifyingController videoFilesModifyingController(AuthService authService,
                                                                       MovieServiceInterface movieService,
                                                                       AudioServiceInterface audioService,
                                                                       PackshotServiceInterface packshotService,
                                                                       SessionParams sessionParams,
                                                                       VideoCreativesService videoCreativesService,
                                                                       InBannerVideoFilesService inBannerVideoFilesService, DirectService directService, VideoPresetsService videoPresetsService) {
        return new VideoFilesModifyingController(authService, movieService, audioService, packshotService,
                sessionParams, videoCreativesService, directService, inBannerVideoFilesService, videoPresetsService);
    }

    @Bean
    public VideoStockFilesSearchController videoStockFilesSearchController(StockMoviesService stockMoviesService,
                                                                           VideoPresetsService videoPresetsService,
                                                                           VideoCategoriesService videoCategoriesService) {
        return new VideoStockFilesSearchController(stockMoviesService, videoCategoriesService, videoPresetsService);
    }

    @Bean
    public StockVideoController stockVideoController(StockMoviesService stockMoviesService,
                                                     VideoCategoriesService videoCategoriesService) {
        return new StockVideoController(stockMoviesService, videoCategoriesService);
    }

    @Bean
    public DiagnosticsController diagnosticsController(VideoFilesRepository videoFilesRepository) {
        return new DiagnosticsController(videoFilesRepository);
    }


    @Bean
    public InBannerPreviewController inBannerPreviewController(InBannerHtmlCreativeWriter inBannerCreativesWriter,
                                                               AuthService authService,
                                                               CreativesService creativesService,
                                                               SessionParams sessionParams, Validator validator,
                                                               InBannerVideoFilesService inBannerVideoFilesService) {
        return new InBannerPreviewController(inBannerCreativesWriter, authService, creativesService,
                sessionParams, validator, inBannerVideoFilesService);
    }

}
