package tech.glinfo.enbao.modules.mq;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import tech.glinfo.enbao.common.utils.ByteUtils;
import tech.glinfo.enbao.common.utils.DateUtils;
import tech.glinfo.enbao.common.utils.RedisUtils;
import tech.glinfo.enbao.modules.sh.entity.ShDeviceDataEntity;
import tech.glinfo.enbao.modules.sh.entity.ShDeviceEntity;
import tech.glinfo.enbao.modules.sh.entity.ShDeviceRecordEntity;
import tech.glinfo.enbao.modules.sh.entity.ShInstructionParsingEntity;
import tech.glinfo.enbao.modules.sh.service.OtherShDevicePowerService;
import tech.glinfo.enbao.modules.sh.service.OtherShDeviceService;
import tech.glinfo.enbao.modules.sh.service.ShDeviceDataService;
import tech.glinfo.enbao.modules.sh.service.ShDeviceRecordService;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


//智能插座
@Component("outletParse")
public class OutletParse implements IParse {

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

    @Autowired
    private OtherShDeviceService otherShDeviceService;

    @Autowired
    private ShDeviceRecordService shDeviceRecordService;

    @Autowired
    private ShDeviceDataService shDeviceDataService;

    @Autowired
    private OtherShDevicePowerService otherShDevicePowerService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private TimeParseUtils timeParseUtils;

    @Autowired
    private MqProducer mqProducer;

    @Override
    public Map<String, String> run(Object o, Map<String, String> datas) {
        ShDeviceEntity device = (ShDeviceEntity) o;
        Map<String, String> ws = new HashMap<>();

        ws.put("deviceId", String.valueOf(device.getId()));


        if ("1C".equals(datas.get("cmd")) && datas.get("content").equals("00")) {
            logger.info("delete:{}", device.getNumbering());
            redisUtils.delete("device:sendtemp:" + device.getNumbering());
        }else
        if("08".equals(datas.get("cmd"))) {//登录包
            redisUtils.set(datas.get("mac").toUpperCase(), datas.toString(), 180);//3分钟有效
            //校验设备时钟
            new Thread(new Runnable() {
                @Override
                public void run() {
                    logger.info("start checkDeviceTime");
                    timeParseUtils.checkDeviceTime1(datas.get("receiveId"), datas.get("content"), "03");
                }
            }).start();

            return datas;
        }else if("06".equals(datas.get("cmd"))) {//实时数据上报
            String content = datas.get("content");
            //开关状态
            String eqh = content.substring(2, 4);
            String eq = String.valueOf(Integer.valueOf(eqh, 16));
            //开关状态
            String power1 = content.substring(4, 8);
            String power1h = String.valueOf(Integer.valueOf(power1, 16));
            //总电量
            String powerh = content.substring(8, 16);
            String power = String.valueOf(Integer.valueOf(powerh, 16));
            logger.info("eq : {}, power : {}, 功率 : {}", eq, power, power1h);

            otherShDevicePowerService.saveOrUpdateByTime(device.getId(), 1, Integer.parseInt(power));
            //查询解析指令集
            List<ShInstructionParsingEntity> cmds = otherShDeviceService.getDeviceInstructionList(device.getProductId(), datas.get("cmd"));
            if (cmds != null && cmds.size() > 0) {
                int length = 0;
                //解析设备报文内容
                String content1 = datas.get("content");
                Map<String, Object> map = new HashMap<>();
                for (ShInstructionParsingEntity cmd : cmds) {
                    String hex = content1.substring(length, length + cmd.getLength());
                    String hex1;
                    if (cmd.getType() == 1 || cmd.getType() == 2) {
                        hex1 = String.valueOf(Integer.valueOf(hex, 16));

                    }else {
                        hex1 = ByteUtils.signHex2IntString(hex);
                    }
                    map.put(cmd.getName(), hex1);
                    ws.put(cmd.getName(), hex1);
                    length += cmd.getLength();
                }
                otherShDeviceService.updateDeviceData(JSON.toJSONString(map), device.getId());
            } else {
                ws = datas;
            }

           /* ws.put("onlineStatus", "2");
            ws.put("power", power);*/
        }else if("18".equals(datas.get("cmd"))) {//开关响应
            redisUtils.delete(device.getNumbering() + "cf");
            logger.info("已删除重复 : {}", redisUtils.hasKey(device.getNumbering() + "cf"));
            String content = datas.get("content");
            //开关状态
           /* if (content.equals("00")) {
                //保存开关记录
                String action = redisUtils.get(datas.get("receiveId") + "action");
                if (action != null) {
                    ShDeviceRecordEntity recordEntity = new ShDeviceRecordEntity();
                    recordEntity.setDeviceId(device.getId());
                    recordEntity.setAction(action.equals("01") ? 1 : 2);
                    shDeviceRecordService.save(recordEntity);
                    redisUtils.delete(datas.get("receiveId") + "action");
                }
            }*/
            ws.put("action", content);

        }else if("1A".equals(datas.get("cmd"))) {//温控响应
            String content = datas.get("content");
            logger.info("设置温控响应 : {}", content);
          /*  String content1 = redisUtils.get(device.getNumbering() + "temp");
            //设备响应成功之后修改数据，不用等30秒，页面体验好些
            if ("00".equals(content)) {
                if (content1 != null) {
                    ShDeviceDataEntity entity = shDeviceDataService.getOne(new QueryWrapper<ShDeviceDataEntity>().eq("device_id", device.getId()));
                    if (entity != null) {
                        JSONObject jsonObj = new JSONObject(entity.getValue());
                        jsonObj.put("highTemp", ByteUtils.signHex2IntString(content1.substring(0, 2)));
                        jsonObj.put("highTempStatus", ByteUtils.signHex2IntString(content1.substring(2, 4)));
                        jsonObj.put("lowTemp", ByteUtils.signHex2IntString(content1.substring(4, 6)));
                        jsonObj.put("lowTempStatus", ByteUtils.signHex2IntString(content1.substring(6, 8)));
                        entity.setValue(jsonObj.toString());
                        shDeviceDataService.updateById(entity);
                    }
                }
            }
            redisUtils.delete(device.getNumbering() + "temp");*/

        }else if("20".equals(datas.get("cmd"))) {//事件上报
            //保存开关记录
            String content = datas.get("content");
            String action = content.substring(6, 8);
            ShDeviceRecordEntity recordEntity = new ShDeviceRecordEntity();
            recordEntity.setDeviceId(device.getId());
            recordEntity.setAction(action.equals("01") ? 1 : 2);
            shDeviceRecordService.save(recordEntity);

        }
        new Thread(() -> {
            //检测有没待下发指令
            String send = redisUtils.get("device:sendtemp:" + device.getNumbering());
            if(send != null) {
                mqProducer.sendT(send);
                int tryTimes = 2;//尝试两次
                while (tryTimes > 0) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if(redisUtils.hasKey("device:sendtemp:" + device.getNumbering())) {
                        logger.info("try update-time again: {}", DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN));
                        tryTimes--;
                        mqProducer.sendT(send);
                        if (tryTimes == 0) {
                            redisUtils.delete("device:sendtemp:" + device.getNumbering());
                        }
                    } else {
                        break;
                    }
                }
            }
        }).start();
        return ws;
    }


}
