package net.northking.cctp.designer.ws.server;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.hzbank.testteam.autotest.dependencies.authDependency.constants.AuthDependencyConstants;
import com.hzbank.testteam.autotest.dependencies.authDependency.dto.TokenValueDTO;
import com.hzbank.testteam.autotest.dependencies.baseDefineDependency.utils.SpringUtil;
import net.northking.cctp.common.enums.FileBusinessTypeEnum;
import net.northking.cctp.common.http.ResultWrapper;
import net.northking.cctp.common.s3.FileUploadException;
import net.northking.cctp.common.s3.NKFile;
import net.northking.cctp.common.s3.SimpleStorageService;
import net.northking.cctp.common.saas.cache.StaticTenantCache;
import net.northking.cctp.common.util.UUIDUtil;
import net.northking.cctp.designer.ws.*;
import net.northking.cctp.designer.ws.client.EngineWsClient;
import net.northking.cctp.designer.ws.client.RobotWsClient;
import net.northking.cctp.designer.ws.feign.CctpPlatformFeignClient;
import net.northking.cctp.designer.ws.feign.DesignerFeignClient;
import net.northking.cctp.designer.ws.mq.MqConstant;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Component
@ServerEndpoint("/pub/recordDebug")
public class FrontDatasWebsocket {

    private static final Logger logger = LoggerFactory.getLogger(FrontDatasWebsocket.class);

    private Session session;

    private static RedisUtil redisUtil;

    private String sessionId;

    private String tenantId;
    private String authorization;
    private Long userId;
    private String deviceId;
    private String token;

    private static SimpleStorageService storageService;


    @Autowired
    public void setStorageService(SimpleStorageService storageService) {
        FrontDatasWebsocket.storageService = storageService;
    }


    @Autowired
    public  void setRedisUtil(RedisUtil redisUtil) {
        FrontDatasWebsocket.redisUtil = redisUtil;
    }


    private static DesignerFeignClient designerFeignClient;

    @Autowired
    public void setDesignerFeignClient(DesignerFeignClient designerFeignClient) {
        FrontDatasWebsocket.designerFeignClient = designerFeignClient;
    }

    private static CctpPlatformFeignClient cctpPlatformFeignClient;

    @Autowired
    public void setCctpPlatformFeignClient(CctpPlatformFeignClient cctpPlatformFeignClient) {
        FrontDatasWebsocket.cctpPlatformFeignClient = cctpPlatformFeignClient;
    }


    private static RabbitTemplate rabbitTemplate;


    @Autowired
    public void setRabbitTemplate(RabbitTemplate rabbitTemplate) {
        FrontDatasWebsocket.rabbitTemplate = rabbitTemplate;
    }

    //默认为一分钟
    private static int release = 60;


    @Value("${pcui.release}")
    public void setRelease(int release) {
        FrontDatasWebsocket.release = release;
    }


    private static String catalogCode = "webElePropFilter";
    @Value("${pcui.catalogCode:webElePropFilter}")
    public void setCatalogCode(String catalogCode) {
        if (org.apache.commons.lang.StringUtils.isNotBlank(catalogCode)){
            FrontDatasWebsocket.catalogCode = catalogCode;
        }

    }

    @OnOpen
    public void onOpen(Session session) {
        //设置传输数据的大小
        session.setMaxTextMessageBufferSize(10 * 1024 *1024);
        session.setMaxBinaryMessageBufferSize(10 * 1024 *1024);
        this.session = session;
        Map<String, List<String>> requestParameterMap = session.getRequestParameterMap();
        //通道已接通
        logger.info("前端websocket通道已接通,参数:{}", requestParameterMap);
        List<String> authentication = requestParameterMap.get("authorization");
        if (authentication == null || authentication.size() == 0) {
            //未携带鉴权authentication,直接关闭并且添加原因
            this.optClose("未携带authorization" + InstructSetMsg.sit);
        } else {
            List<String> sessionIds = requestParameterMap.get("sessionId");
            if (sessionIds == null || sessionIds.size() == 0){
                //未携带sessionId
                this.optClose("未携带sessionId" + InstructSetMsg.sit);
                return;
            }
            //鉴权是否为有效登录
            this.authorization = authentication.get(0);
            RedissonClient redisson = SpringUtil.getBean(RedissonClient.class);
            RBucket<TokenValueDTO> tokenValueDTORBucket = redisson.getBucket(AuthDependencyConstants.TOKEN_PREFIX + this.authorization);
            TokenValueDTO tokenValueDTO = tokenValueDTORBucket.get();
            if (tokenValueDTO == null ) {
                try {
                    this.session.close();
                } catch (IOException e) {
                    this.optClose("用户未登录" + InstructSetMsg.sit);
                }
                return;
            }
            this.userId = tokenValueDTO.getUser().getId();
            this.tenantId = StaticTenantCache.getDefaultTenantId();
            //如果为有效登录查询redis数据是否有
            Object o = redisUtil.get(sessionIds.get(0));
            if (null != o){
                //移除之前的数据
                redisUtil.remove(sessionIds.get(0));
                //发送redis中的引擎的数据给前端
                this.sendMessage(o.toString());
            }

            //因为多结点因为需要将与前端的连接状态同步到redis
            redisUtil.set(WsUtils.frontWsStateKey + sessionIds.get(0),"1");

            //判断该链接是否正在连接机器人和引擎
            Object enter = redisUtil.get(WsUtils.redisEnterKey + sessionIds.get(0));
            //还需要判断是否为前端断线重新连接
            WsManyWaysBo wsManyWaysBo = WsUtils.sessionMap.get(sessionIds.get(0));
            if (wsManyWaysBo != null){
                //则为前端断线重连,需要清除原始map中的数据和断开之前和前端的连接
                FrontDatasWebsocket frontDatasWebsocket = wsManyWaysBo.getFrontDatasWebsocket();
                frontDatasWebsocket.optClose("已用新连接,断开旧连接" + InstructSetMsg.sit);
            }

            //添加session管理map
            WsManyWaysBo bo = new WsManyWaysBo();
            bo.setSessionId(sessionIds.get(0));
            this.sessionId = sessionIds.get(0);
            bo.setFrontDatasWebsocket(this);
            WsUtils.sessionMap.put(sessionIds.get(0), bo);

            //需要再重新连接
            if (enter != null){
                //重新连接机器人和引擎
                JSONObject jsonObject = JSONObject.parseObject(enter.toString());
                this.deviceEnter(jsonObject);
                //需要直接转发给引擎
                this.sendEngineMsg(jsonObject,enter.toString());
            }

            logger.info("当前map存储的ws大小:{}",WsUtils.sessionMap.size());
            logger.info("当前状态map存储的大小:{}",WsUtils.connectStatus.size());
            logger.info("当前线程任务map存储的大小:{}",WsUtils.scheduledFutures.size());
        }

    }

    @OnMessage
    public void onMessage(String message) {
        if (!StringUtils.isEmpty(message)) {
            if (InstructSetMsg.ping.equals(message)) {
                //说明是前端发送的心跳,前端回复pong
                this.sendMessage(InstructSetMsg.pong);
            } else {
                JSONObject jsonObject = JSONObject.parseObject(message);
                //接收到参数
                logger.info("接受前端websocket参数:{}", message);
                //做消息转发,判断是发送给机器人还是执行引擎
                String cmd = jsonObject.getString(InstructSetMsg.cmd);
                if (InstructSetTransetionEnum.START_DEBUG.getFrontCode().equals(cmd) || InstructSetTransetionEnum.STOP_DEBUG.getFrontCode().equals(cmd)) {
                    //发送之前判断机器人或者引擎是否已连接
                    //需要直接转发给引擎
                    this.sendEngineMsg(jsonObject,message);
                } else {
                    //设备连接
                    if (InstructSetMsg.device_enter.equals(cmd)){
                        this.deviceEnter(jsonObject);
                        //需要直接转发给引擎
                        this.sendEngineMsg(jsonObject,message);
                    }else if (InstructSetMsg.device_exit.equals(cmd)){
                        //退出设备使用命令
                        this.sendEngineMsg(jsonObject,message);
                        //需要直接转发给引擎
                        this.deviceExit(jsonObject);
                    }else{
                        //其他的指令
                        if (InstructSetMsg.device_init.equals(cmd)){
                            WsManyWaysBo wsManyWaysBo = WsUtils.sessionMap.get(this.sessionId);
                            if (wsManyWaysBo.getEngineWsClient() == null || wsManyWaysBo.getRobotWsClient() == null){
                                this.errorData(jsonObject,"设备未连接,请先连接设备");
                            }else{
                                //需要直接转发给引擎
                                this.sendEngineMsg(jsonObject,message);
                            }
                        }else{
                            //发送之前判断机器人或者引擎是否已连接
                            WsManyWaysBo wsManyWaysBo = WsUtils.sessionMap.get(this.sessionId);
                            if (wsManyWaysBo.getEngineWsClient() == null || wsManyWaysBo.getRobotWsClient() == null){
                                this.errorData(jsonObject,"设备未连接,请先连接设备");
                            }else{
                                WsUtils.sendMsgRobot(this,message);
                            }
                        }
                    }
                }
            }
        }
    }


    private void sendEngineMsg(JSONObject jsonObject, String message){
        WsManyWaysBo wsManyWaysBo = WsUtils.sessionMap.get(this.sessionId);
        //说明需要发送给执行引擎
        if (wsManyWaysBo.getEngineWsClient() == null || wsManyWaysBo.getRobotWsClient() == null){
        }else{
            WsUtils.sendMsgEngine(this,message);
        }
    }



    @OnClose
    public void onClose(CloseReason cr) {
            logger.info("前端ws通道关闭:{},:{}",this.sessionId,cr);
            if (null != this.sessionId){
                //移除redis的与前端的ws状态
                redisUtil.remove(WsUtils.frontWsStateKey + this.sessionId);
                WsUtils.closeFrontWs(this.sessionId);
            }
            //通过远程调用告知释放资源,调用释放资源的时候需要等待1分钟判断前端是否重新连接上
        if (null != cr
                && cr.getCloseCode() != null
                && cr.getCloseCode().getCode() == CloseReason.CloseCodes.NORMAL_CLOSURE.getCode()
                && null != cr.getReasonPhrase()
                && cr.getReasonPhrase().contains(InstructSetMsg.sit)){
            logger.info("前端通道ws关闭代码:{}",cr.getCloseCode().getCode());
            //说明是为内部释放无需通知释放
        }else {
            if (this.token!= null && this.deviceId != null) {
                WsUtils.scheduledExecutorService.schedule(() -> {
                    //判断该sessionId是否重新连接
                    Object o = redisUtil.get(WsUtils.frontWsStateKey + this.sessionId);
                    logger.info("延迟一分钟资源释放参数1:{},参数2:{}", this.token, this.deviceId);
                    if (o == null) {
                        this.release();
                    }
                }, release, TimeUnit.SECONDS);
            }
        }
    }


    public void release(){
        //redis清除enter状态
        redisUtil.remove(WsUtils.redisEnterKey + this.sessionId);
        //调用接口释放资源
        if (this.token!= null && this.deviceId != null) {
            Map<String, String> map = new HashMap<>();
            map.put("deviceId",this.deviceId);
            map.put("token",this.token);
            try {
                ResultWrapper<String> release = designerFeignClient.release(authorization,userId,map);
                logger.info("资源释放远程调用:{}",JSONObject.toJSONString(release));
                if (!release.isSuccess()){
                    logger.error("资源释放失败:{}",release.getMessage());
                }
                //如果通过退出设备释放资源,释放成功后需要将this.deviceId设置为null
                if (release.isSuccess()){
                    this.deviceId = null;
                }
            }catch (Exception e){
                logger.error("远程调用资源释放异常:",e);
                try {
                    String queueName = MqConstant.ENGINE_RELEASE;
                    String[] tokens = {this.token};
                    Message message = new Message(JSON.toJSONString(Arrays.asList(tokens)).getBytes());
                    rabbitTemplate.send(queueName, message);
                    logger.info("发送队列释放设备成功：token -> {}, deviceId -> {}", token, deviceId);
                } catch (AmqpException ex) {
                    logger.error("设备退出发送mq重试异常：",ex);
                }
            }
        }
    }


    @OnError
    public void onError(Throwable xb) {
        logger.error("前端ws通道异常:{},:{}",this.sessionId,xb);
    }


    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String msg) {
        if (this.session.isOpen()){
            //try {
            if (!msg.equals(InstructSetMsg.pong)) {
                JSONObject jsonObject = JSONObject.parseObject(msg);
                if (null != jsonObject.get(InstructSetMsg.robot_engine) && InstructSetMsg.engine.equals(jsonObject.get(InstructSetMsg.robot_engine))) {
                    logger.info("引擎发送给前端的参数:{}", msg);
                    this.sendMsgText(msg);
                } else if (null != jsonObject.get(InstructSetMsg.robot_engine) && InstructSetMsg.robot.equals(jsonObject.get(InstructSetMsg.robot_engine))) {
                    JSONObject json = null;
                    if (InstructSetMsg.device_status.equals(jsonObject.get(InstructSetMsg.cmd))) {
                        //如果是机器人返回的单向指令直接发
                        json = jsonObject;
                    } else {
                        //机器人指令转换
                        json = this.instructTransetion(jsonObject);
                    }
                    logger.info("机器人发送给前端的参数:{}", json);
                    this.sendMsgText(json.toJSONString());

                }

            }
        }else{
            //如果是引擎发上来的消息将未发出去的消息存放到redis中
            JSONObject jsonObject = JSONObject.parseObject(msg);
            if (null != jsonObject.get(InstructSetMsg.robot_engine) && InstructSetMsg.engine.equals(jsonObject.get(InstructSetMsg.robot_engine))){
                logger.info("引擎发送给前端消息失败,存入redis:{}", msg);
                redisUtil.set(sessionId,msg,600L);
            }
        }
    }

    public void optClose(String msg){
        if (this.session.isOpen()){
            try {
                this.session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE,msg));
            } catch (IOException e) {
                logger.error("关闭执行机ws异常:",e);
            }
        }
    }

    private void sendMsgText(String msg){
        synchronized(this) {
            try {
                this.session.getBasicRemote().sendText(msg);
            } catch (Exception e) {
                logger.error("发送消息至前端失败:", e);
            }
        }
    }

    /**
     * 申请设备使用
     */
    private void deviceEnter(JSONObject jsonObject){
        //根据令牌连接机器人和执行引擎,连接机器人和执行引擎指令
        JSONObject datar = jsonObject.getJSONObject(InstructSetMsg.data);
        String token = null;
        if (null == datar){
            this.errorData(jsonObject,"未携带token参数");
        }else{
             token = datar.getString(InstructSetMsg.token);
             this.token = token;
            if (null == token){
                this.errorData(jsonObject,"未携带token参数");
            }
        }
        //调用外部微服务校验token参数等待目标机地址
        String ipAddr = null;
        String ipPort = null;
            try {
                ResultWrapper<JSONObject> res = designerFeignClient.getInfosByToken(authorization, userId, token);
                if (!res.isSuccess()){
                    this.errorData(jsonObject,"获取设备信息失败");
                    logger.error("获取设备信息失败:{}",res.getMessage());
                    return;
                }
                JSONObject infos = res.getData();
                logger.info("远程调用信息:{}",infos);
                JSONObject engineInfo = infos.getJSONObject("engineInfo");
                JSONObject cdPcDevice = infos.getJSONObject("cdPcDevice");
                if(cdPcDevice != null){
                    this.deviceId = cdPcDevice.getString("id");
                }
                ipAddr = engineInfo.getString("ipAddr");
                ipPort = engineInfo.getString("ipPort");
                if (StringUtils.isEmpty(ipAddr)){
                    this.errorData(jsonObject,"获取设备信息失败");
                    return;
                }

            }catch (Exception e){
                logger.error("远程调用异常:",e);
                this.errorData(jsonObject,"获取设备信息失败");
                return;
            }
        List<Map<String, Object>> filterList = new ArrayList<>();
        try {
            Map<String, String> platMap = new HashMap<>();
            platMap.put("catalogCode", catalogCode);
            JSONArray array = cctpPlatformFeignClient.catalogItems(authorization, platMap);
            for (Object o : array) {
                JSONObject jsonForm = JSONObject.parseObject(JSONObject.toJSONString(o));
                String itemName = jsonForm.getString("itemName");
                itemName = itemName.replace(":443","").replace(":80","");
                String itemCode = jsonForm.getString("itemCode");
                Set<String> codes = new HashSet<>();
                if (itemCode.contains(",")) {
                    String[] split = itemCode.split(",");
                    codes.addAll(Arrays.asList(split));
                } else {
                    codes.add(itemCode);
                }
                Map<String, Object> prop = new HashMap<>();
                prop.put("domainName", itemName);
                prop.put("properties", codes);
                boolean i = true;
                for (Map<String, Object> item : filterList) {
                    if (item.get("domainName").equals(itemName)){
                        Set set = (Set)item.get("properties");
                        set.addAll(codes);
                        i = false;
                        break;
                    }
                }
                if (i){
                    filterList.add(prop);
                }
            }
        } catch (Exception e) {
            logger.error("远程调用获取字典目录条目异常:", e);
        }

        String address = "ws://" + ipAddr + ":5589/robot/designer";//机器人地址   杰少的地址:192.168.77.72
        String addressEngine = "ws://" + ipAddr + ":" + ipPort + "/debugger/pc";//执行引擎地址
        String sessionId = jsonObject.getString(InstructSetMsg.sessionId);
        //通过sessionId查找对应的对象信息
        WsManyWaysBo wsManyWaysBo = WsUtils.sessionMap.get(sessionId);
        if (null != wsManyWaysBo){
            if(wsManyWaysBo.getRobotWsClient() != null || wsManyWaysBo.getEngineWsClient() != null){
                //说明是第二次连接,现将之前连接的断开
                WsUtils.closeRobotAndEngineWs(sessionId,"断开旧连接");
            }
            //去连接机器人和引擎
            JSONObject json = new JSONObject();
            json.put(InstructSetMsg.cmd, InstructSetMsg.reply);
            json.put(InstructSetMsg.sessionId, sessionId);
            JSONObject data = new JSONObject();
            data.put(InstructSetMsg.requestId,jsonObject.getJSONObject(InstructSetMsg.data).getString(InstructSetMsg.requestId));
            data.put(InstructSetMsg.finish, 1);

            RobotWsClient robotWsClient = new RobotWsClient(URI.create(address), sessionId, filterList);
            EngineWsClient engineWsClient = new EngineWsClient(URI.create(addressEngine + "/" + token + "/" + sessionId), sessionId);
            if (robotWsClient.isNormal() && engineWsClient.isNormal()) {
                wsManyWaysBo.setRobotWsClient(robotWsClient);
                wsManyWaysBo.setEngineWsClient(engineWsClient);
                //将状态map初始化,连接成功后重新初始化
                //添加连接状态管理map
                RobotEngineConnetStatusBo statusBo = new RobotEngineConnetStatusBo();
                statusBo.setSessionId(this.sessionId);
                WsUtils.connectStatus.put(this.sessionId,statusBo);

                //连接成功通知前端正在连接机器人和执行引擎
                data.put(InstructSetMsg.success, 1);
                data.put(InstructSetMsg.msg,"设备连接成功");
                //连接成功将enter信息存放redis
                redisUtil.set(WsUtils.redisEnterKey + this.sessionId, jsonObject.toJSONString());
            }else{
                data.put(InstructSetMsg.success, 0);
                data.put(InstructSetMsg.msg,"设备连接失败");
            }
            json.put(InstructSetMsg.data, data);
            logger.info("设备连接设计器服务推送:{}",json);
            this.sendMsgText(json.toJSONString());
        }else{
            this.errorData(jsonObject,"该sessionId对于的ws不存在");
        }
    }

    /**
     * 退出设备使用
     * @param jsonObject
     */
    private void deviceExit(JSONObject jsonObject) {
        String sessionId = jsonObject.getString(InstructSetMsg.sessionId);
        //通过sessionId查找对应的对象信息
        WsManyWaysBo wsManyWaysBo = WsUtils.sessionMap.get(sessionId);
        if (null != wsManyWaysBo){
            if (null != wsManyWaysBo.getRobotWsClient()){
                //需要通知机器人做退出,修改退出无需再给机器人发送退出指令
                //需要断开机器人和引擎的ws
                WsUtils.closeRobotAndEngineWs(this.sessionId,"设备退出断开");
            }

            JSONObject json = new JSONObject();
            json.put(InstructSetMsg.cmd, InstructSetMsg.reply);
            json.put(InstructSetMsg.sessionId, sessionId);
            JSONObject data = new JSONObject();
            data.put(InstructSetMsg.requestId,jsonObject.getJSONObject(InstructSetMsg.data).getString(InstructSetMsg.requestId));
            data.put(InstructSetMsg.finish, 1);
            data.put(InstructSetMsg.success, 1);
            data.put(InstructSetMsg.msg,"设备退出成功");
            json.put(InstructSetMsg.data, data);
            logger.info("设备退出设计器服务推送:{}",json);
            this.sendMsgText(json.toJSONString());
            //远程调用通知释放资源
            //判断该sessionId是否重新连接
            this.release();
        }else{
            this.errorData(jsonObject,"该sessionId对于的ws不存在");
        }
    }
    public void errorData(JSONObject jsonObject,String errorMsg){
        JSONObject json = new JSONObject();
        json.put(InstructSetMsg.cmd, InstructSetMsg.reply);
        json.put(InstructSetMsg.sessionId, sessionId);
        JSONObject data = new JSONObject();
        data.put(InstructSetMsg.requestId,jsonObject.getJSONObject(InstructSetMsg.data).getString(InstructSetMsg.requestId));
        data.put(InstructSetMsg.finish, 1);
        data.put(InstructSetMsg.success, 0);
        data.put(InstructSetMsg.msg,errorMsg);
        json.put(InstructSetMsg.data, data);
        logger.info("指令参数错误,设计器服务主动推送:{}",json);
        this.sendMsgText(json.toJSONString());
    }
    private JSONObject instructTransetion(JSONObject jsonObject) {
        String cmd = jsonObject.getString(InstructSetMsg.cmd);
        JSONObject json = new JSONObject();
        json.put(InstructSetMsg.cmd, InstructSetMsg.reply);
        json.put(InstructSetMsg.sessionId, this.sessionId);
        JSONObject data = new JSONObject();
        data.put(InstructSetMsg.requestId,jsonObject.getString(InstructSetMsg.seqId));
        data.put(InstructSetMsg.finish, 1);
        data.put(InstructSetMsg.msg,jsonObject.getString(InstructSetMsg.msg));
        if (0 == jsonObject.getIntValue(InstructSetMsg.state)){
            data.put(InstructSetMsg.success, 1);
        }else{
            data.put(InstructSetMsg.success, 0);
        }

        //返回进行中命令
        if (InstructSetMsg.detectByElementRes.equals(cmd) ||
                InstructSetMsg.detectByImageRes.equals(cmd) ||
                InstructSetMsg.detectByOcrRes.equals(cmd) ||
                InstructSetMsg.detectByPointRes.equals(cmd)){
            data.put(InstructSetMsg.finish, 0);
            data.put(InstructSetMsg.msg,"成功");
            data.put(InstructSetMsg.success, 1);
        }


        if (InstructSetMsg.detectByElement.equals(cmd) ||
                InstructSetMsg.detectByImage.equals(cmd) ||
                InstructSetMsg.detectByOcr.equals(cmd) ||
                InstructSetMsg.detectByPoint.equals(cmd)){
            // 图形转换
            JSONObject target = jsonObject.getJSONObject(InstructSetMsg.target);
            if (null != target){
                if (InstructSetMsg.image.equals(target.getString(InstructSetMsg.using)) || InstructSetMsg.ocr.equals(target.getString(InstructSetMsg.using))
                        || InstructSetMsg.hzocr.equals(target.getString(InstructSetMsg.using))){
                    JSONObject value = target.getJSONObject(InstructSetMsg.value);
                    if (null != value){
                        value.put(InstructSetMsg.imgUri,this.imgInstruct(value.getString(InstructSetMsg.imgUri)));
                    }
                }
                target.put(InstructSetMsg.thumbImage,this.imgInstruct(target.getString(InstructSetMsg.thumbImage)));
                target.put(InstructSetMsg.fullImage,this.imgInstruct(target.getString(InstructSetMsg.fullImage)));


                Set<String> strings = jsonObject.keySet();
                for (String string : strings) {
                    if (!string.equals(InstructSetMsg.cmd) &&
                            !string.equals(InstructSetMsg.seqId) &&
                            !string.equals(InstructSetMsg.msg) &&
                            !string.equals(InstructSetMsg.state) &&
                            !string.equals(InstructSetMsg.target) &&
                            !string.equals(InstructSetMsg.robot_engine)){
                        target.put(string,jsonObject.get(string));
                    }
                }
            }
            data.put(InstructSetMsg.result,target);
        }
        json.put(InstructSetMsg.data, data);
        if (InstructSetMsg.fetchCmdRes.equals(cmd)){
            json.put(InstructSetMsg.cmd, InstructSetMsg.detect_step);
            // 图形转换
            JSONObject step = jsonObject.getJSONObject(InstructSetMsg.step);
            if (null != step){
                JSONObject command = step.getJSONObject(InstructSetMsg.command);
                if (null != command){
                    JSONObject extAttrs = command.getJSONObject(InstructSetMsg.extAttrs);
                    if (null != extAttrs){
                        extAttrs.put(InstructSetMsg.imgUri,this.imgInstruct(extAttrs.getString(InstructSetMsg.imgUri)));
                        extAttrs.put(InstructSetMsg.fullImage,this.imgInstruct(extAttrs.getString(InstructSetMsg.fullImage)));
                    }
                    JSONArray targets = command.getJSONArray(InstructSetMsg.targets);
                    for (Object target : targets) {
                        JSONObject jsonTarget = (JSONObject)target;
                        if (InstructSetMsg.image.equals(jsonTarget.getString(InstructSetMsg.using))
                        || InstructSetMsg.ocr.equals(jsonTarget.getString(InstructSetMsg.using))
                        || InstructSetMsg.hzocr.equals(jsonTarget.getString(InstructSetMsg.using))){
                            JSONObject value = jsonTarget.getJSONObject(InstructSetMsg.value);
                            if (null != value){
                                value.put(InstructSetMsg.imgUri,this.imgInstruct(value.getString(InstructSetMsg.imgUri)));
                            }
                        }
                    }
                    String fullImage = command.getString(InstructSetMsg.fullImage);
                    if (fullImage != null){
                        command.put(InstructSetMsg.fullImage,this.imgInstruct(fullImage));
                    }
                    String imgUri = command.getString(InstructSetMsg.imgUri);
                    if (imgUri != null){
                        command.put(InstructSetMsg.imgUri,this.imgInstruct(imgUri));
                    }
                    JSONObject argsJson = command.getJSONObject(InstructSetMsg.args);
                    if (null != argsJson && null != argsJson.getString(InstructSetMsg.fullImage)){
                        argsJson.put(InstructSetMsg.fullImage, this.imgInstruct(argsJson.getString(InstructSetMsg.fullImage)));
                    }

                }
            }
            json.put(InstructSetMsg.data, step);

        }

        return json;
    }

    private String imgInstruct(String base64String) {
        if (StringUtils.isEmpty(base64String)){
            return "";
        }
        File temp = ImgBase64InstructUtil.decode(base64String, UUIDUtil.create32UUID() + ".png", "temp");
        if (null != temp){
            try {
                NKFile nkFile = storageService.upload(tenantId, temp,true,null, FileBusinessTypeEnum.PC_RECORD_SCREENSHOT);
                boolean delete = temp.delete();
                logger.info("删除文件：{}",delete);
                return nkFile.getId();
            } catch (FileUploadException e) {
                logger.error("字符串转图片异常",e);
            }
        }
        return "";
    }
}
