package cn.skcks.docking.gb28181.wvp.service.ffmpeg;


import cn.skcks.docking.gb28181.wvp.config.FfmpegConfig;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.exec.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@RequiredArgsConstructor
public class FfmpegSupportService {
    private final FfmpegConfig ffmpegConfig;

    @SneakyThrows
    public Executor downloadToStream(String input, String out, long time, TimeUnit unit, ExecuteStreamHandler streamHandler, ExecuteResultHandler executeResultHandler) {
        FfmpegConfig.Rtp rtp = ffmpegConfig.getRtp();
        FfmpegConfig.Debug debug = ffmpegConfig.getDebug();
        String inputParam = debug.getDownload() ? rtp.getDownload() : StringUtils.joinWith(" ", "-y", rtp.getDownload(), input);
        log.info("视频输入参数 {}", inputParam);

        String outputParam = debug.getOutput() ? rtp.getOutput() : StringUtils.joinWith(" ", "-t", unit.toSeconds(time), rtp.getOutput(), out);
        log.info("视频输出参数 {}", outputParam);

        return ffmpegExecutor(inputParam, outputParam, unit.toSeconds(time) + 60, TimeUnit.SECONDS, streamHandler, executeResultHandler);
    }

    @SneakyThrows
    public Executor downloadToStream(String input, long time, TimeUnit unit, ExecuteStreamHandler streamHandler, ExecuteResultHandler executeResultHandler) {
        return downloadToStream(input, "-", time, unit, streamHandler, executeResultHandler);
    }

    @SneakyThrows
    public Executor playbackToStream(String input, String out, long time, TimeUnit unit, ExecuteStreamHandler streamHandler, ExecuteResultHandler executeResultHandler){
        FfmpegConfig.Rtp rtp = ffmpegConfig.getRtp();
        FfmpegConfig.Debug debug = ffmpegConfig.getDebug();
        String inputParam = debug.getInput() ? rtp.getInput() : StringUtils.joinWith(" ", "-y", rtp.getInput(), input);
        log.info("视频输入参数 {}", inputParam);

        String outputParam = debug.getOutput() ? rtp.getOutput() : StringUtils.joinWith(" ", rtp.getOutput(), out);
        log.info("视频输出参数 {}", outputParam);

        return ffmpegExecutor(inputParam, outputParam, unit.toSeconds(time) + 60, TimeUnit.SECONDS, streamHandler, executeResultHandler);
    }

    @SneakyThrows
    public Executor playbackToStream(String input, long time, TimeUnit unit, ExecuteStreamHandler streamHandler, ExecuteResultHandler executeResultHandler) {
        return playbackToStream(input, "-", time, unit, streamHandler, executeResultHandler);
    }

    @SneakyThrows
    public Executor ffmpegExecutor(String inputParam,String outputParam, long time, TimeUnit unit,ExecuteStreamHandler streamHandler,ExecuteResultHandler executeResultHandler){
        FfmpegConfig.Rtp rtp = ffmpegConfig.getRtp();
        String logLevelParam = StringUtils.joinWith(" ","-loglevel", rtp.getLogLevel());
        String command = StringUtils.joinWith(" ", ffmpegConfig.getFfmpeg(), logLevelParam, inputParam, outputParam);
        CommandLine commandLine = CommandLine.parse(command);
        log.info("{}", commandLine);
        Executor executor = new DefaultExecutor();
        ExecuteWatchdog watchdog = new ExecuteWatchdog(unit.toMillis(time));
        executor.setStreamHandler(streamHandler);
        executor.setExitValues(null);
        executor.setWatchdog(watchdog);
        if(executeResultHandler == null){
            executor.execute(commandLine);
        } else {
            executor.execute(commandLine, executeResultHandler);
        }
        return executor;
    }
}
