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.GnssTrxMsg;
import com.imdroid.sideslope.calc.GNSSDataCalcService;
import com.imdroid.sideslope.calc.MultiLineGNSSCalcService;
import com.imdroid.sideslope.message.D3F2StopIndicationMessage;
import com.imdroid.sideslope.service.Device;
import com.imdroid.sideslope.service.DeviceService;
import com.imdroid.sideslope.service.DataPersistService;
import com.imdroid.sideslope.service.GnssSingleBufferServiceImpl;
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 LiGang
 * 1、更新统计
 * 2、启动单周期固定解处理
 * 3、保存统计信息，判断是否有连续无固定解、连续无有效解等告警，清除离线告警
 */
@Component
public class D3F2StopIndicationMessageExecutor implements Executor<D3F2StopIndicationMessage, Void> {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private DataPersistService dataPersistService;

    @Autowired
    private DeviceService deviceService;
    @Autowired
    private BeidouClient beidouClient;
    @Autowired
    private GNSSDataCalcService gnssCalcService;
    @Autowired
    MultiLineGNSSCalcService multiLineGNSSCalcService;

    @Autowired
    GnssSingleBufferServiceImpl gnssSingleBufferService;

    @Override
    public Void execute(D3F2StopIndicationMessage message) {
        logger.debug("receive d3f2 message of {} device: {}", message.getId(), DataTypeUtil.getHexString(message.getSrcData()));

        // 补齐tenantId
        String deviceId = message.getId();
        Device device = deviceService.findByDeviceId(deviceId);
        if(device == null) return null;
        message.setTenantId(device.getTenantId());
        if(device.getDeviceType() == Device.DEVICE_ROVER) {
            message.setOtherInfo(message.getOtherInfo() + ",no calc:" + device.getNoFixedAndFloatResult()+",warning:"+device.getWarningcode());
            if (device.getLastValidCalcDataTime() != null) {
                message.setOtherInfo(message.getOtherInfo() + ",valid calc:" + device.getLastValidCalcDataTime());
            }
        }
        //更新统计
        device.updateRx(message.getHeader(), message.getLen(),1);
        GnssTrxMsg gnssTrxMsg = message.getTrxMsg();
        gnssTrxMsg.setTenantid(device.getTenantId());
        gnssTrxMsg.setD3xxbytes(device.getD3xxbytes());
        gnssTrxMsg.setB562bytes(device.getD341bytes());
        gnssTrxMsg.setB562count(device.getD341Count());
        gnssTrxMsg.setSatelliteinuse(device.getSatelitesInUse());
        gnssTrxMsg.setFixnum(device.getFixedNum());
        gnssTrxMsg.setFloatnum(device.getFloatNum());
        gnssTrxMsg.setJumpcount(device.getJumpCount());

        // 储设备收发字节数统计信息
        ThreadManager.getFixedThreadPool().submit(() -> {
            // 开始周期解算
            LocalDateTime uploadTime = multiLineGNSSCalcService.checkUploadTime(
                    device.getDeviceId(), device.getTenantId());
            gnssCalcService.calSingleDone(device, null, message.getCreateTime());

            // 保存统计，判断是否有连续无固定解、连续无有效解等告警，清除离线告警
            dataPersistService.saveDeviceTrxStat(message, (uploadTime!=null), device);

            // 保存缓存中的 GNSS 单次解析结果
            gnssSingleBufferService.flush();

            // 通知beidou服务设备休眠
            try {
                beidouClient.onDeviceStop(deviceId, device.getTenantId());
                if (uploadTime != null) {
                    String info = "d342 num:" + device.getD342Count() +
                            ", bytes:" + device.getD342Bytes() +
                            ", d341 included:" + device.getD341In42Count();
                    beidouClient.onGnssUpload(deviceId, device.getTenantId(), uploadTime, info);
                }
            }
            catch (Exception e){

            }
            // 清除统计
            device.clearStat();
        });

        return null;
    }

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