package com.imdroid.beidou_fwd.task;

import com.imdroid.beidou_fwd.entity.XFZData;
import com.imdroid.beidou_fwd.service.TCPClient;
import com.imdroid.beidou_fwd.service.TCPListener;
import com.imdroid.common.util.GsonUtil;
import com.imdroid.common.util.NumberUtils;
import com.imdroid.secapi.dto.GnssCalcData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

@Component
@Configuration
@EnableScheduling
public class SaasForwarder extends Forwarder{
    static final String FORWARDER_NAME = "测试";
    @Value("${sass.server.host}")
    private String host;

    @Value("${sass.server.port}")
    private int port;

    private TCPClient tcpClient;

    final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    static class MyTCPListener implements TCPListener {
        public static final int STATE_NO_ACK = 0;
        public static final int STATE_OK = 1;
        public static final int STATE_FAILED = 2;
        public int state = STATE_NO_ACK;

        public void clear(){
            state = STATE_NO_ACK;
        }
        @Override
        public void onConnected() {

        }

        @Override
        public void onDisconnect() {

        }

        @Override
        public void onMessage(String msg) {
            if(msg.contains("succeed")) state = STATE_OK;
            else state = STATE_FAILED;
        }
    }
    MyTCPListener listener = new MyTCPListener();
    @PostConstruct
    void registerMe(){
        init(FORWARDER_NAME, "TCP "+host+":"+port,0,false,30);
        tcpClient = new TCPClient();
        tcpClient.init(host, port,listener);
        tcpClient.start();
    }

    /**
     * 每半小时转发GNSS解算结果
     */
    @Scheduled(cron = "0 20,50 * * * ?") // 每30分钟执行一次
    private void forwardGnss() {
        logger.info("saas forwardGnss");
        forwardCurrentGnss();
    }

    @Override
    int send(String projectId, List<GnssCalcData> records, LocalDateTime sentTime){
        int sendNum = 0;
        if(records.size() == 0) return 0;

        XFZData tcpMessage = new XFZData();
        tcpMessage.setProjectID(projectId);
        tcpMessage.setWorkPointID(projectId);

        List<XFZData.Data> dataList = new ArrayList<>(records.size());
        tcpMessage.setData(dataList);

        for(GnssCalcData locationRecord: records) {
            XFZData.Data data = new XFZData.Data();
            dataList.add(data);
            data.setDataTime(locationRecord.getCreatetime().format(dateFormatter));
            data.setDevNum(locationRecord.getDeviceid());
            data.setDevtype("GNSS");
            // 单位由mm转化为m
            data.setX(NumberUtils.scale(locationRecord.getRpose() * 0.001, 5));
            data.setY(NumberUtils.scale(locationRecord.getRposn() * 0.001, 5));
            data.setZ(NumberUtils.scale(locationRecord.getRposd() * 0.001, 5));
            sendNum++;
        }
        String json = "#" + GsonUtil.toJson(tcpMessage) + "!";
        logger.info("project " + projectId + ": push calculation result to SAAS");
        logger.info(json);
        try {
            listener.clear();
            tcpClient.writeAndFlush(json);
            if(!checkResult()) sendNum = 0;
        } catch (Exception e1) {
            e1.printStackTrace();
            sendNum = 0;
        }
        return sendNum;
    }

    boolean checkResult() throws InterruptedException {
        // 等待应答，最多等1s
        /*for(int i=0; i<10; i++){
            Thread.sleep(100);
            if(listener.state == MyTCPListener.STATE_OK) return true;
            else if(listener.state == MyTCPListener.STATE_FAILED) return false;
        }*/
        Thread.sleep(100);
        return true;
    }

}
