package com.yfd.platform.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yfd.platform.modules.basedata.domain.LinkageSignal;
import com.yfd.platform.modules.basedata.mapper.LinkageSignalMapper;
import com.yfd.platform.modules.patroltask.domain.Task;
import com.yfd.platform.modules.patroltask.domain.TaskResult;
import com.yfd.platform.modules.patroltask.domain.TaskTodo;
import com.yfd.platform.modules.patroltask.mapper.TaskMapper;
import com.yfd.platform.modules.patroltask.mapper.TaskResultMapper;
import com.yfd.platform.modules.patroltask.mapper.TaskTodoMapper;
import com.yfd.platform.modules.patroltask.service.ITaskTodoService;
import com.yfd.platform.modules.robotapi.service.IStationRobotService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * TODO:
 *
 * @Author: ZHANG
 * @create: 2021/8/27 16:11
 */
@Component
@Slf4j
public class RtspToMP4 {

    private Map<String, Process> map = new ConcurrentHashMap<>();

    @Resource
    private TaskResultMapper taskResultMapper;
    @Resource
    private TaskTodoMapper taskTodoMapper;
    @Resource
    private LinkageSignalMapper linkageSignalMapper;
    @Resource
    private TaskMapper taskMapper;

    @Value("${file-space.confirmfilepath}")
    private String confirmfilepath;

    public void createVideocfmresult(String resultId) {

        TaskResult taskResult = taskResultMapper.selectById(resultId);
        taskResult.setValue("1");
        taskResult.setDesc("合位");
        taskResult.setDefectFilePath(taskResult.getFilePath());
        TaskTodo taskTodo = taskTodoMapper.selectById(taskResult.getTaskTodoId());
        if (taskTodo.getTaskType().equals("4")) {
            String controlNum = taskTodo.getControlNum();
            List<LinkageSignal> linkageSignals =
                    linkageSignalMapper.selectList(new LambdaQueryWrapper<LinkageSignal>().eq(LinkageSignal::getControlNum, controlNum));
            if (linkageSignals.size() > 0) {
                LinkageSignal linkageSignal = linkageSignals.get(0);
                String linkageType = linkageSignal.getLinkageType();
                if ("1".equals(linkageType)) {
                    //对于一键顺控任务调用顺控文件生成和处理方法
                    try {
                        this.createVideo(taskResult.getStationCode(), taskResult.getTaskCode(),
                                taskResult.getDesc());
                    } catch (Exception e) {
                        log.error(e.getMessage());
                    }

                }
            }

        }

    }

    private void createVideo(String stationcode, String taskcode, String videoresult) {
        String[] temp = taskcode.split("-");
        //监控索引号
        String monitorindex = temp[0];
        //事件时标
        String eventtime = DateUtil.format(DateUtil.date(Long.parseLong(temp[1])), "yyyy-MM-dd HH:mm:ss.SSS");

        List<Map<String, Object>> tasklist =
                taskMapper.selectMaps(new LambdaQueryWrapper<Task>().eq(Task::getTaskCode, taskcode));
        //        String value1 = "";//一键顺控的原始值
        String equip = "";
        List<LinkageSignal> linkageSignals =
                linkageSignalMapper.selectList(new LambdaQueryWrapper<LinkageSignal>().eq(LinkageSignal::getControlNum, monitorindex));
        String stationNum = "";
        if (tasklist.size() > 0) {//任务表
            //            value1 = tasklist.get(0).get("custom3").toString();
            if (linkageSignals.size() > 0) {
                LinkageSignal linkageSignal = linkageSignals.get(0);
                stationNum = linkageSignal.getStationNum();
                String linkageDeviceName = linkageSignal.getLinkageDeviceName();
                equip = StrUtil.subBefore(linkageDeviceName, "-", true);
            }
        }
        //        String result = "分析识别";
        //        if (value1.equals("合位") && videoresult.equals("刀闸关闭")) {
        //            result = "合闸正常";
        //        }
        //        if (value1.equals("合位") && (videoresult.equals("中间状态") || videoresult.equals("刀闸打开"))) {
        //            result = "合闸异常";
        //        }
        //        if (value1.equals("分位") && videoresult.equals("刀闸打开")) {
        //            result = "分闸正常";
        //        }
        //        if (value1.equals("分位") && (videoresult.equals("中间状态") || videoresult.equals("刀闸关闭"))) {
        //            result = "分闸异常";
        //        }
        String cimfilecontent = getReturnCimFile(stationNum, monitorindex, equip, videoresult, eventtime);
        String filename = confirmfilepath + "videocfmresult.cime";
        FileUtil.writeString(cimfilecontent, filename, Charset.forName("GB2312"));
    }

    private String getReturnCimFile(String stationcode, String monitorindex, String equip, String result, String time) {
        StringBuffer content = new StringBuffer();
        content.append(String.format("<!Entity=设备状态请求结果 ver='V1.0' time='%s'（文件最新时间)!>\n", DateUtil.now()));
        content.append("<DeviceInfo::设备状态>\n");
        content.append("@序号 站序号 监控索引号 设备名称 设备状态 事件时标\n");
        String resultinfo = String.format("#1\t%s\t%s\t%s\t%s\t%s\n",
                stationcode, monitorindex, equip, result, time);
        content.append(resultinfo);
        content.append("</DeviceInfo::设备状态>\n");
        return content.toString();
    }

    public static class In implements Runnable {

        private InputStream inputStream;

        public In(InputStream inputStream) {
            this.inputStream = inputStream;
        }

        @Override
        public void run() {
            try {
                //转成字符输入流
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "gbk");
                int len = -1;
                char[] c = new char[1024];
                //读取进程输入流中的内容
                while ((len = inputStreamReader.read(c)) != -1) {
                    String s = new String(c, 0, len);
                    log.info(s);
                }
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
    }

    public Process StartRecord(String videoStream, String ffmpegPath, String streamUrl, String FilePath) {
        ProcessBuilder processBuilder = new ProcessBuilder();
        //定义命令内容
        List<String> command = new ArrayList<>();
        command.add(ffmpegPath + "ffmpeg");
        command.add("-rtsp_transport");
        command.add("tcp");
        command.add("-i");
        command.add(streamUrl);
        command.add("-t");
        command.add("30");
        command.add("-f");
        command.add("mp4");
        command.add(FilePath);
        processBuilder.command(command);
        log.info("脚本：" + command.toString());
        //将标准输入流和错误输入流合并，通过标准输入流读取信息
        processBuilder.redirectErrorStream(true);
        try {
            //启动进程
            Process process = processBuilder.start();
            log.info("开始时间：" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis())));
            //获取输入流
            InputStream inputStream = process.getInputStream();
            Thread inThread = new Thread(new In(inputStream));
            inThread.start();
            map.put(videoStream, process);
            int i = process.waitFor();
            log.info("StartRecord结束" + i);
            return process;
        } catch (Exception e) {
            log.error(e.getMessage());
        }

        return null;
    }

    public boolean stopRecord(String videoStream) {
        try {
            if (map.containsKey(videoStream)) {
                Process process = map.get(videoStream);
                if (process == null) {
                    return false;
                }
                OutputStream os = process.getOutputStream();
                os.write("q".getBytes());
                // 一定要刷新
                os.flush();
                os.close();
            }
        } catch (Exception err) {
            log.error(err.getMessage());
            return false;
        }
        return true;
    }
}
