package com.yeejoin.equipmanage.listener;

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.yeejoin.equipmanage.common.entity.Car;
import com.yeejoin.equipmanage.common.entity.WlCarMileage;
import com.yeejoin.equipmanage.fegin.IotFeign;
import com.yeejoin.equipmanage.service.ICarService;
import com.yeejoin.equipmanage.service.IWlCarMileageService;
import com.yeejoin.equipmanage.thread.ThreadCar;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
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.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.component.emq.EmqKeeper;
import org.typroject.tyboot.component.emq.EmqxListener;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Component
public class CarIotNewListener extends EmqxListener {
    Logger logger = LoggerFactory.getLogger(CarIotNewListener.class);

    @Autowired
    private IWlCarMileageService iWlCarMileageService;

    @Autowired
    private ICarService iCarService;

    @Autowired
    private IotFeign iotFeign;
    @Value("${mileage.clippingtime:600000}")
    private Long clipping_time;
    private final String GUIDE_KEY = "813684495d9a3981dd2c7694916fe404";

    private final String GUIDE_URL = "https://restapi.amap.com/v3/geocode/regeo?";

    @Autowired
    private EmqKeeper emqkeeper;

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    // 用于根据topicId 也就是物联设备id 存储对应的线程来进行计时
    private static final HashMap<String, ThreadCar> deviceInfo = new HashMap();
    private static final HashMap<String, String> deviceLastInfo = new HashMap();

    @Override
    public void processMessage(String topic, MqttMessage message) throws Exception {

        logger.info("----收到物联消息：：topic---------------" + topic);
        logger.info("----收到物联消息：：message---------------" + message);
        String measurement = topic.split("/")[0];
        String deviceName = topic.split("/")[1];
        String iotCode = measurement + deviceName;
        JSONObject jsonObject = JSONObject.parseObject(message.toString());
        //通过消息存电量到扩展字段2
        this.updateEquipBattery(jsonObject, iotCode);
        logger.info("当前设备信息info" + JSON.toJSONString(deviceInfo));
        //判断是否有效数据
        if (!ObjectUtils.isEmpty(jsonObject.containsKey("FireCar_Longitude"))&&!ObjectUtils.isEmpty(jsonObject.containsKey("FireCar_Latitude"))) {
            this.updateCarLocation(jsonObject, iotCode);
            //如果map中已经存在该设备或者该设备有但是线程已经执行了
            //存储上报上来的经纬度信息
            String coordinate = jsonObject.getDoubleValue("FireCar_Longitude") + String.valueOf(jsonObject.getDoubleValue("FireCar_Latitude"));
            if ((!deviceInfo.containsKey(iotCode))) {
                logger.info("topic---------------------" + topic + "开启计时线程");
                ThreadCar threadCar = new ThreadCar(topic, jsonObject, this.iWlCarMileageService, this.iotFeign, this.iCarService, clipping_time);
                deviceInfo.put(iotCode, threadCar);
                threadCar.start();
            }
            if (!deviceLastInfo.containsKey(iotCode)) {
                deviceLastInfo.put(iotCode, coordinate);
            }
            //获取打不过全部系统时间
            Long currentTime = System.currentTimeMillis();
            //获取上报的时间
            Long endTime = jsonObject.getLong("time");
            //如果当前时间减去上报时间大小于配置的时间并且之前没包含上报的数据
            if (((currentTime - endTime) < clipping_time) && (!deviceLastInfo.get(iotCode).equals(coordinate))) {
                try {
                    //销毁线程后移除
                    deviceInfo.get(iotCode).interrupt();
                    deviceInfo.remove(iotCode);
                } catch (Exception e) {
                }
                logger.info("topic---------------------" + topic + "开启计时线程");
                ThreadCar threadCar = new ThreadCar(topic, jsonObject, this.iWlCarMileageService, this.iotFeign, this.iCarService, clipping_time);
                deviceInfo.put(iotCode, threadCar);
                //更新车辆的最新坐标数据
                deviceLastInfo.put(iotCode, coordinate);
                threadCar.start();
                if (iWlCarMileageService.getUncompleteMileagByIotCode(iotCode)) {
                    WlCarMileage wlCarMileage = new WlCarMileage();
                    wlCarMileage.setIotCode(iotCode);
                    wlCarMileage.setDate(new Date());
                    // 获取开始坐标
                    double startLongitude = jsonObject.getDoubleValue("FireCar_Longitude");
                    double startLatitude = jsonObject.getDoubleValue("FireCar_Latitude");
                    // String currentTime = "20"+jsonObject.getString("currentTime");
                    wlCarMileage.setStartLongitude(startLongitude);
                    wlCarMileage.setStartLatitude(startLatitude);
                    // Date startTime = UTCToCST();
                    //时间值被mysql自动转换
                    Date startTime = new Date((jsonObject.getLong("time") / 1000) * 1000);
                    wlCarMileage.setStartTime(startTime);
                    wlCarMileage.setStartName(getAddress(startLongitude, startLatitude));
                    wlCarMileage.setStartSpeed(Double.valueOf(jsonObject.getDoubleValue("FireCar_Speed")).intValue());
                    logger.info("新增数据信息如下：："+JSONObject.toJSONString(wlCarMileage));
                    try {
                        iWlCarMileageService.save(wlCarMileage);
                    } catch (Exception e) {
                        e.printStackTrace();
                        iWlCarMileageService.save(wlCarMileage);
                    }
                }
            }
        }
    }

    public String getAddress(double longitude, double lantitude) {
        StringBuilder api = new StringBuilder(GUIDE_URL);
        api.append("key=").append(GUIDE_KEY).append("&location=").append(longitude).append(",").append(lantitude).append("&radius=1000").append("&batch=false").append("&extensions=base").append("&roadlevel=0").append("&batch=false");
        StringBuilder res = new StringBuilder();
        BufferedReader in = null;
        try {
            System.out.println(api.toString());
            URL url = new URL(api.toString());
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setDoOutput(true);
            conn.setRequestMethod("POST");
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                res.append(line).append("\n");
            }
            JSONObject object = JSONObject.parseObject(res.toString());
            System.out.println(object);
            JSONObject regeocode = object.getJSONObject("regeocode");
            String address = regeocode.getString("formatted_address");
            if ("[]".equals(address)) {
                logger.info("===============无效坐标:" + longitude + "," + lantitude);
                address = "无效坐标";
            }
            res = new StringBuilder(address);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return res.toString();
    }

    public Date UTCToCST(String UTCStr) throws ParseException {
        Date date = sdf.parse(UTCStr);
        System.out.println("UTC时间: " + date);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR, calendar.get(Calendar.HOUR) + 8);
        return calendar.getTime();
    }

    public void updateCarLocation(JSONObject jsonObject, String iotCode) {
        if (jsonObject.containsKey("FireCar_Longitude") && jsonObject.containsKey("FireCar_Latitude")) {
            // 获取开始坐标
            double startLongitude = jsonObject.getDoubleValue("FireCar_Longitude");
            double startLatitude = jsonObject.getDoubleValue("FireCar_Latitude");
            int direction = jsonObject.getIntValue("direction");

            // 地图推送消息
            Car car = iCarService.getOne(new LambdaQueryWrapper<Car>().eq(Car::getIotCode, iotCode));
            if (car != null && startLongitude != 0 && startLatitude != 0) {
                JSONArray sendArr = new JSONArray();
                JSONObject sendObj = new JSONObject();
                sendObj.put("id", String.valueOf(car.getId()));
                sendObj.put("direction", direction);
                sendObj.put("longitude", String.valueOf(startLongitude));
                sendObj.put("latitude", String.valueOf(startLatitude));
                sendObj.put("carNum", car.getCarNum());
                sendObj.put("bizOrgName", car.getBizOrgName());
                sendArr.add(sendObj);
                MqttMessage mqttMessage = new MqttMessage();
                mqttMessage.setPayload(sendArr.toJSONString().getBytes());
                car.setLongitude(startLongitude);
                car.setLatitude(startLatitude);
                iCarService.updateById(car);
                logger.info("-----------推送车辆位置消息到到地图成功--------");
                try {
                    emqkeeper.getMqttClient().publish("car/location", mqttMessage);
                } catch (MqttException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    //存储设备电量到扩展字段2
    public void updateEquipBattery(JSONObject jsonObject, String iotCode) {
        Integer power = 0;
        if (jsonObject.containsKey("additionalInformations") && jsonObject.get("additionalInformations") != null) {
            JSONObject jsonObject1 = JSONObject.parseObject(jsonObject.get("additionalInformations").toString());
            if (jsonObject1 != null) {
                JSONObject jsonObject2 = JSONObject.parseObject(jsonObject1.get("additionalInformations").toString());
                if (jsonObject2 != null && jsonObject2.containsKey("power")) {
                    power = jsonObject2.getInteger("power");
                }
            }
        }

        Car car = iCarService.getOne(new LambdaQueryWrapper<Car>().eq(Car::getIotCode, iotCode));
        if (car != null && power != 0) {
            car.setExtra2(power.toString());
            iCarService.updateById(car);
            logger.info("-----------更新车辆设备电池电量成功--------");
        }
    }
}
