package com.cisdi.data.RFID.gateway;

import com.cisdi.data.common.dto.AlarmDto;
import com.cisdi.data.sdk.consts.ServiceName;
import com.cisdi.data.sdk.service.AlarmService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.Date;

public class RfidDaemonTask implements Runnable {
    private static final Logger logger = LoggerFactory.getLogger(RfidDaemonTask.class);

    private RfidClient rfidClient;
    private RfidTaskStartVo startVo;

    public RfidDaemonTask(RfidClient rfidClient, RfidTaskStartVo startVo) {
        this.rfidClient = rfidClient;
        this.startVo = startVo;
    }

    @Override
    public void run() {
        String channelInfo = null;
        while (startVo.getShouldRun().get() == true) {
            channelInfo = String.format("channel:%s, active:%s,open:%s,writable:%s", rfidClient.getChannel(),
                rfidClient.getChannel() == null ? "" : rfidClient.getChannel().isActive(),
                rfidClient.getChannel() == null ? "" : rfidClient.getChannel().isOpen(),
                rfidClient.getChannel() == null ? "" : rfidClient.getChannel().isWritable());
            try {
                if (rfidClient != null && rfidClient.getChannel() != null
                    && rfidClient.getChannel().isActive() == true) {
                    if (startVo.getGatewayBase() != null
                        && Boolean.TRUE.equals(startVo.getGatewayBase().getInstanceVo().getLogOpen())) {
                        logger.info("当前永锋物流Rfid拉取连接通道处于连接状态，连接id:{},连接信息:{}",
                            startVo.getGatewayBase().getInstanceVo().getRunId(), channelInfo);
                    }
                    
                    if(startVo.getCustomParam() != null 
                        && Boolean.TRUE.equals(startVo.getCustomParam().getEnableHeartbeat()) 
                            && Math.abs(System.currentTimeMillis() - rfidClient.getLastHeartbeatTime()) > 
                                  startVo.getCustomParam().getHeartbeatMaxLostCount() * startVo.getCustomParam().getHeartbeatTimeInMs()){
                        logger.warn("当前永锋物流Rfid拉取连接通道心跳启用，且心跳超时，触发重连，连接id:{},连接信息:{}",
                            startVo.getGatewayBase().getInstanceVo().getRunId(), channelInfo);
                        //启用了心跳，且心跳时间超时
                       reconnectToRfid(channelInfo, true);
                    }
                } else if (rfidClient.getChannel() == null) {
                    String errorMsg = String.format("永锋物流Rfid到%s:%s的连接未建立或已关闭,  %s", rfidClient.getIp(),
                        rfidClient.getPort(), channelInfo);
                    logger.warn(errorMsg);
                    sendAlarmToPlatform(errorMsg);
                    reconnectToRfid(channelInfo, false);
                }                
                else {
                    String errorMsg = String.format("永锋物流Rfid到%s:%s的连接未建立或已关闭,  %s", rfidClient.getIp(),
                        rfidClient.getPort(), channelInfo);
                    logger.warn(errorMsg);

                    sendAlarmToPlatform(errorMsg);
                    
                    if(startVo.getCustomParam() != null 
                        && Boolean.TRUE.equals(startVo.getCustomParam().getEnableHeartbeat()) 
                            && Math.abs(System.currentTimeMillis() - rfidClient.getLastHeartbeatTime()) > 
                                  startVo.getCustomParam().getHeartbeatMaxLostCount() * startVo.getCustomParam().getHeartbeatTimeInMs()){
                        logger.warn("当前永锋物流Rfid拉取连接通道心跳启用，且心跳超时，触发重连，连接id:{},连接信息:{}",
                            startVo.getGatewayBase().getInstanceVo().getRunId(), channelInfo);
                        //启用了心跳，且心跳时间超时
                       reconnectToRfid(channelInfo, true);
                    }
                }

                Thread.sleep(startVo.getSocketParam().getPullInternal());
            } catch (Exception e) {
                logger.warn(e.getMessage(), e);
            }
        }

        if (rfidClient != null) {
            rfidClient.close();
            rfidClient = null;
        }
        logger.info("退出永锋物流Rfid拉取连接线程 {}", channelInfo);
    }

    private void reconnectToRfid(final String copyChannelInfo, boolean forceConnect) throws InterruptedException {
        Thread.sleep(5000);
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    logger.info("永锋物流Rfid触发重连强制:{}....{}:{} {}", forceConnect, rfidClient.getIp(), rfidClient.getPort(),
                        copyChannelInfo);
                    if (rfidClient.getChannel() == null || forceConnect) {
                        rfidClient.reconnect();
                    }
                } catch (Exception e) {
                    logger.info(e.getMessage(), e);
                }
            }
        });
        thread.start();
    }

    public void forceReconnectToRfid() {
        String channelInfo = String.format("channel:%s, active:%s,open:%s,writable:%s", rfidClient.getChannel(),
                rfidClient.getChannel() == null ? "" : rfidClient.getChannel().isActive(),
                rfidClient.getChannel() == null ? "" : rfidClient.getChannel().isOpen(),
                rfidClient.getChannel() == null ? "" : rfidClient.getChannel().isWritable());
        try {
            Thread.sleep(500);
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        logger.info("永锋物流Rfid触发重连强制:{}....{}:{} {}", true, rfidClient.getIp(), rfidClient.getPort(),
                                channelInfo);
                            rfidClient.reconnect();
                    } catch (Exception e) {
                        logger.info(e.getMessage(), e);
                    }
                }
            });
            thread.start();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    private void sendAlarmToPlatform(String detail) {
        if (startVo.getServiceProvider() != null && startVo.getGatewayBase() != null) {
            AlarmService alarmService = (AlarmService)startVo.getServiceProvider().getByName(ServiceName.Alarm);
            if (alarmService != null) {
                AlarmDto alarmDto = new AlarmDto();

                alarmDto.setAlarmType(AlarmDto.Connect_Fail_Alarm);
                alarmDto.setDetail(detail);
                alarmDto.setDeviceId(startVo.getDeviceId());
                alarmDto.setGatewayId(startVo.getGatewayBase().getInstanceVo().getRunId());
                alarmDto.setGatewayName(startVo.getGatewayBase().getInstanceVo().getName());
                alarmDto.setMsgKey(null);
                alarmDto.setUpper(Boolean.TRUE);
                alarmDto.setTime(new Date());

                alarmService.raiseAlarm(Arrays.asList(alarmDto));
            }
        }
    }
}
