package ru.yandex.canvas.service.video;

import java.io.IOException;
import java.net.URI;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import javax.annotation.Nullable;

import org.springframework.data.domain.Sort;

import ru.yandex.canvas.model.stillage.StillageFileInfo;
import ru.yandex.canvas.model.video.VideoFiles;
import ru.yandex.canvas.model.video.files.AudioSource;
import ru.yandex.canvas.model.video.files.FileType;
import ru.yandex.canvas.repository.ItemsWithTotal;
import ru.yandex.canvas.repository.video.VideoFilesRepository;
import ru.yandex.canvas.service.SessionParams;
import ru.yandex.canvas.service.video.files.StockMoviesService;

/**
 * Сервис для работы с аудиодорожкой к видео.
 */
public class VideoSoundTrackService implements VideoFilesServiceInterface<AudioSource, String> {
    private StockMoviesService stockMoviesService;
    private SessionParams sessionParams;
    private VideoFilesRepository videoFilesRepository;

    public VideoSoundTrackService(StockMoviesService stockMoviesService, SessionParams sessionParams,
                                  VideoFilesRepository videoFilesRepository) {
        this.stockMoviesService = stockMoviesService;
        this.sessionParams = sessionParams;
        this.videoFilesRepository = videoFilesRepository;
    }

    @Override
    public String markFileUsed(AudioSource file, Long clientId) {
        throw new UnsupportedOperationException("You must mark audio through MovieService");
    }

    @Override
    public AudioSource upload(byte[] content, String filename, Long clientId,
                              VideoCreativeType videoCreativeType, Long presetId) throws IOException {
        throw new UnsupportedOperationException("Audio can't be uploaded");
    }

    @Override
    public AudioSource upload(URI url, String filename, Long clientId,
                              VideoCreativeType videoCreativeType, Long presetId) throws IOException {
        throw new UnsupportedOperationException("Audio can't be uploaded");
    }

    @Override
    public AudioSource upload(StillageFileInfo info, String filename, Long clientId,
                              VideoCreativeType videoCreativeType, Long presetId) {
        throw new UnsupportedOperationException("Audio can't be uploaded");
    }

    @Override
    public StillageFileInfo processFileInfo(StillageFileInfo info, String filename,
                                            VideoCreativeType videoCreativeType) {
        throw new UnsupportedOperationException("Audio can't be uploaded");
    }

    public boolean delete(AudioSource file, Long clientId) {
        return videoFilesRepository.deleteFile(file.getId(), clientId, FileType.AUDIO);
    }

    @Override
    public AudioSource makeFromDb(VideoFiles record) {
        if (record.getCreativeType() != null && record.getCreativeType() != sessionParams.getCreativeType()) {
            throw new IllegalArgumentException(
                    "Could not create object from " + record.getCreativeType() + "in " + sessionParams.getCreativeType()
                            + " session");
        }

        AudioSource source = stockMoviesService.getAudio(record.getStockFileId());

        return new AudioSource(record, source);
    }

    @Override
    public ItemsWithTotal<AudioSource> getUserFiles(Long clientId, String nameSubstring,
                                                    Sort.Direction direction,
                                                    int limit,
                                                    int offset, VideoCreativeType videoCreativeType,
                                                    Long presetId,
                                                    @Nullable Boolean showFeeds) {
        VideoFilesRepository.QueryBuilder queryBuilder = new VideoFilesRepository.QueryBuilder();
        queryBuilder.withType(FileType.AUDIO)
                .withClientId(clientId)
                .withArchive(false)
                .withStockFile();

        if (nameSubstring != null) {
            queryBuilder.withNameRegexp(".*" + Pattern.quote(nameSubstring) + ".+", "i");
        }

        return new ItemsWithTotal<>(
                videoFilesRepository.findByQuery(queryBuilder, direction, limit, offset).stream()
                        .map(this::makeFromDb).collect(Collectors.toList()),
                videoFilesRepository.count(queryBuilder)
        );

    }
}
