package com.imdroid.sideslope.executor;

import com.imdroid.common.util.DataTypeUtil;
import com.imdroid.common.util.ThreadManager;
import com.imdroid.secapi.client.BeidouClient;
import com.imdroid.secapi.dto.GnssDevice;
import com.imdroid.sideslope.bd.Gga;
import com.imdroid.sideslope.calc.GNSSDataCalcService;
import com.imdroid.sideslope.message.D341LocationMessage;
import com.imdroid.sideslope.service.Device;
import com.imdroid.sideslope.service.DeviceService;
import com.imdroid.sideslope.service.DataPersistService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;

/**
 * @author Layton
 * @date 2023/2/2 20:50
 */
@Component
public class D341LocationMessageExecutor implements Executor<D341LocationMessage, Void> {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private GNSSDataCalcService gnssCalcService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private BeidouClient beidouClient;
    @Autowired
    private DataPersistService dataPersistService;
    @Override
    public Void execute(D341LocationMessage message) {
        // 更新device对象统计
        Device device = deviceService.findByDeviceId(message.getId());
        if(device == null) return null;

        // 如果没有收到d3f2,这里判断是否是一个新的周期：上一次收到D341的时间大于两分钟且上次收到d3f2的时间大于30分钟
        if(device.getD341Count()>0) {
            LocalDateTime now = LocalDateTime.now();
            if (device.getLastRxTime().isBefore(now.minusMinutes(1)) &&
                (device.getLastD3f2Time() == null ||
                        device.getLastD3f2Time().isBefore(now.minusMinutes(30)))) {
                // new cycle
                Device lastCycleDevice = new Device();
                lastCycleDevice.setDeviceId(device.getDeviceId());
                lastCycleDevice.setDeviceType(device.getDeviceType());
                lastCycleDevice.setTenantId(device.getTenantId());
                lastCycleDevice.setD341bytes(device.getD341bytes());
                lastCycleDevice.setD341Count(device.getD341Count());
                lastCycleDevice.setFixedNum(device.getFixedNum());
                lastCycleDevice.setFloatNum(device.getFloatNum());
                lastCycleDevice.setNoFixedAndFloatResult(device.getNoFixedAndFloatResult());
                lastCycleDevice.setLastRxTime(device.getLastRxTime());
                lastCycleDevice.setLastValidCalcDataTime(device.getLastValidCalcDataTime());
                lastCycleDevice.setSatelitesInUse(device.getSatelitesInUse());
                device.clearStat();
                ThreadManager.getFixedThreadPool().submit(() -> {
                    // 通知上线
                    try {
                        beidouClient.onDeviceActive(device.getDeviceId(), device.getTenantId());
                    } catch (Exception e) {

                    }
                    dataPersistService.updateDeviceState(lastCycleDevice);
                });
            }
        }

        // update trx
        message.setTenantId(device.getTenantId());
        device.updateRx(message.getHeader(), message.getLen(), 1);
        if(device.isB562AsCalc()) {
            double[] pos = message.getB562_loc();
            device.updateCalcQuality((int) pos[3]);
        }

        Gga gga = message.getGga();
        if(gga != null) {
            device.updateSatelitesNum(gga.getSatellitesInUsed());
            if(gga.isFixed() || device.getDeviceType() == Device.DEVICE_BASE_STATION) {
                device.setLatitude(gga.getLatitude());
                device.setLongitude(gga.getLongitude());
                device.setAltitude(gga.getAltitude());
            }
            if(!device.isB562AsCalc()){
                device.updateCalcQuality(gga.getQuality());
            }
        }

        if(device.getDeviceType() == Device.DEVICE_ROVER) {
            ThreadManager.getFixedThreadPool().submit(() -> {
                gnssCalcService.calcSingle(message, true);
                // 原始码流输出到日志文件 -- INFO 级别
                if (device.getLoggingmode() == GnssDevice.LOGGING_MODE_FULL) {
                    logger.info("receive {} d341 message: {}", message.getId(), DataTypeUtil.getHexString(message.getSrcData()));
                }
            /*else {
                Gga gga1 = message.getGga();
                if (gga1 != null && !gga1.isFixed()) {
                    // 若不是固定解，则打印原始码流到日志里
                    logger.info("receive {} d341 message: {}", message.getId(), DataTypeUtil.getHexString(message.getSrcData()));
                }
            }*/
            });
        }

        return null;
    }

    @Override
    public Class<?> getMessageType() {
        return D341LocationMessage.class;
    }
}
