package com.project.zcustom.controller.video;

import cn.hutool.core.collection.CollUtil;
import com.project.common.core.controller.BaseController;
import com.project.common.core.domain.AjaxResult;
import com.project.common.utils.StringUtils;
import com.project.zcustom.domain.video.ZnhqWebcam;
import com.project.zcustom.service.video.IScreenUnifiedVideoService;
import com.project.zcustom.service.video.IZnhqWebcamService;
import com.project.zcustom.tools.ProcessCache;
import com.project.zcustom.tools.ProcessConstant;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * 基础运行数据Controller
 *
 * @author change
 * @date 2024-10-21
 */

@RestController
@RequestMapping("/large/video")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class PlatVideoController extends BaseController {
    private static final Logger logger = LoggerFactory.getLogger(PlatVideoController.class);

    @Value("${znhqcamera.path}")
    private String videoPath;

    @Value("${znhqcamera.rtmp}")
    private String videoRtmp;

    @Value("${znhqcamera.flv}")
    private String videoflv;

    private final ThreadPoolTaskExecutor threadPoolTaskExecutor;
    private final IZnhqWebcamService znhqWebcamService;
    private final IScreenUnifiedVideoService iScreenUnifiedVideoService;


    //@RequestMapping("/monitorList")
    public AjaxResult monitorList(@RequestParam String code) {
        return AjaxResult.success("查询成功", znhqWebcamService.selectVideoList(code));
    }


    @RequestMapping("/videoList")
    public AjaxResult videoList(@RequestParam String code) {
        return AjaxResult.success("查询成功", iScreenUnifiedVideoService.selectVideoList(code));
    }


    //@RequestMapping("/openCamera")
    public AjaxResult openCamera(@RequestParam("videoCode") String videoCode) {
        try {
            List<ZnhqWebcam> list = znhqWebcamService.selectVideoList(videoCode);
            if (CollUtil.isNotEmpty(list)) {
                ZnhqWebcam resultPO = list.get(0);
                ProcessCache cache = ProcessConstant.processConcurrentHashMap.get(videoCode);
                String userId = "sxgw001";
                //如果流媒体服务器已经在推当前摄像头编码的数据，就直接从缓存map中获取摄像头访问地址
                if (cache != null) {
                    Process process = cache.getProcess();
                    if (process != null && process.isAlive()) {
                        // 进程仍然活跃，返回视频URL
                        String videoUrl = cache.getVideoUrl();
                        cache.getUserIds().add(userId);
                        logger.info("查看视频，已有推流：processConcurrentHashMap:" + ProcessConstant.processConcurrentHashMap);
                        return AjaxResult.success("获取成功",videoUrl);
                    } else {
                        // 进程不再活跃，从缓存中移除并处理这种情况
                        ProcessConstant.processConcurrentHashMap.remove(videoCode);
                        logger.info("流媒体进程已停止，从缓存中移除对应视频代码：" + videoCode);
                        // 这里您可以添加代码重新启动进程或返回错误消息
                        // ...
                    }

                }
                String resolution = resultPO.getResolution();
                //组合执行的进程命令：海康威视
                List<String> command = new ArrayList<>();
                command.add(videoPath);
                command.add("-rtsp_transport");
                command.add("tcp");
                command.add("-i");
                command.add(resultPO.getUrl());
                command.add("-vcodec");
                //h264编码====山西专用。  解决报错：Video codec hevc not compatible with flv
                command.add("libx264");
                command.add("-acodec");
                command.add("copy");

                // -threads 5 -preset ultrafast -max_delay 100000        设置超快速
                command.add("-threads");
                command.add("5");
                command.add("-preset");
                command.add("ultrafast");
                command.add("-max_delay");
                command.add("100000");
                //
                command.add("-f");
                command.add("flv");

                if (StringUtils.isNotBlank(resolution)){
                    command.add("-s");
                    command.add(resolution);
                }
                command.add(videoRtmp + videoCode);

                logger.error("海康---摄像头command地址：" + command.toString());
                //构建进程对象
                ProcessBuilder builder = new ProcessBuilder();
                builder.command(command);
                //将标准输入流和错误输入流合并，通过标准输入流程读取信息
                builder.redirectErrorStream(true);
                //启动进程
                Process process = builder.start();

                //注意：java虚拟机内存是有限，这里开启一个线程读取进程往外刷的数据，如果不读取java虚拟机会爆满，导致推流的进程卡死
                threadPoolTaskExecutor.execute(() -> {
                    BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
                    String line = null;
                    while (true) {
                        try {
                            if (!((line = br.readLine()) != null)) {
                                break;
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        System.out.println("开启一个线程,读取进程往外刷的数据:" + line);
                    }
                });

                //构建进程缓存对象，在内存中保存进程对象
                ProcessCache processCache = new ProcessCache();
                processCache.setProcess(process);
                processCache.setVideoCode(videoCode);
                Set<String> userIds = processCache.getUserIds();
                userIds.add(userId);
                String videoUrl = videoflv + videoCode;
                processCache.setVideoUrl(videoUrl);
                ProcessConstant.processConcurrentHashMap.put(videoCode, processCache);
                logger.info("查看视频，最新推流：processConcurrentHashMap:" + ProcessConstant.processConcurrentHashMap);
                return AjaxResult.success("获取成功",videoUrl);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            logger.error("error" + ex.getMessage());
        } finally {

        }
        return AjaxResult.error("拉流失败");
    }


}
