package com.inspect.exec.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.inspect.access.base.domain.InfraredFileNameGenerator;
import com.inspect.access.base.feign.AccessFeign;
import com.inspect.access.base.model.InfraredModel;
import com.inspect.analysis.service.IResultAnalysisService;
import com.inspect.base.core.constant.RedisConst;
import com.inspect.base.core.domain.DataMsg;
import com.inspect.base.core.sftp.SftpClient;
import com.inspect.base.core.sftp.SftpUploadEntity;
import com.inspect.base.core.utils.DateUtils;
import com.inspect.base.core.utils.HttpClientUtils;
import com.inspect.base.core.utils.StringUtils;
import com.inspect.base.core.web.controller.BaseController;
import com.inspect.base.redis.service.RedisService;
import com.inspect.exec.domain.DBPatrolPoint;
import com.inspect.exec.domain.EqpBook;
import com.inspect.exec.domain.PatrolTaskExecRecord;
import com.inspect.exec.domain.PatrolTaskPointExecRecord;
import com.inspect.exec.domain.livesipb.RecordData;
import com.inspect.exec.domain.livesipb.Stream;
import com.inspect.exec.domain.task.PatrolResult;
import com.inspect.exec.domain.task.PatrolResultData;
import com.inspect.exec.domain.task.TaskState;
import com.inspect.exec.domain.task.TaskStateData;
import com.inspect.exec.service.IPatrolTaskExecRecordService;
import com.inspect.exec.util.HttpClientUtil;
import com.inspect.base.core.domain.maintain.MaintainRegion;
import com.inspect.partrolresult.controller.PatrolResultController;
import com.inspect.partrolresult.service.IPatrolResultService;
import com.inspect.patrol.domain.PatrolPresetAction;
import com.inspect.patrol.domain.PatrolPresetParam;
import com.inspect.patrol.domain.PatrolPresetPos;
import com.inspect.system.base.domain.SysDictData;
import com.inspect.task.domain.PatrolTask;
import com.inspect.task.service.IPatrolTaskService;
import com.inspect.taskinfo.domain.PatrolTaskInfo;
import com.inspect.taskinfo.service.IPatrolTaskInfoService;
import com.inspect.taskstatus.client.FeignTaskClient;
import com.inspect.taskstatus.service.IPatrolTaskStatusService;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;

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.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping({"/taskExecuteScheduler"})
public class PatrolTaskExecuteSchedulerController extends BaseController {
    @Value("${liveSIPB.url}")
    private String liveSIPB_URL;
    @Value("${sftp.stationCode}")
    private String stationCode;
    private String preset = "/api/v1/control/preset";
    private String channelsnap = "/api/v1/device/channelsnap";
    private static final ExecutorService executor = Executors.newFixedThreadPool(500);
    private final Logger log = LoggerFactory.getLogger(PatrolTaskExecuteSchedulerController.class);
    @Autowired
    private IPatrolTaskService patrolTaskService;
    @Autowired
    private IPatrolTaskStatusService patrolTaskStatusService;
    @Autowired
    private IPatrolTaskInfoService patrolTaskInfoService;
    @Autowired
    private IResultAnalysisService resultAnalysisService;
    @Autowired
    private IPatrolResultService patrolResultService;
    @Resource
    private FeignTaskClient feignTaskClient;
    @Autowired
    private SftpClient sftpClient;
    @Autowired
    public RedisService redisService;
    @Autowired
    private IPatrolTaskExecRecordService patrolTaskExecRecordService;
    @Autowired
    PatrolTaskExecController taskExecClient;
    @Autowired
    PatrolResultController patrolResultController;
    @Autowired
    AccessFeign accessFeign;

    //和JobMainTask完全重复
    @PostMapping({"/immediatelyExecTask"})
    public void immediatelyExecTask(PatrolTask patrolTask) {
        PatrolTaskInfo patrolTaskInfo = new PatrolTaskInfo();
        PatrolPresetPos patrolPresetPos = new PatrolPresetPos();
        PatrolPresetAction patrolPresetAction = new PatrolPresetAction();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        List<String> taskStates = new ArrayList<>();
        taskStates.add("2");
        List<PatrolTaskExecRecord> patrolTaskExecRecordList = null;
        List<PatrolTask> patrolTaskList = new ArrayList<>();
        patrolTaskList.add(patrolTask);
        List<PatrolTask> cameraPatrolTasks = new ArrayList<>();
        this.assembleVideoTask(patrolTaskList, cameraPatrolTasks);

        try {
            for (PatrolTask task : cameraPatrolTasks) {
                List<PatrolTaskExecRecord> patrolTaskExecRecords = this.taskExecClient.selectCameraPatrolTaskExecRecordList(task.getDevNo(), taskStates);
                if (patrolTaskExecRecords != null && !patrolTaskExecRecords.isEmpty()) {
                    return;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        String immediatelyExecTaskTime = "";
        Iterator iterator = cameraPatrolTasks.iterator();
        while (true) {
            PatrolTask task = null;
            while (true) {
                do {
                    if (!iterator.hasNext()) {
                        if (immediatelyExecTaskTime != null && !immediatelyExecTaskTime.isEmpty()) {
                            this.redisService.deleteObjectOfTask(RedisConst.IMMEDIATELY_EXEC_TASK_TIME, task.getTaskCode());
                        }

                        return;
                    }

                    task = (PatrolTask) iterator.next();
                    PatrolTaskExecRecord taskExecRecord = new PatrolTaskExecRecord();
                    taskExecRecord.setTaskId(task.getTaskId());
                    patrolTaskExecRecordList = this.taskExecClient.selectPatrolTaskExecRecordList(taskExecRecord);
                } while (patrolTaskExecRecordList != null && !patrolTaskExecRecordList.isEmpty() && "2".equals(patrolTaskExecRecordList.get(patrolTaskExecRecordList.size() - 1).getTaskState()));

                patrolTaskExecRecordList = this.taskExecClient.selectCameraPatrolTaskExecRecordList(task.getDevNo(), taskStates);
                if (patrolTaskExecRecordList == null || patrolTaskExecRecordList.isEmpty()) {
                    break;
                }

                PatrolTaskExecRecord patrolTaskExecRecord = patrolTaskExecRecordList.get(0);
                if (!"5".equals(patrolTaskExecRecord.getTaskType())) {
                    PatrolTaskPointExecRecord patrolTaskPointExecRecord = new PatrolTaskPointExecRecord();
                    patrolTaskPointExecRecord.setTaskPatrolledId(patrolTaskExecRecord.getTaskPatrolId());
                    List<PatrolTaskPointExecRecord> patrolTaskPointExecRecordList = this.taskExecClient.selectPatrolTaskPointExecRecordList(patrolTaskPointExecRecord);
                    if (patrolTaskPointExecRecordList != null && !patrolTaskPointExecRecordList.isEmpty()) {
                        patrolTaskPointExecRecord = patrolTaskPointExecRecordList.get(patrolTaskPointExecRecordList.size() - 1);
                        patrolTaskExecRecord.setExecPointId(patrolTaskPointExecRecord.getPointId());
                        patrolTaskExecRecord.setDeviceId(patrolTaskPointExecRecord.getDeviceId());
                    }

                    this.log.info("暂停当前执行任务 {} ", "taskName:" + patrolTaskExecRecord.getTaskName() + " taskCode:" + patrolTaskExecRecord.getTaskCode() + " execPointId:" + patrolTaskExecRecord.getExecPointId() + " deviceId:" + patrolTaskPointExecRecord.getDeviceId());
                    patrolTaskExecRecord.setTaskState("3");
                    this.taskExecClient.updatePatrolTaskExecRecord(patrolTaskExecRecord);
                    break;
                }
            }

            PatrolTaskExecRecord patrolTaskExecRecord = new PatrolTaskExecRecord();
            if (immediatelyExecTaskTime != null && !immediatelyExecTaskTime.isEmpty()) {
                immediatelyExecTaskTime = this.redisService.getCacheObjectOfTask(RedisConst.IMMEDIATELY_EXEC_TASK_TIME, task.getTaskCode());
            } else {
                SimpleDateFormat sdfOld = new SimpleDateFormat("yyyyMMddHHmmss");
                immediatelyExecTaskTime = sdfOld.format(new Date());
                this.redisService.setCacheObjectOfTask(RedisConst.IMMEDIATELY_EXEC_TASK_TIME, task.getTaskCode(), immediatelyExecTaskTime);
            }

            Date time = task.getFixedStartTime();
            patrolTaskExecRecord.setTaskPatrolId(task.getDevNo() + "_" + task.getTaskCode() + "_" + immediatelyExecTaskTime);
            patrolTaskExecRecord.setOldTaskPatrolId(task.getTaskCode() + "_" + sdf.format(time) + "_" + immediatelyExecTaskTime);
            patrolTaskExecRecord.setTaskName(task.getTaskName());
            patrolTaskExecRecord.setTaskCode(task.getTaskCode());
            patrolTaskExecRecord.setTaskState("2");
            patrolTaskExecRecord.setPlanStartTime(task.getCycleStartTime());
            patrolTaskExecRecord.setStartTime(new Date());
            patrolTaskExecRecord.setTaskProgress("");
            patrolTaskExecRecord.setEndTime(task.getCycleEndTime());
            patrolTaskExecRecord.setDescription("");
            patrolTaskExecRecord.setDevNo(task.getDevNo());
            patrolTaskExecRecord.setTaskType(task.getType());
            patrolTaskExecRecord.setTaskPriority(task.getPriority());
            patrolTaskExecRecord.setTaskId(task.getTaskId());
            patrolTaskExecRecord.setStationName(task.getStationName());
            patrolTaskExecRecord.setStationCode(task.getStationCode());
            this.log.info("保存立即执行任务主表信息 {} ", "TaskName:" + patrolTaskExecRecord.getTaskName() + " TaskCode:" + patrolTaskExecRecord.getTaskCode() + " TaskPatrolledId:" + patrolTaskExecRecord.getTaskPatrolId());
            this.taskExecClient.addPatrolTaskExecRecord(patrolTaskExecRecord);
            patrolTaskInfo.setTaskMajorId(task.getTaskId().toString());
            patrolTaskInfo.setDevNo(task.getDevNo());
            List<PatrolTaskInfo> patrolTaskInfoList = this.taskExecClient.selectTaskInfoList(patrolTaskInfo);
            this.immediatelyPrePointExecControl(patrolTaskExecRecord, patrolPresetPos, patrolPresetAction, patrolTaskInfoList);
            task.setExecutionStatus("3");
            this.taskExecClient.updatePatrolTaskStatus(task);
        }
    }

    private void assembleVideoTask(List<PatrolTask> patrolTaskList, List<PatrolTask> cameraPatrolTasks) {
        if (patrolTaskList != null && !patrolTaskList.isEmpty()) {
            Iterator<PatrolTask> iterator = patrolTaskList.iterator();

            while (true) {
                PatrolTask task;
                do {
                    if (!iterator.hasNext()) {
                        return;
                    }

                    task = iterator.next();
                } while (StringUtils.isEmpty(task.getDevType()));

                String[] devTypes = task.getDevType().split(StringUtils.COMMA);
                String[] devNos = task.getDevNo().split(StringUtils.COMMA);
                for (int i = 0; i < devTypes.length; ++i) {
                    if ("2".equals(devTypes[i])) {
                        PatrolTask cameraPatrolTask = new PatrolTask();
                        cameraPatrolTask.setTaskId(task.getTaskId());
                        cameraPatrolTask.setStationName(task.getStationName());
                        cameraPatrolTask.setStationCode(task.getStationCode());
                        cameraPatrolTask.setType(task.getType());
                        cameraPatrolTask.setTaskCode(task.getTaskCode());
                        cameraPatrolTask.setTaskName(task.getTaskName());
                        cameraPatrolTask.setPriority(task.getPriority());
                        cameraPatrolTask.setDeviceLevel(task.getDeviceLevel());
                        cameraPatrolTask.setDeviceList(task.getDeviceList());
                        cameraPatrolTask.setFixedStartTime(task.getFixedStartTime());
                        cameraPatrolTask.setCycleMonth(task.getCycleMonth());
                        cameraPatrolTask.setCycleWeek(task.getCycleWeek());
                        cameraPatrolTask.setCycleExecuteTime(task.getCycleExecuteTime());
                        cameraPatrolTask.setCycleStartTime(task.getCycleStartTime());
                        cameraPatrolTask.setCycleEndTime(task.getCycleEndTime());
                        cameraPatrolTask.setIntervalNumber(task.getIntervalNumber());
                        cameraPatrolTask.setIntervalType(task.getIntervalType());
                        cameraPatrolTask.setIntervalExecuteTime(task.getIntervalExecuteTime());
                        cameraPatrolTask.setIntervalStartTime(task.getIntervalStartTime());
                        cameraPatrolTask.setIntervalEndTime(task.getIntervalEndTime());
                        cameraPatrolTask.setInvalidStartTime(task.getInvalidStartTime());
                        cameraPatrolTask.setInvalidEndTime(task.getInvalidEndTime());
                        cameraPatrolTask.setIsEnable(task.getIsEnable());
                        cameraPatrolTask.setLinkageState(task.getLinkageState());
                        cameraPatrolTask.setDevType("2");
                        cameraPatrolTask.setDrafter(task.getDrafter());
                        cameraPatrolTask.setExecutionStatus(task.getExecutionStatus());
                        cameraPatrolTask.setFileStatus(task.getFileStatus());
                        cameraPatrolTask.setTaskCycle(task.getTaskCycle());
                        cameraPatrolTask.setDevNo(devNos[i]);
                        cameraPatrolTask.setStorage(task.getStorage());
                        cameraPatrolTask.setTaskProgress(task.getTaskProgress());
                        cameraPatrolTask.setTaskState(task.getTaskState());
                        cameraPatrolTask.setExecutionMode(task.getExecutionMode());
                        cameraPatrolTask.setBeginTime(task.getBeginTime());
                        cameraPatrolTask.setEndTime(task.getEndTime());
                        cameraPatrolTask.setAreaId(task.getAreaId());
                        cameraPatrolTask.setAreaName(task.getAreaName());
                        cameraPatrolTasks.add(cameraPatrolTask);
                    }
                }
            }
        }
    }

    private void immediatelyPrePointExecControl(PatrolTaskExecRecord patrolTaskExecRecord, PatrolPresetPos patrolPresetPos, PatrolPresetAction patrolPresetAction, List<PatrolTaskInfo> patrolTaskInfoList) {
        PatrolTaskExecRecord taskExecRecord = this.taskExecClient.selectPatrolTaskExecRecordByTaskPatrolId(patrolTaskExecRecord.getTaskPatrolId());
        if (taskExecRecord != null && "2".equals(taskExecRecord.getTaskState())) {
            MaintainRegion maintainRegion = new MaintainRegion();
            maintainRegion.setEnable("1");
            List maintainAreaList = null;

            try {
                maintainAreaList = this.taskExecClient.selectMaintainRegionList(maintainRegion);
            } catch (Exception e) {
                e.printStackTrace();
            }

            List<String> deviceIds = new ArrayList<>();
            this.execRemoveMaintainArea(patrolTaskInfoList, maintainAreaList, deviceIds);
            boolean continueExce = true;
            int patrolTaskInfoListSize = patrolTaskInfoList.size();

            for (int ii = 0; ii < patrolTaskInfoListSize; ++ii) {
                PatrolTaskInfo taskInfo = patrolTaskInfoList.get(ii);
                taskExecRecord = this.taskExecClient.selectPatrolTaskExecRecordByTaskPatrolId(patrolTaskExecRecord.getTaskPatrolId());
                if (taskExecRecord != null && ("3".equals(taskExecRecord.getTaskState()) || "4".equals(taskExecRecord.getTaskState()))) {
                    continueExce = false;
                }

                this.log.info("[EXEC] taskInfo {} ", "deviceId:" + taskInfo.getDeviceId() + " LineId=" + taskInfo.getLineId());
                this.prePointExec(patrolTaskExecRecord, patrolPresetPos, patrolPresetAction, taskExecRecord, continueExce, patrolTaskInfoListSize, ii, taskInfo);
            }
        }

    }

    private void execRemoveMaintainArea(List<PatrolTaskInfo> patrolTaskInfoList, List<MaintainRegion> maintainRegionList, List<String> deviceIds) {

        for (MaintainRegion area : maintainRegionList) {
            if (area.getStartTime().getTime() < System.currentTimeMillis() && area.getEndTime().getTime() > System.currentTimeMillis()) {
                deviceIds.addAll(Arrays.asList(area.getPointList().split(StringUtils.COMMA)));
                String[] pointIds = area.getPointList().split(StringUtils.COMMA);
                this.patrolTaskInfoMaintainAreaRemove(patrolTaskInfoList, pointIds);
            }
        }

    }

    private void patrolTaskInfoMaintainAreaRemove(List<PatrolTaskInfo> patrolTaskInfoList, String[] pointIds) {
        if (pointIds != null && pointIds.length > 0 && patrolTaskInfoList != null && !patrolTaskInfoList.isEmpty()) {
            for (String pointId : pointIds) {
                for (int p = 0; p < patrolTaskInfoList.size(); ++p) {
                    if (pointId.equals(patrolTaskInfoList.get(p).getDeviceId())) {
                        patrolTaskInfoList.remove(p);
                    }
                }
            }
        }

    }

    private PatrolTaskExecRecord prePointExec(PatrolTaskExecRecord patrolTaskExecRecord, PatrolPresetPos patrolPresetPos, PatrolPresetAction patrolPresetAction, PatrolTaskExecRecord taskExecRecord, boolean continueExce, int patrolTaskInfoListSize, int ii, PatrolTaskInfo taskInfo) {
        if (continueExce) {
            Calendar now = Calendar.getInstance();
            int year = now.get(Calendar.YEAR);
            int month = now.get(Calendar.MONTH) + 1;
            int day = now.get(Calendar.DATE);
            patrolPresetPos.setPatrolPointId(Long.parseLong(taskInfo.getDeviceId()));
            patrolPresetPos.setIsEnable("1");
            patrolPresetPos.setPatrolDeviceCode(taskInfo.getDevNo());
            List<PatrolPresetPos> patrolPresetPosList = this.taskExecClient.selectPatrolPresetPosList(patrolPresetPos);
            if (patrolPresetPosList != null && !patrolPresetPosList.isEmpty()) {
                String monthStr = "" + month;
                if (month < 10) {
                    monthStr = "0" + monthStr;
                }

                String dayStr = "" + day;
                if (day < 10) {
                    dayStr = "0" + dayStr;
                }

                String basePath = (patrolTaskExecRecord.getStationCode() == null ? this.stationCode : patrolTaskExecRecord.getStationCode()) + "/" + year + "/" + monthStr + "/" + dayStr + "/" + patrolTaskExecRecord.getTaskCode() + "/";
                PatrolPresetPos presetPos = patrolPresetPosList.get(0);
                try {
                    String param = "serial=" + presetPos.getVideoNvrCode() + "&command=goto&preset=" + presetPos.getPresetPosCode() + "&code=" + presetPos.getChannelCode();
                    log.info("[EXEC] PRESET TURN TO MEDIA CLOUD MIRROR CONTROL INTERFACE: {}", this.liveSIPB_URL + this.preset + param);
                    HttpClientUtils.get(this.liveSIPB_URL + this.preset, param);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                try {
                    Thread.sleep(2000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                patrolPresetAction.setPresetPosId(presetPos.getPresetPosId());
                List<PatrolPresetAction> patrolPresetActionList = taskExecClient.selectPatrolPresetActionList(patrolPresetAction);
                StringBuffer fileTypes = new StringBuffer();
                StringBuffer filePaths = new StringBuffer();
                Iterator<PatrolPresetAction> iterator = patrolPresetActionList.iterator();
                while (true) {
                    if (!iterator.hasNext()) {
                        taskExecRecord = this.savePatrolTaskExecRecordAndPointExecRecord(patrolTaskExecRecord, taskExecRecord, patrolTaskInfoListSize, ii, taskInfo, presetPos, fileTypes, filePaths);
                        break;
                    }

                    PatrolPresetAction presetAction = iterator.next();
                    int photoGap;
                    if ("1".equals(presetAction.getActionType())) {
                        if ("vl".equals(presetPos.getChannelType())) {
                            fileTypes.append(2).append(",");
                        } else if ("ir".equals(presetPos.getChannelType())) {
                            fileTypes.append(1).append(",");
                        }

                        photoGap = presetAction.getPhotoGap();
                        long count = presetAction.getPhotoCount();

                        for (byte i = 0; (long) i < count; --count) {
                            patrolTaskExecRecord = this.taskExecClient.selectPatrolTaskExecRecordByTaskPatrolId(patrolTaskExecRecord.getTaskPatrolId());
                            if ("3".equals(patrolTaskExecRecord.getTaskState()) || "4".equals(patrolTaskExecRecord.getTaskState())) {
                                taskExecRecord = this.savePatrolTaskExecRecordAndPointExecRecord(patrolTaskExecRecord, taskExecRecord, patrolTaskInfoListSize, ii, taskInfo, presetPos, fileTypes, filePaths);
                                return taskExecRecord;
                            }

                            if (count * (long) photoGap / (long) photoGap == count) {
                                System.out.println(count);

                                try {
                                    Thread.sleep(1000L * photoGap);
                                    if ("vl".equals(presetPos.getChannelType())) {
                                        Date date = new Date();
                                        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
                                        String filePath = this.saveFile(this.liveSIPB_URL + "/api/v1/device/channelsnap?serial=" + presetPos.getVideoNvrCode() + "&realtime=true&code=" + presetPos.getChannelCode(), presetPos.getPatrolPointId() + "_" + patrolTaskExecRecord.getDevNo() + "_" + sdf.format(date) + ".jpg", basePath + "CCD");
                                        if ("".equals(filePath)) {
                                            filePath = this.saveFile(this.liveSIPB_URL + "/api/v1/device/channelsnap?serial=" + presetPos.getVideoNvrCode() + "&realtime=true&code=" + presetPos.getChannelCode(), presetPos.getPatrolPointId() + "_" + patrolTaskExecRecord.getDevNo() + "_" + sdf.format(date) + ".jpg", basePath + "CCD");
                                        }

                                        filePaths.append(filePath).append(",");
                                    } else if ("ir".equals(presetPos.getChannelType())) {
                                        InfraredModel infraredModel = new InfraredModel();
                                        infraredModel.setChannelSerial(presetPos.getChannelCode());
                                        infraredModel.setPresetId(Integer.parseInt(presetPos.getPresetPosCode()));
                                        EqpBook eqpbook = new EqpBook();
                                        eqpbook.setPatrolDeviceCode(presetPos.getPatrolDeviceCode());
                                        List<EqpBook> eqpBookListList = this.taskExecClient.selectBasedataEqpbookList(eqpbook);
                                        if (eqpBookListList != null && !eqpBookListList.isEmpty()) {
                                            eqpbook = eqpBookListList.get(0);
                                            infraredModel.setIp(eqpbook.getIpAddr());
                                            infraredModel.setPort(Integer.parseInt(eqpbook.getPort()));
                                            infraredModel.setPassword(eqpbook.getPassword());
                                            infraredModel.setUsername(eqpbook.getUser());
                                            InfraredFileNameGenerator infraredFileNameGenerator = new InfraredFileNameGenerator();
                                            if (taskExecRecord.getStationCode() != null) {
                                                infraredFileNameGenerator.setStationCode(taskExecRecord.getStationCode());
                                            } else {
                                                infraredFileNameGenerator.setStationCode("1");
                                            }

                                            infraredFileNameGenerator.setTaskCode(taskExecRecord.getTaskCode());
                                            infraredFileNameGenerator.setPatrolpointCode(presetPos.getPresetPosCode());
                                            infraredFileNameGenerator.setPatroldeviceCode(eqpbook.getPatrolDeviceCode());
                                            infraredModel.setInfraredFileNameGenerator(infraredFileNameGenerator);
                                            this.accessFeign.infrared(infraredModel);
                                            String path = "";

                                            for (int x = 0; x < 120; ++x) {
                                                Thread.sleep(1000L);
                                                path = this.redisService.getCacheObject("REDIS_ACCESS_INFRARED_RESULT");
                                                if (path != null && !path.isEmpty()) {
                                                    break;
                                                }
                                            }

                                            filePaths.append(path).append(",");
                                            this.log.info("[EXEC] TASK NAME: {}, INFRA PIC PATH :{}", taskExecRecord.getTaskName(), path);
                                            redisService.deleteObject("REDIS_ACCESS_INFRARED_RESULT");
                                        }
                                    }
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    } else if ("2".equals(presetAction.getActionType())) {
                        fileTypes.append(4).append(",");
                        photoGap = presetAction.getVideoTime();
                        String jsonStr = HttpClientUtil.getHttpResultJson(this.liveSIPB_URL + "/api/v1/stream/start?serial=" + presetPos.getVideoNvrCode() + "&code=" + presetPos.getChannelCode());
                        this.log.info("[EXEC] LIVE NVR CODE: {}, CHANNEL CODE:/api/v1/stream/start?serial=&code={} ", presetPos.getVideoNvrCode(), presetPos.getChannelCode());
                        this.log.info("/api/v1/stream/start 返回 json 字符串{} ", jsonStr);
                        JSONObject UserInfoReturn = JSON.parseObject(jsonStr);
                        Stream stream = JSON.toJavaObject(UserInfoReturn, Stream.class);

                        try {
                            String rel = HttpClientUtils.get(this.liveSIPB_URL + "/api/v1/record/start", "streamid=" + stream.getStreamId() + "&code=" + presetPos.getChannelCode());
                            this.log.info("[EXEC] VIDEO REC START:{}, /api/v1/record/start channelCode={}, /api/v1/record/start result: {} ", stream.getStreamId(), presetPos.getChannelCode(), rel);
                            if (rel.isEmpty()) {
                                rel = HttpClientUtils.get(this.liveSIPB_URL + "/api/v1/record/start", "streamid=" + stream.getStreamId() + "&code=" + presetPos.getChannelCode());
                                this.log.info("[EXEC] VIDEO REC START AGAIN :{}, /api/v1/record/start channelCode={}, /api/v1/record/start result: {} ", stream.getStreamId(), presetPos.getChannelCode(), rel);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                        try {
                            for (int jj = 0; jj < photoGap + 2; ++jj) {
                                patrolTaskExecRecord = this.taskExecClient.selectPatrolTaskExecRecordByTaskPatrolId(patrolTaskExecRecord.getTaskPatrolId());
                                if ("3".equals(patrolTaskExecRecord.getTaskState()) || "4".equals(patrolTaskExecRecord.getTaskState())) {
                                    this.log.info("[EXEC] VIDEO REC START TaskPatrolledId :{}", patrolTaskExecRecord.getTaskPatrolId());
                                    this.videotapeRecordStop(filePaths, stream, presetPos.getChannelCode(), basePath, presetPos.getPatrolPointId(), presetPos.getVideoNvrCode());
                                    taskExecRecord = this.savePatrolTaskExecRecordAndPointExecRecord(patrolTaskExecRecord, taskExecRecord, patrolTaskInfoListSize, ii, taskInfo, presetPos, fileTypes, filePaths);
                                    return taskExecRecord;
                                }

                                Thread.sleep(1000L);
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        this.videotapeRecordStop(filePaths, stream, presetPos.getChannelCode(), basePath, presetPos.getPatrolPointId(), presetPos.getVideoNvrCode());
                    }
                }
            }
        }

        return taskExecRecord;
    }

    private PatrolTaskExecRecord savePatrolTaskExecRecordAndPointExecRecord(PatrolTaskExecRecord patrolTaskExecRecord, PatrolTaskExecRecord taskExecRecord, int patrolTaskInfoListSize, int ii, PatrolTaskInfo taskInfo, PatrolPresetPos presetPos, StringBuffer fileTypes, StringBuffer filePaths) {
        PatrolPresetParam patrolPresetParam = new PatrolPresetParam();
        patrolPresetParam.setPresetPosId(presetPos.getPresetPosId());
        List<PatrolPresetParam> patrolPresetParams = this.taskExecClient.selectPatrolPresetParamList(patrolPresetParam);
        StringBuilder rectangles = new StringBuilder();
        if (patrolPresetParams != null) {
            for (PatrolPresetParam presetParam : patrolPresetParams) {
                rectangles.append(presetParam.getCoordinate()).append(";");
            }
        }

        PatrolTaskPointExecRecord pointExecRecord = new PatrolTaskPointExecRecord();
        pointExecRecord.setPatrolDeviceName(taskInfo.getDeviceName());
        pointExecRecord.setPatrolDeviceCode(patrolTaskExecRecord.getDevNo());
        pointExecRecord.setTaskName(taskExecRecord.getTaskName());
        pointExecRecord.setTaskCode(taskExecRecord.getTaskCode());
        pointExecRecord.setDeviceName(taskInfo.getDeviceName());
        pointExecRecord.setDeviceId(taskInfo.getDeviceId());
        pointExecRecord.setRecognitionType(presetPos.getAlgSubtypeCode());
        if (fileTypes != null && fileTypes.length() > 1) {
            pointExecRecord.setFileType(fileTypes.substring(0, fileTypes.length() - 1));
        }

        if (filePaths != null && filePaths.length() > 1) {
            pointExecRecord.setFilePath(filePaths.substring(0, filePaths.length() - 1));
        }

        pointExecRecord.setRectangle(rectangles.toString());
        pointExecRecord.setTaskPatrolledId(patrolTaskExecRecord.getTaskPatrolId());
        pointExecRecord.setOldTaskPatrolledId(patrolTaskExecRecord.getOldTaskPatrolId());
        pointExecRecord.setPatrolPointId(presetPos.getPatrolPointId());
        pointExecRecord.setTime(new Date());
        log.info("[EXEC] SAVE PRESET EXEC TABLE INFO START, pointId={}, TaskPatrolledId={}, OldTaskPatrolledId={} ", pointExecRecord.getPointId(), pointExecRecord.getTaskPatrolledId(), pointExecRecord.getOldTaskPatrolledId());
        this.taskExecClient.addPatrolTaskPointExecRecord(pointExecRecord);
        log.info("[EXEC] SAVE PRESET EXEC TABLE INFO END, pointId={}, TaskPatrolledId={}, OldTaskPatrolledId={} ", pointExecRecord.getPointId(), pointExecRecord.getTaskPatrolledId(), pointExecRecord.getOldTaskPatrolledId());

        PatrolResultData patrolResultData = new PatrolResultData();
        patrolResultData.setType("61");
        patrolResultData.setReceiveCode("");
        patrolResultData.setSendCode("");
        List<PatrolResult> patrolResults = new ArrayList<>();
        PatrolResult patrolResult = new PatrolResult();
        patrolResult.setTask_patrolled_id(patrolTaskExecRecord.getTaskPatrolId().split(StringUtils.UNDERLINE)[1] + "_" + patrolTaskExecRecord.getTaskPatrolId().split(StringUtils.UNDERLINE)[2]);
        patrolResult.setDeviceId(pointExecRecord.getDeviceId());
        patrolResult.setDeviceName(pointExecRecord.getDeviceName());
        patrolResult.setFilePath(pointExecRecord.getFilePath());
        patrolResult.setFileType(pointExecRecord.getFileType());
        patrolResult.setPatrolDeviceCode(pointExecRecord.getPatrolDeviceCode());
        patrolResult.setPatrolDeviceName(pointExecRecord.getPatrolDeviceName());
        patrolResult.setRectangle(pointExecRecord.getRectangle());
        patrolResult.setTaskCode(pointExecRecord.getTaskCode());
        patrolResult.setTaskName(pointExecRecord.getTaskName());
        SysDictData sysDictData = SysDictData.builder().build();
        DBPatrolPoint dbPatrolPoint = this.taskExecClient.selectBasedataPatrolPointByPatrolPointId(pointExecRecord.getPatrolPointId());
        List<SysDictData> sysDictDataList = this.taskExecClient.selectDictDataList(sysDictData);
        this.algMapping(patrolResult, dbPatrolPoint, sysDictDataList);
        patrolResult.setTime(DateUtils.format(DateUtils.yyyyMMddHHmmss2, new Date()));
        patrolResult.setUnit("");
        patrolResult.setValid("1");
        patrolResult.setValue("");
        patrolResult.setValueType("");
        patrolResult.setValueUnit("");
        patrolResults.add(patrolResult);
        patrolResultData.setItems(patrolResults);
        Object obj = JSONArray.toJSON(patrolResultData);

        try {
            log.info("[EXEC] CALL startThreadGetInfo json: {} ", obj.toString());
            startThreadGetInfo(obj.toString(), "61");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("[EXEC] CALL startThreadGetInfo Exception ", e);
        }

        List<PatrolTaskInfo> patrolTaskInfoList;
        String taskProgress = "0";

        try {
            PatrolTaskInfo patrolTaskInfo = new PatrolTaskInfo();
            patrolTaskInfo.setDevType("2");
            patrolTaskInfo.setTaskMajorId(taskExecRecord.getTaskId().toString());
            patrolTaskInfoList = this.taskExecClient.selectTaskInfoList(patrolTaskInfo);
            PatrolTaskPointExecRecord patrolTaskPointExecRecord = new PatrolTaskPointExecRecord();
            patrolTaskPointExecRecord.setOldTaskPatrolledId(taskExecRecord.getOldTaskPatrolId());
            patrolTaskPointExecRecord.setTaskCode(taskExecRecord.getTaskCode());
            List<PatrolTaskPointExecRecord> patrolTaskPointExecRecordList = this.taskExecClient.selectPatrolTaskPointExecRecordList(patrolTaskPointExecRecord);
            if (patrolTaskInfoList != null && patrolTaskPointExecRecordList != null) {
                taskProgress = this.decimalFormatNum(patrolTaskPointExecRecordList.size() - 1, patrolTaskInfoList.size());
            }

            log.info("[EXEC] BIND progress={}, taskName={}, taskCode: {}, OldTaskPatrolledId: {} ", taskProgress, taskExecRecord.getTaskName(), taskExecRecord.getTaskCode(), taskExecRecord.getOldTaskPatrolId());
        } catch (Exception e) {
            e.printStackTrace();
        }

        Object obj41;
        TaskStateData taskStateData;
        ArrayList taskStates;
        TaskState taskState;
        if (patrolTaskInfoListSize - 1 != ii && patrolTaskInfoListSize != 1) {
            taskExecRecord = this.taskExecClient.selectPatrolTaskExecRecordByTaskPatrolId(patrolTaskExecRecord.getTaskPatrolId());
            if ("3".equals(taskExecRecord.getTaskState())) {
                List<PatrolTaskPointExecRecord> pointExecRecordList = this.taskExecClient.selectPatrolTaskPointExecRecordList(pointExecRecord);
                taskExecRecord.setDeviceId(pointExecRecord.getDeviceId());
                taskExecRecord.setExecPointId(pointExecRecordList.get(pointExecRecordList.size() - 1).getPointId());
                taskExecRecord.setTaskProgress(this.decimalFormatNum(ii, patrolTaskInfoListSize));
                log.info("[EXEC] DETACH progress={}, taskName={}, taskCode={}, taskPatrolledId={}", taskExecRecord.getTaskProgress(), taskExecRecord.getTaskName(), taskExecRecord.getTaskCode(), taskExecRecord.getTaskPatrolId());
                this.taskExecClient.updatePatrolTaskExecRecord(taskExecRecord);
                taskStateData = new TaskStateData();
                taskStateData.setType("41");
                taskStateData.setReceiveCode("");
                taskStateData.setSendCode("");
                taskStates = new ArrayList<>();
                taskState = new TaskState();
                taskState.setDescription("");
                if (patrolTaskExecRecord.getPlanStartTime() != null) {
                    taskState.setPlanStartTime(DateUtils.format(DateUtils.yyyyMMddHHmmss2, patrolTaskExecRecord.getPlanStartTime()));
                } else {
                    taskState.setPlanStartTime("");
                }

                if (ii == 0) {
                    taskState.setStartTime(DateUtils.format(DateUtils.yyyyMMddHHmmss2, new Date()));
                } else {
                    taskState.setStartTime("");
                }

                taskState.setTaskCode(patrolTaskExecRecord.getTaskCode());
                taskState.setTaskEstimatedTime(patrolTaskExecRecord.getTaskEstimatedTime());
                taskState.setTaskName(patrolTaskExecRecord.getTaskName());
                taskState.setTaskPatrolledId(patrolTaskExecRecord.getTaskPatrolId().split(StringUtils.UNDERLINE)[1] + "_" + patrolTaskExecRecord.getTaskPatrolId().split(StringUtils.UNDERLINE)[2]);
                taskState.setTaskProgress(taskProgress);
                taskState.setTaskState(taskExecRecord.getTaskState());
                taskState.setCode(taskExecRecord.getDevNo());
                taskStates.add(taskState);
                taskState.setPatrolType("2");
                taskStateData.setItems(taskStates);
                obj41 = JSONArray.toJSON(taskStateData);

                try {
                    log.info("[EXEC] UPDATE PATROL STATE START, CALL startThreadGetInfo type=41 json={} ", obj41.toString());
                    startThreadGetInfo(obj41.toString(), "41");
                    log.info("[EXEC] UPDATE PATROL STATE END type=41");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                taskExecRecord.setTaskProgress(this.decimalFormatNum(ii, patrolTaskInfoListSize));
                log.info("[EXEC] progress={}, taskName={}, taskCode={}, taskPatrolledId={}", taskExecRecord.getTaskProgress(), taskExecRecord.getTaskName(), taskExecRecord.getTaskCode(), taskExecRecord.getTaskPatrolId());
                try {
                    this.taskExecClient.updatePatrolTaskExecRecord(taskExecRecord);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                taskStateData = new TaskStateData();
                taskStateData.setType("41");
                taskStateData.setReceiveCode("");
                taskStateData.setSendCode("");
                taskStates = new ArrayList();
                taskState = new TaskState();
                taskState.setDescription("");
                if (patrolTaskExecRecord.getPlanStartTime() != null) {
                    taskState.setPlanStartTime(DateUtils.format(DateUtils.yyyyMMddHHmmss2, patrolTaskExecRecord.getPlanStartTime()));
                } else {
                    taskState.setPlanStartTime("");
                }

                if (ii == 0) {
                    taskState.setStartTime(DateUtils.format(DateUtils.yyyyMMddHHmmss2, new Date()));
                } else {
                    taskState.setStartTime("");
                }

                taskState.setTaskCode(patrolTaskExecRecord.getTaskCode());
                taskState.setTaskEstimatedTime(patrolTaskExecRecord.getTaskEstimatedTime());
                taskState.setTaskName(patrolTaskExecRecord.getTaskName());
                taskState.setTaskPatrolledId(patrolTaskExecRecord.getTaskPatrolId().split(StringUtils.UNDERLINE)[1] + "_" + patrolTaskExecRecord.getTaskPatrolId().split(StringUtils.UNDERLINE)[2]);
                taskState.setTaskProgress(taskProgress);
                taskState.setTaskState(taskExecRecord.getTaskState());
                taskState.setCode(taskExecRecord.getDevNo());
                taskStates.add(taskState);
                taskState.setPatrolType("2");
                taskStateData.setItems(taskStates);
                obj41 = JSONArray.toJSON(taskStateData);

                try {
                    log.info("[EXEC] 2 UPDATE PATROL STATE START, CALL startThreadGetInfo type=41 json={} ", obj41.toString());
                    this.startThreadGetInfo(obj41.toString(), "41");
                    log.info("[EXEC] 2 UPDATE PATROL STATE END type=41");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } else {
            taskExecRecord.setEndTime(new Date());
            taskExecRecord.setTaskState("1");
            taskExecRecord.setTaskProgress(this.decimalFormatNum(ii, patrolTaskInfoListSize));
            taskExecClient.updatePatrolTaskExecRecord(taskExecRecord);
            log.info("[EXEC] 3 progress={} ,taskName={}, taskCode={}, taskPatrolledId={}", taskExecRecord.getTaskProgress(), taskExecRecord.getTaskName(), taskExecRecord.getTaskCode(), taskExecRecord.getTaskPatrolId());
            taskStateData = new TaskStateData();
            taskStateData.setType("41");
            taskStateData.setReceiveCode("");
            taskStateData.setSendCode("");
            taskStates = new ArrayList<>();
            taskState = new TaskState();
            taskState.setDescription("");
            if (patrolTaskExecRecord.getPlanStartTime() != null) {
                taskState.setPlanStartTime(DateUtils.format(DateUtils.yyyyMMddHHmmss2, patrolTaskExecRecord.getPlanStartTime()));
            } else {
                taskState.setPlanStartTime("");
            }

            if (ii == 0) {
                taskState.setStartTime(DateUtils.format(DateUtils.yyyyMMddHHmmss2, new Date()));
            } else {
                taskState.setStartTime("");
            }

            taskState.setTaskCode(patrolTaskExecRecord.getTaskCode());
            taskState.setTaskEstimatedTime(patrolTaskExecRecord.getTaskEstimatedTime());
            taskState.setTaskName(patrolTaskExecRecord.getTaskName());
            taskState.setTaskPatrolledId(patrolTaskExecRecord.getTaskPatrolId().split(StringUtils.UNDERLINE)[1] + "_" + patrolTaskExecRecord.getTaskPatrolId().split(StringUtils.UNDERLINE)[2]);
            taskState.setTaskProgress(taskProgress);
            taskState.setTaskState("1");
            taskState.setCode(taskExecRecord.getDevNo());
            taskStates.add(taskState);
            taskState.setPatrolType("2");
            taskStateData.setItems(taskStates);
            obj41 = JSONArray.toJSON(taskStateData);

            try {
                log.info("[EXEC] 3 UPDATE PATROL STATE START, CALL startThreadGetInfo type=41 json={} ", obj41.toString());
                this.startThreadGetInfo(obj41.toString(), "41");
                log.info("[EXEC] 3 UPDATE PATROL STATE END type=41");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return taskExecRecord;
    }

    private void startThreadGetInfo(final Object obj, final String type) {
        executor.submit(() -> {
            PatrolTaskExecuteSchedulerController.this.patrolResultController.getInfo(type, obj.toString());
        });
    }

    private void videotapeRecordStop(StringBuffer filePaths, Stream stream, String code, String basePath, Long patrolpointId, String devNo) {
        try {
            log.info("[EXEC] VIDEO RECORD STOP /api/v1/record/stop?streamid={}, code={} ", stream.getStreamId(), code);
            String jsonStr = HttpClientUtil.getHttpResultJson(this.liveSIPB_URL + "/api/v1/record/stop?streamid=" + stream.getStreamId() + "&code=" + code);
            log.info("[EXEC] VIDEO RECORD STOP, json /api/v1/record/stop?jsonStr={} ", jsonStr);
            JSONObject jsonObject = JSON.parseObject(jsonStr);
            RecordData recordData = JSON.toJavaObject(jsonObject, RecordData.class);
            String path = recordData.getRecordList().get(0).getDownloadURL();
            path = this.saveFile(path, patrolpointId + "_" + devNo + "_" + path.split(StringUtils.SLASH)[path.split(StringUtils.SLASH).length - 1].split(StringUtils.UNDERLINE)[2], basePath + "Video");
            filePaths.append(path).append(StringUtils.COMMA);
            log.info("[EXEC] VIDEO SAVE PATH path={} ", path);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private String decimalFormatNum(int current, int all) {
        DecimalFormat nf = new DecimalFormat(StringUtils.HASHTAG);
        nf.setMaximumIntegerDigits(3);
        float decimalFormatNum = (float) (current + 1) / (float) all;
        return nf.format(decimalFormatNum * 100.0F);
    }

    private void algMapping(PatrolResult patrolResult, DBPatrolPoint dbPatrolPoint, List<SysDictData> sysDictDataList) {
        if (dbPatrolPoint != null) {
            boolean exist = false;
            if (dbPatrolPoint.getAlgSubtypeIds() != null && !dbPatrolPoint.getAlgSubtypeIds().isEmpty()) {
                String[] ids = dbPatrolPoint.getAlgSubtypeIds().split(StringUtils.COMMA);

                for (String id : ids) {
                    for (SysDictData sysDictData : sysDictDataList) {
                        if (Long.parseLong(id) == sysDictData.getDictSort()) {
                            if (!exist && sysDictData.getRemark() == null) {
                                patrolResult.setRecognitionType(sysDictData.getDictValue());
                                log.info("[EXEC] Algorithm Recognition Type Relation Mismatch recognitionType: {}", patrolResult.getRecognitionType());
                            } else if (!exist) {
                                patrolResult.setRecognitionType(sysDictData.getRemark());
                                exist = true;
                            }
                        }
                    }
                }
            }
        }

    }

    public String saveFile(String url, String fileName, String fileTypeDir) {
        DataMsg dataMsg = new DataMsg();

        try {
            String[] split = url.split("\\?");
            SftpUploadEntity sftpUploadEntity = new SftpUploadEntity(HttpClientUtils.getStream(split[0], split[split.length - 1]));
            sftpUploadEntity.setFilePath(fileTypeDir);
            sftpUploadEntity.setFileName(fileName.split(StringUtils.HASHTAG)[0]);
            return this.sftpClient.upload(sftpUploadEntity);
        } catch (Exception e) {
            e.printStackTrace();
            return dataMsg.getFilePath() + "/" + fileName;
        }
    }
}
