package com.zc.business.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.system.service.ISysConfigService;
import com.zc.business.constant.DeviceTypeConstants;
import com.zc.business.domain.DcDevice;
import com.zc.business.enums.CameraDirectionEnum;
import com.zc.business.enums.LaneDirectionEnum;
import com.zc.business.enums.UniversalEnum;
import com.zc.business.service.IDcDeviceService;
import com.zc.business.service.IMiddleDatabaseService;
import com.zc.common.core.httpclient.OkHttp;
import com.zc.common.core.httpclient.exception.HttpException;
import com.zc.common.core.httpclient.request.RequestParams;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * License
 *
 * @author Athena-xiepufeng
 */
@Api(tags = "视频接口")
@RestController
@RequestMapping("/video")
public class VideoController extends BaseController {

//    private static final String ID = "admin";
//    private static final String SECRET = "21232f297a57a5a743894a0e4a801fc3";
//    private static final String CALLBACKURL = "http://10.0.81.209/broadcast/logIn";
//    private final static String TOKENKEY = "tokenRoadTestBroadcastPlatform";


//    private static final String USERNAME = "jhgskj";
//    private static final String PASSWORD = "jhgskj@2023";
    private static String TOKEN;

//    private final static String URL = HTTP + "10.166.147.60:9021";

    public static final Integer UNAUTHORIZED = UniversalEnum.FOUR_HUNDRED_AND_ONE.getNumber();


    public static final Integer ERROR = UniversalEnum.FIVE_HUNDRED.getNumber();

    @Value("${iot.address}")
    private String iotAddress;

    @Resource
    private RedisCache redisCache;
    @Resource
    private IDcDeviceService iDcDeviceService;

    @Resource
    private IMiddleDatabaseService middleDatabaseService;
    @Autowired
    private ISysConfigService configService;

    // 组织机构id
//    private final static String CAM_DEPT_ID = "1301730";

    /**
     * 同步物联网ID。
     * 该方法用于查询未同步物联网ID的摄像头设备信息,并从外部API获取这些设备的详细信息,然后更新它们的物联网ID。
     * 该过程主要涉及查询未初始化物联网ID的摄像头、构建设备IP与设备映射、从API获取设备详细信息以及批量更新设备的物联网ID。
     */
    @ApiOperation("同步监控摄像设备ID")
    @PatchMapping(value = "/sync/id")
    public AjaxResult synchronizeIotIds() {
        // 查询未同步物联ID的摄像头设备信息
        LambdaQueryWrapper<DcDevice> query = new LambdaQueryWrapper<>();
        query.eq(DcDevice::getDeviceType, DeviceTypeConstants.CAMERA)
                .isNull(DcDevice::getIotDeviceId);

        List<DcDevice> uninitializedCameras = iDcDeviceService.list(query);

        if (uninitializedCameras.isEmpty()) {
            return AjaxResult.success(UniversalEnum.NO_DEVICES_NEED_TO_BE_SYNCHRONIZED.getValue()); // 若无待同步设备,则直接返回
        }

        // 将未初始化的摄像头列表转换为Map,以设备的桩号、方向和子类型拼接作为键,设备本身作为值
        Map<String, DcDevice> cameraMap = new HashMap<>();
        uninitializedCameras.forEach(dcDevice -> {
            String otherConfig = dcDevice.getOtherConfig();
            if (otherConfig == null) return;
            JSONObject otherConfigJson = JSONObject.parseObject(otherConfig);
            String ptzCtrl = otherConfigJson.getString("ptzCtrl");
            String key = dcDevice.getStakeMark() + UniversalEnum.VERTICAL_LINE.getValue() + dcDevice.getDirection() + UniversalEnum.VERTICAL_LINE.getValue() + ptzCtrl;
            cameraMap.put(key, dcDevice);
        });

        try {
            // 获取部门下的摄像头详细信息
            JSONObject camApiResponse = getCamByDept();

            if (camApiResponse == null || !camApiResponse.containsKey("data")) {
                return AjaxResult.error(UniversalEnum.FAILED_TO_OBTAIN_CAMERA_INFORMATION_BASED_ON_THE_ORGANIZATION.getValue()); // 如果获取信息失败或不含有效数据,直接返回
            }

            JSONArray camDataArray = camApiResponse.getJSONArray("data");

            // 遍历并更新具备匹配IP的摄像头设备物联ID
            List<DcDevice> devicesToUpdate = new ArrayList<>();
            camDataArray.forEach(item -> {
                JSONObject cameraInfo = (JSONObject) item;
                // 桩号
                String pileNum = cameraInfo.getString("pileNum");
                // 方向
                Integer camOrientation = cameraInfo.getInteger("camOrientation");
                LaneDirectionEnum laneDirectionEnum = CameraDirectionEnum.fromCode(camOrientation).toLaneDirection();

                // 是否有云台控制 0 有(球机) 1 ⽆(枪机)
                String ptzCtrl = cameraInfo.getString("ptzCtrl");

                String key = pileNum + UniversalEnum.VERTICAL_LINE.getValue() + laneDirectionEnum.getValue() + UniversalEnum.VERTICAL_LINE.getValue() + ptzCtrl;

                if (cameraMap.containsKey(key)) {
                    DcDevice dcDevice = cameraMap.get(key);
                    dcDevice.setIotDeviceId(cameraInfo.getString("camId"));
                    devicesToUpdate.add(dcDevice);
                }
            });

            // 批量更新摄像头设备的物联ID
            iDcDeviceService.updateBatchById(devicesToUpdate);
            return AjaxResult.success(UniversalEnum.SYNCHRONIZING_THE_IOT_ID_SUCCEEDED.getValue(), devicesToUpdate);
        } catch (Exception e) {
            logger.error(UniversalEnum.FAILED_TO_OBTAIN_CAMERA_INFORMATION_PROCEDURE.getValue(), e);
        }

        return AjaxResult.error(UniversalEnum.DESCRIPTION_FAILED_TO_SYNCHRONIZE_THE_IOT_ID.getValue());
    }

    /**
     * 查询附近相机
     */
    @ApiOperation("查询附近相机")
    @GetMapping(value = "/nearCamListDistance")
    public JSONObject nearCamListDistance(@ApiParam(value = "纬度", name = "devLat", required = true) String devLat,
                                          @ApiParam(value = "经度", name = "devLon", required = true) String devLon) throws HttpException, IOException {

        JSONObject cameraInfo = JSONObject.parseObject(configService.selectConfigByKey("dc.cameraInfo"));

        // 1000 米
        String distance = UniversalEnum.THOUSAND.getValue();

        OkHttp okHttp = new OkHttp();

        RequestParams requestParams = new RequestParams();
        requestParams.put("devLat", devLat);
        requestParams.put("devLon", devLon);
        requestParams.put("distance", distance);

        Map<String, String> header = new HashMap<>();

        if (VideoController.TOKEN == null) {
            getToken();
        }

        header.put("Authorization", TOKEN);

        Response response // 请求响应
                = okHttp
                .headers(header)
                .url(cameraInfo.getString("URL") + UniversalEnum.SEARCH_NEARBY_CAMERAS.getValue()) // 请求地址
                .data(requestParams) // 请求参数
                .get(); // 请求方法

        return getJsonResult(response,okHttp);

    }

    /***
     * 根据相机中的设备状态,修改数据平台设备的设备状态
     */
    @Scheduled(cron = "0 0/5 * * * ?")
    public void updateDeviceState() throws HttpException, IOException {
        logger.debug("开始执行:同步数据平台视频设备设备的设备状态!!");
        JSONObject cameraData = synchronizeCameraData();
        if (cameraData.get("code").equals(UniversalEnum.TWO_HUNDRED.getNumber())) {
            JSONObject data = JSONObject.parseObject(JSONArray.parseArray(cameraData.get("data").toString()).get(UniversalEnum.ZERO.getNumber()).toString());
            JSONObject dataChildren = JSONObject.parseObject(JSONArray.parseArray(data.get("children").toString()).get(UniversalEnum.ZERO.getNumber()).toString());
            JSONObject qiLuGaoSu = JSONObject.parseObject(JSONArray.parseArray(dataChildren.get("children").toString()).get(UniversalEnum.ZERO.getNumber()).toString());
            JSONObject jiHeYunGuan = JSONObject.parseObject(JSONArray.parseArray(qiLuGaoSu.get("children").toString()).get(UniversalEnum.ZERO.getNumber()).toString());
            JSONArray jiHeYunGuanG35 = JSONArray.parseArray(jiHeYunGuan.get("children").toString());
            List<DcDevice> list = new ArrayList<>();
            for (Object json : jiHeYunGuanG35) {
                JSONObject item = JSONObject.parseObject(json.toString());
                DcDevice device = new DcDevice();
                if (item.get("status").equals(UniversalEnum.ZERO.getValue())) {
                    device.setDeviceState(UniversalEnum.ONE.getValue());
                } else {
                    device.setDeviceState(UniversalEnum.ZERO.getValue());
                }
                device.setIotDeviceId(item.get("camId").toString());
                list.add(device);
            }

            iDcDeviceService.batchUpdate(list);

            //更新中间库的设备状态
            middleDatabaseService.updateMiddleDatabaseDeviceByList(list);

            logger.debug("执行:同步数据平台视频设备的设备状态成功!!");

        }
        logger.debug("开始执行:同步物联平台设备的设备状态!!");
        AjaxResult ajaxResult = synchronizingDeviceStatus();
        if (ajaxResult.get("code").equals(UniversalEnum.TWO_HUNDRED.getNumber())) {
            JSONArray data = (JSONArray) ajaxResult.get("data");
            ArrayList<DcDevice> dcDevices = new ArrayList<>();
            for (Object datum : data) {
                DcDevice dcDevice = new DcDevice();
                JSONObject datum1 = (JSONObject) datum;
                dcDevice.setIotDeviceId(datum1.getString("id"));
                dcDevice.setDeviceState(Objects.equals(datum1.getString("deviceState"), UniversalEnum.ON_LINE.getValue()) ? UniversalEnum.ONE.getValue() : UniversalEnum.ZERO.getValue());
                dcDevices.add(dcDevice);
            }
            iDcDeviceService.batchUpdate(dcDevices);

            //更新中间库的设备状态
            middleDatabaseService.updateMiddleDatabaseDeviceByList(dcDevices);

            logger.debug("执行:同步物联平台设备的设备状态成功!!");

        }
        logger.debug("开始执行:同步广播设备的设备状态!!");
        AjaxResult ajaxResultBroadcast = synchronizingBroadcastDeviceStatus();
        if (Objects.equals(String.valueOf(ajaxResultBroadcast.get("retCode")), UniversalEnum.ZERO.getValue())) {
            JSONArray data = (JSONArray) ajaxResultBroadcast.get("termList");
            for (Object datum : data) {
                DcDevice dcDevice = new DcDevice();
                JSONObject datum1 = (JSONObject) datum;
                dcDevice.setIotDeviceId(datum1.getString("termDN"));
                dcDevice.setDeviceState(Objects.equals(datum1.getString("regState"), UniversalEnum.ON_LINE.getValue()) ? UniversalEnum.ONE.getValue() : UniversalEnum.ZERO.getValue());
                LambdaQueryWrapper<DcDevice> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(DcDevice::getIotDeviceId, dcDevice.getIotDeviceId());
                iDcDeviceService.update(dcDevice, queryWrapper);

                //更新中间库的设备状态
                middleDatabaseService.updateMiddleDatabaseDevice(dcDevice);
            }
            logger.debug("执行:同步广播设备的设备状态成功!!");

        }

    }

    private AjaxResult synchronizingBroadcastDeviceStatus() throws HttpException, IOException {
        OkHttp okHttp = new OkHttp();
        RequestParams requestParams = new RequestParams();
        JSONObject broadcast = JSONObject.parseObject(configService.selectConfigByKey("broadcast"));

        String tokenRoadTestBroadcastPlatform = redisCache.getCacheObject(broadcast.getString("TOKENKEY"));
        if (tokenRoadTestBroadcastPlatform == null) {
            tokenRoadTestBroadcastPlatform = getBroadcastToken();
        }
        requestParams.put("zoneId", UniversalEnum.ASTERISK_ASTERISK_SIX_THOUSAND_AND_ONE.getValue());
        requestParams.put("termDN", UniversalEnum.EMPTY_STRING.getValue());
        Response response // 请求响应
                = okHttp
                .headers(new HashMap<>())
                .data(requestParams) // 请求参数
                .url(broadcast.getString("URL") + UniversalEnum.QUERY_TERM_DO_ACCESS_TOKEN.getValue() + tokenRoadTestBroadcastPlatform) // 请求地址
                .post(); // 请求方法
        return JSON.parseObject(response.body().string(), AjaxResult.class);
    }

    public String getBroadcastToken() throws HttpException, IOException {

        JSONObject broadcast = JSONObject.parseObject(configService.selectConfigByKey("broadcast"));

        OkHttp okHttp = new OkHttp();
        RequestParams requestParams = new RequestParams();
        requestParams.put("id", broadcast.getString("ID"));
        requestParams.put("secret", broadcast.getString("SECRET"));
        requestParams.put("callbackUrl", broadcast.getString("CALLBACKURL"));
        Response response // 请求响应
                = okHttp
                .headers(new HashMap<>())
                .url(broadcast.getString("URL") + UniversalEnum.LOGIN_DO.getValue()) // 请求地址
                .data(requestParams) // 请求参数
                .post(); // 请求方法
        if (response.body() != null) {
            String accessToken = JSONObject.parseObject(response.body().string()).getString("accessToken");
            redisCache.setCacheObject(broadcast.getString("TOKENKEY"), accessToken, UniversalEnum.FIVE.getNumber(), TimeUnit.MINUTES);
            return accessToken;
        }
        return null;
    }


    private AjaxResult synchronizingDeviceStatus() throws HttpException, IOException {

        OkHttp okHttp = new OkHttp();

        Response response // 请求响应
                = okHttp
                .url(iotAddress + UniversalEnum.INTERNET_OF_THINGS_DEVICE_QUERY.getValue()) // 请求地址
                .get(); // 请求方法
        return JSON.parseObject(response.body().string(), AjaxResult.class);
    }


    /**
     * 查询同步相机数据
     */
    public JSONObject synchronizeCameraData() throws HttpException, IOException {
        JSONObject cameraInfo = JSONObject.parseObject(configService.selectConfigByKey("dc.cameraInfo"));

        OkHttp okHttp = new OkHttp();

        RequestParams requestParams = new RequestParams();

        Map<String, String> header = new HashMap<>();

        if (VideoController.TOKEN == null) {
            getToken();
        }

        header.put("Authorization", TOKEN);

        Response response // 请求响应
                = okHttp
                .headers(header)
                .url(cameraInfo.getString("URL") + UniversalEnum.EXAMPLE_QUERY_SYNC_CAMERA_DATA.getValue()) // 请求地址
                .data(requestParams) // 请求参数
                .get(); // 请求方法

        return getJsonResult(response,okHttp);

    }

    /**
     * 根据桩号查询附近相机
     */
    @ApiOperation("根据桩号查询附近相机")
    @GetMapping(value = "/nearCamListPileNum")
    public Object nearCamListPileNum(@ApiParam(value = "桩号", name = "pileNum", required = true) String pileNum) throws HttpException, IOException {

        // 获取济菏运管中心相机信息
        JSONObject camInfo = getCamByDept();

        if (!camInfo.containsKey("data")) {
            return camInfo;
        }

        JSONArray camData = camInfo.getJSONArray("data");

        List<Object> resultList = new ArrayList<>();

        camData.forEach(item -> {
            JSONObject jsonObject = (JSONObject) item;
            if (isNearbyPileNum(pileNum, jsonObject.getString("pileNum"))) {
                resultList.add(item);
            }
        });

        return AjaxResult.success(resultList);
    }

    /**
     * 根据桩号查询上下行相机
     */
    @ApiOperation("根据桩号查询上下行相机")
    @GetMapping(value = "/nearCamPileNum")
    public Object nearCamPileNum(@ApiParam(value = "桩号", name = "pileNum", required = true) String pileNum) throws HttpException, IOException {

        // 获取济菏运管中心相机信息
        /*JSONObject camInfo = getCamByDept("1301730");

        if (!camInfo.containsKey("data")) {
            return camInfo;
        }

        List<Map<String,Object>> datalist = (List<Map<String, Object>>) camInfo.get("data");

        Integer pileNumDistance = pileNumTransformMetre(pileNum);
        Map<String,Object> result = new HashMap<>();

        //上行列表(包含双向)
        List<Map<String,Object>> upCameraList = datalist.stream()
                .map(item->{
                    item.put("distance",Math.abs(pileNumTransformMetre(item.get("pileNum").toString()) - pileNumDistance));
                    return item;
                })
                .filter(item ->
                        ("0".equals(item.get("camOrientation")) || "2".equals(item.get("camOrientation")))
                                && Integer.parseInt(item.get("distance").toString()) < 2000)
                .sorted(comparing(item -> Integer.parseInt(item.get("distance").toString())))
                .collect(Collectors.toList());
        result.put("upCamera",upCameraList);


        //下行列表
        List<Map<String,Object>> downCameraList = datalist.stream()
                .map(item->{
                    item.put("distance",Math.abs(pileNumTransformMetre(item.get("pileNum").toString()) - pileNumDistance));
                    return item;
                })
                .filter(item -> "1".equals(item.get("camOrientation")) && Integer.parseInt(item.get("distance").toString()) < 2000)
                .sorted(comparing(item -> Integer.parseInt(item.get("distance").toString())))
                .collect(Collectors.toList());
        result.put("downCamera",downCameraList);*/

        Map<String,Object> result = new HashMap<>();

        Integer pileNumDistance = pileNumTransformMetre(pileNum);
        String startMileage = String.valueOf(pileNumDistance - UniversalEnum.TWO_THOUSAND.getNumber());
        String endMileage = String.valueOf(pileNumDistance + UniversalEnum.TWO_THOUSAND.getNumber());
        List<DcDevice> upCameraList = iDcDeviceService.selectNearCamPile(UniversalEnum.ONE.getValue(), startMileage,endMileage);
        List<DcDevice> downCameraList = iDcDeviceService.selectNearCamPile(UniversalEnum.THREE.getValue(),startMileage,endMileage);
        result.put("upCamera",upCameraList);
        result.put("downCamera",downCameraList);

        return AjaxResult.success(result);
    }

    /**
     * 获取视频流信息
     */
    @ApiOperation("获取视频流信息")
    @GetMapping(value = "/externalVideoStreaming")
    public JSONObject externalVideoStreaming(@ApiParam(value = "摄像头标识", name = "camId", required = true) String camId) {
        JSONObject cameraInfo = JSONObject.parseObject(configService.selectConfigByKey("dc.cameraInfo"));

        JSONObject jsonResult = null;

        OkHttp okHttp = new OkHttp();

        RequestParams requestParams = new RequestParams();
        requestParams.put("type", UniversalEnum.ONE.getValue());
        requestParams.put("camId", camId);

        try {
            Map<String, String> header = new HashMap<>();

            if (VideoController.TOKEN == null) {
                getToken();
            }

            header.put("Authorization", TOKEN);

            Response response // 请求响应
                    = okHttp
                    .headers(header)
                    .url(cameraInfo.getString("URL") + UniversalEnum.GET_VIDEO_STREAM_INFORMATION.getValue()) // 请求地址
                    .data(requestParams) // 请求参数
                    .post(); // 请求方法

            if (response.body() != null) {
                jsonResult = JSONObject.parseObject(response.body().string());

                if (jsonResult.containsKey("code")) {
                    if (HttpStatus.SUCCESS == jsonResult.getInteger("code")) {
                        Map<String,Object> data = jsonResult.getJSONObject("data");
                        String liveUrl = data.get("liveUrl").toString();
                        liveUrl = configService.selectConfigByKey("dc.cameraUrl") + liveUrl.substring(UniversalEnum.SEVEN.getNumber());
                        data.put("liveUrl",liveUrl);
                        jsonResult.put("data",data);
                    } else if (UNAUTHORIZED.equals(jsonResult.getInteger("code"))) {
                        getToken();
                        okHttp.post();
                        if (response.body() != null) {
                            jsonResult = JSONObject.parseObject(response.body().string());
                            if (HttpStatus.SUCCESS == jsonResult.getInteger("code")) {
                                Map<String,Object> data = jsonResult.getJSONObject("data");
                                String liveUrl = data.get("liveUrl").toString();
                                liveUrl = configService.selectConfigByKey("cameraUrl") + liveUrl.substring(UniversalEnum.SEVEN.getNumber());
                                data.put("liveUrl",liveUrl);
                                jsonResult.put("data",data);
                            }
                        }
                    }
                }
            }
        }catch (Exception e) {
            jsonResult = new JSONObject();
            jsonResult.put("code",200);
            jsonResult.put("data", new JSONObject());
            jsonResult.put("msg","摄像机连接失败");
        }


        return jsonResult;
    }


    /**
     * 设置预置位
     */
    @ApiOperation("设置预置位")
    @GetMapping(value = "/setPresetBit")
    public JSONObject setPresetBit(@ApiParam(value = "相机id", name = "camId", required = true) String camId,
                                 @ApiParam(value = "预置位名称", name = "cmdType", required = true) String presetBitName) throws HttpException, IOException {
        // http://[IP]:[PORT]/preset/addPreset

        DcDevice device = iDcDeviceService.getById(camId);

        JSONObject jsonResult = null;
        OkHttp okHttp = new OkHttp();

        RequestParams requestParams = new RequestParams();
        requestParams.put("camId",device.getIotDeviceId());
        requestParams.put("presetName",presetBitName);

        Map<String, String> header = new HashMap<>();

        if (VideoController.TOKEN == null) {
        }
        getToken();

        header.put("Authorization", TOKEN);

        Response response // 请求响应
                = okHttp
                .headers(header)
                .url(UniversalEnum.HTTP.getValue()+device.getDeviceIp()+UniversalEnum.SET_PRESET_BIT.getValue()) // 请求地址
                .data(requestParams) // 请求参数
                .post(); // 请求方法

        if (response.body() != null) {
            jsonResult = JSONObject.parseObject(response.body().string());

            if (jsonResult.containsKey("code") && UNAUTHORIZED.equals(jsonResult.getInteger("code"))) {
                getToken();
                okHttp.get();
                if (response.body() != null) {
                    jsonResult = JSONObject.parseObject(response.body().string());
                }
            }
        }

        JSONObject otherConfig = JSONObject.parseObject(device.getOtherConfig());

        JSONArray presetBitList = otherConfig.getJSONArray("presetBitList");
        if (presetBitList == null){
            presetBitList = new JSONArray();
        }
        presetBitList.add(jsonResult);

        otherConfig.put("presetBitList",presetBitList);

        device.setOtherConfig(String.valueOf(otherConfig));

        LambdaQueryWrapper<DcDevice> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(DcDevice::getId,device.getId());
        iDcDeviceService.update(device,lambdaQueryWrapper);

        return jsonResult;
    }

    /**
     * 新增预置位
     */
    @ApiOperation("新增预置位")
    @GetMapping(value = "/addPreset")
    public JSONObject addPreset(@ApiParam(value = "相机id", name = "camId", required = true) String camId,
                                @ApiParam(value = "预置位名称", name = "presetName", required = true) String presetName) throws HttpException, IOException {
        JSONObject cameraInfo = JSONObject.parseObject(configService.selectConfigByKey("dc.cameraInfo"));
        OkHttp okHttp = new OkHttp();

        RequestParams requestParams = new RequestParams();
        requestParams.put("camId", camId);
        requestParams.put("presetName", presetName);

        Map<String, String> header = new HashMap<>();

        if (VideoController.TOKEN == null) {
            getToken();
        }

        header.put("Authorization", TOKEN);

        Response response // 请求响应
                = okHttp
                .headers(header)
                .url(cameraInfo.getString("URL") + UniversalEnum.NEW_PRESET_BIT.getValue()) // 请求地址
                .data(requestParams) // 请求参数
                .post(); // 请求方法

        // 新增预置位
        JSONObject addPresetResult = getJsonResult(response, okHttp);
        if (addPresetResult.getInteger("code").equals(UniversalEnum.TWO_HUNDRED.getNumber())) {
            JSONObject data = JSON.parseObject(addPresetResult.get("data").toString());
            return PTZControl(camId, UniversalEnum.EIGHT.getValue(), data.getString("presetId"));
        }else {
            JSONObject error = new JSONObject();
            error.put("code",UniversalEnum.FIVE_HUNDRED.getNumber());
            error.put("msg",UniversalEnum.OPERATION_FAILURE.getValue());
            return error;
        }

    }

    /**
     * 查询预置位列表
     */
    @ApiOperation("查询预置位列表")
    @GetMapping(value = "/presetList")
    public JSONObject presetList(@ApiParam(value = "相机id", name = "camId", required = true) String camId) throws HttpException, IOException {
        JSONObject cameraInfo = JSONObject.parseObject(configService.selectConfigByKey("dc.cameraInfo"));

        OkHttp okHttp = new OkHttp();

        RequestParams requestParams = new RequestParams();
        requestParams.put("camId", camId);

        Map<String, String> header = new HashMap<>();

        if (VideoController.TOKEN == null) {
            getToken();
        }

        header.put("Authorization", TOKEN);

        Response response // 请求响应
                = okHttp
                .headers(header)
                .url(cameraInfo.getString("URL") + UniversalEnum.EXAMPLE_QUERY_THE_PRESET_BIT_LIST.getValue()) // 请求地址
                .data(requestParams) // 请求参数
                .get(); // 请求方法

        return getJsonResult(response,okHttp);
    }
    /**
     * 返回结果处理
     */
    public JSONObject getJsonResult(Response response, OkHttp okHttp) throws HttpException, IOException {
        JSONObject jsonResult = null;
        if (response.body() != null) {
            jsonResult = JSONObject.parseObject(response.body().string());

            if (jsonResult.containsKey("code") && UNAUTHORIZED.equals(jsonResult.getInteger("code"))) {
                getToken();
                okHttp.get();
                if (response.body() != null) {
                    jsonResult = JSONObject.parseObject(response.body().string());
                }
            }
        }
        return jsonResult;
    }


    /**
     * 云平台控制
     */
    @ApiOperation("云平台控制")
    @GetMapping(value = "/PTZControl")
    public JSONObject PTZControl(@ApiParam(value = "相机id", name = "camId", required = true) String camId,
                                 @ApiParam(value = "指令类型", name = "cmdType", required = true) String cmdType,
                                 @ApiParam(value = "速度", name = "speed", required = true) String speed) throws HttpException, IOException {
        JSONObject cameraInfo = JSONObject.parseObject(configService.selectConfigByKey("dc.cameraInfo"));

        OkHttp okHttp = new OkHttp();

        RequestParams requestParams = new RequestParams();
        requestParams.put("msgType", UniversalEnum.THREE.getValue());
        requestParams.put("camId", camId);
        requestParams.put("cmdType", cmdType);
        requestParams.put("speed", speed);

        Map<String, String> header = new HashMap<>();

        if (VideoController.TOKEN == null) {
            getToken();
        }

        header.put("Authorization", TOKEN);

        Response response // 请求响应
                = okHttp
                .headers(header)
                .url(cameraInfo.getString("URL") + UniversalEnum.CLOUD_PLATFORM_CONTROL.getValue()) // 请求地址
                .data(requestParams) // 请求参数
                .get(); // 请求方法

        return getJsonResult(response,okHttp);
    }
    /**
     * 获取视频流信息
     * camId		string	相机编号
     * startTime		Date	相机开始时间 yyyy-MM-dd HH:mm:ss
     * duration	是Int	下载时长/分钟 不能超过五分钟
     */
    @ApiOperation("下载相机录像")
    @GetMapping(value = "/downloadCameraVideo")
    public JSONObject downloadCameraVideo( String camId,String startTime,int duration) throws HttpException, IOException {
        JSONObject cameraInfo = JSONObject.parseObject(configService.selectConfigByKey("dc.cameraInfo"));


        OkHttp okHttp = new OkHttp();

        RequestParams requestParams = new RequestParams();
        requestParams.put("camId", camId);
        requestParams.put("startTime", startTime);
        requestParams.put("duration", duration);

        Map<String, String> header = new HashMap<>();

        if (VideoController.TOKEN == null) {
            getToken();
        }

        header.put("Authorization", TOKEN);

        Response response // 请求响应
                = okHttp
                .headers(header)
                .url(cameraInfo.getString("URL") + UniversalEnum.DOWNLOAD_CAMERA_VIDEO.getValue()) // 请求地址
                .data(requestParams) // 请求参数
                .get(); // 请求方法

        return getJsonResult(response,okHttp);

    }


    public void getToken() throws HttpException, IOException {

        JSONObject cameraInfo = JSONObject.parseObject(configService.selectConfigByKey("dc.cameraInfo"));

        OkHttp okHttp = new OkHttp();

        RequestParams requestParams = new RequestParams();
        requestParams.put("username", cameraInfo.getString("USERNAME"));
        requestParams.put("password", cameraInfo.getString("PASSWORD"));

        Response response // 请求响应
                = okHttp
                .url(cameraInfo.getString("URL") + UniversalEnum.GET_THE_CAMERA_TOKEN.getValue()) // 请求地址
                .data(requestParams) // 请求参数
                .post(); // 请求方法

        if (response.body() != null) {
            JSONObject jsonResult = JSONObject.parseObject(response.body().string());
            if (jsonResult.containsKey("token")) {
                VideoController.TOKEN = jsonResult.getString("token");
            }
        }
    }


    /**
     * 根据组织机构获取摄像机信息
     *
     * @param
     * @return
     */
    public JSONObject getCamByDept() throws HttpException, IOException {
        JSONObject cameraInfo = JSONObject.parseObject(configService.selectConfigByKey("dc.cameraInfo"));

        OkHttp okHttp = new OkHttp();

        RequestParams requestParams = new RequestParams();
        requestParams.put("deptId", cameraInfo.getString("CAM_DEPT_ID"));

        Map<String, String> header = new HashMap<>();

        if (VideoController.TOKEN == null) {
            getToken();
        }

        header.put("Authorization", TOKEN);

        Response response // 请求响应
                = okHttp
                .headers(header)
                .url(cameraInfo.getString("URL") + UniversalEnum.GET_CAMERA_INFORMATION_BY_ORGANIZATION.getValue()) // 请求地址
                .data(requestParams) // 请求参数
                .get(); // 请求方法

        return getJsonResult(response,okHttp);
    }

    /**
     * 判断是否是附近桩号
     *
     * @return
     */
    private boolean isNearbyPileNum(String centralPileNum, String nearbyPileNum) {

        int centralPileNumMetre = pileNumTransformMetre(centralPileNum);
        int nearbyPileNumMetre = pileNumTransformMetre(nearbyPileNum);

        return (nearbyPileNumMetre <= centralPileNumMetre + UniversalEnum.THOUSAND.getNumber()) && (nearbyPileNumMetre >= centralPileNumMetre - UniversalEnum.THOUSAND.getNumber());
    }


    /**
     * 转换转换成米
     *
     * @param pileNum 桩号
     * @return
     */
    private int pileNumTransformMetre(String pileNum) {
        String[] parts = pileNum.split("[+ ]");
        if (parts.length < UniversalEnum.TWO.getNumber()) {
            return UniversalEnum.ZERO.getNumber();
        }
        int kilometer = Integer.parseInt(parts[UniversalEnum.ZERO.getNumber()].substring(UniversalEnum.ONE.getNumber())); // 移除开头的字母
        int meter = Integer.parseInt(parts[UniversalEnum.ONE.getNumber()]);
        return kilometer * UniversalEnum.THOUSAND.getNumber() + meter;
    }

}