package ink.wgink.module.file.media.task.transcoding.runnable;

import ink.wgink.module.file.media.manager.MediaManager;
import ink.wgink.module.file.media.manager.domain.enums.CrfValueEnum;
import ink.wgink.module.file.media.manager.domain.enums.PresetVauleEnum;
import ink.wgink.module.file.media.manager.process.IMediaStream;
import ink.wgink.module.file.media.service.video.IVideoService;
import ink.wgink.module.file.media.task.transcoding.VideoConvertManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: VideoTransCodingRunnable
 * @Description: 视频转码
 * @Author: wanggeng
 * @Date: 2021/6/10 10:04 上午
 * @Version: 1.0
 */
public class VideoConvertRunnable implements Runnable {
    private static final Logger LOG = LoggerFactory.getLogger(VideoConvertRunnable.class);
    private static Pattern durationPattern = Pattern.compile("Duration: \\d{2}:\\d{2}:\\d{2}");
    private static Pattern timePattern = Pattern.compile("time=\\d{2}:\\d{2}:\\d{2}");

    private long fullTime = 0L;
    private long currentTime = 0L;
    private double convertPercent = 0D;
    private boolean isUpdateConvertStatus = false;
    private File outFile;

    private String fileId;
    private String sourceFile;
    private IVideoService videoService;

    public VideoConvertRunnable() {
    }

    public VideoConvertRunnable(String fileId, String sourceFile, IVideoService videoService) {
        this.fileId = fileId;
        this.sourceFile = sourceFile;
        this.videoService = videoService;
    }

    @Override
    public void run() {
        File sourceFile = new File(this.sourceFile);
        outFile = new File(this.sourceFile + ".mp4");
        MediaManager.getInstance().convertVideo(sourceFile, outFile, true, CrfValueEnum.HIGH_QUALITY.getCode(), PresetVauleEnum.MAX_FAST_ZIP_SPEED.getPresetValue(), null, null, new IMediaStream() {
            @Override
            public void input(InputStream inputStream) throws Exception {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                for (String line; (line = bufferedReader.readLine()) != null; ) {
                    LOG.debug(line);
                }
            }

            @Override
            public void error(InputStream errorStream) throws Exception {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(errorStream));
                for (String line; (line = bufferedReader.readLine()) != null; ) {
                    Matcher durationMatcher = durationPattern.matcher(line);
                    Matcher timeMatcher = timePattern.matcher(line);
                    if (durationMatcher.find()) {
                        String duration = durationMatcher.group();
                        LOG.debug("开始转码，时长：{}", duration);
                        String durationTime = duration.replace("Duration: ", "");
                        fullTime = durationToLongTime(durationTime);
                    }
                    if (timeMatcher.find()) {
                        String time = timeMatcher.group();
                        String timeTime = time.replace("time=", "");
                        currentTime = durationToLongTime(timeTime);
                    }
                    if (fullTime > 0L) {
                        convertPercent = new BigDecimal((currentTime / (fullTime * 1D) * 100D)).setScale(2, RoundingMode.HALF_UP).doubleValue();
                    }
                    if (convertPercent > 0D && convertPercent < 100D) {
                        VideoConvertManager.getInstance().convertProgressSseEmitterNotice(fileId, convertPercent);
                    }
                }
                VideoConvertManager.getInstance().convertProgressSseEmitterNotice(fileId, convertPercent);
                LOG.debug("转码结束，更新状态");
                videoService.updateConvert(fileId, outFile);
            }
        });
    }

    /**
     * 视频时长
     *
     * @param duration
     * @return
     */
    private long durationToLongTime(String duration) {
        String[] durationArray = duration.split("\\:");
        int hour = Integer.parseInt(durationArray[0]);
        int minute = Integer.parseInt(durationArray[1]);
        int second = Integer.parseInt(durationArray[2]);
        return (hour * 3600 + minute * 60 + second);
    }

}
