package com.cisdi.data.RFID.gateway;

import com.alibaba.fastjson.JSON;
import com.cisdi.data.common.exception.BusinessException;
import com.cisdi.data.common.utils.Strings;
import com.cisdi.data.sdk.consts.ServiceName;
import com.cisdi.data.sdk.enums.GatewayState;
import com.cisdi.data.sdk.gateway.base.PulledSocketGatewayBase;
import com.cisdi.data.sdk.param.PullSocketParam;
import com.cisdi.data.sdk.procotol.message.SocketReturnMessage;
import com.cisdi.data.sdk.service.RouteService;
import com.cisdi.data.sdk.vo.DeviceVo;
import com.cisdi.data.sdk.vo.ExeResultVo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * 物流 rfid 驱动，平台：客户端  rfid：server，多个server，使用tcp协议
 *
 * @author cup
 * @date 2021/03/04
 */
public class RfidPullSocketGateway extends PulledSocketGatewayBase {
    private static Logger logger = LoggerFactory.getLogger(RfidPullSocketGateway.class);

    private String deviceId;
    private AtomicBoolean shouldRun = null;
    private static final int Min_Pull_Internal = 1; // 允许最小的拉取间隔为1毫秒
    private static final int Min_Timeout = 1000; // 允许最小的超时时间间隔，为1000毫秒 

    @Override
    public ExeResultVo sendReturnMessage(SocketReturnMessage returnMsg) {
        throw new BusinessException("永锋物流Rfid协议不支持下发命令。");
    }

    @Override
    public void start() {
        if (state == GatewayState.RUNNING) {
            return;
        }

        try {
            startInternal();
            state = GatewayState.RUNNING;
            logger.info("永锋物流Rfid报警socket拉取网关:{}启动成功", instanceVo.getRunId());
        } catch (Exception e) {
            logger.error("永锋物流Rfid报警socket拉取网关:{}启动失败", instanceVo.getRunId());
            logger.error(e.getLocalizedMessage(), e);
        }
    }

    private void startInternal() {
        socketParam = JSON.parseObject(getInstanceVo().getParameter(), PullSocketParam.class);

        if (StringUtils.isEmpty(socketParam.getPeerIp()) || socketParam.getPeerPort() == null) {
            throw new BusinessException("未正确配置拉取对端ip地址和对端端口。");
        }

        if (socketParam.getPullInternal() == null) {
            throw new BusinessException("未正确配置拉取间隔");
        }

        if (socketParam.getTimeout() == null) {
            throw new BusinessException("未正确配置拉取超时时间");
        }

        socketParam.setPullInternal(socketParam.getPullInternal() < Min_Pull_Internal ?
                Min_Pull_Internal : socketParam.getPullInternal());

        socketParam.setTimeout(socketParam.getTimeout() < Min_Timeout ? Min_Timeout : socketParam.getTimeout());

        RouteService routeService = (RouteService) serviceProvider.getByName(ServiceName.Route);
        List<DeviceVo> deviceVos = routeService.findByRunId(instanceVo.getRunId());

        if (deviceVos.size() > 1) {
            throw new BusinessException("网关Id:" + instanceVo.getRunId() + "为永锋物流Rfid报警socket拉取网关，只允许关联一个设备Id");
        }

        deviceId = deviceVos.size() > 0 ? deviceVos.get(0).getDeviceId() : null;

        if (StringUtils.isEmpty(deviceId)) {
            throw new BusinessException("runId=" + getInstanceVo().getRunId() + "未正确配置网关和设备关联");
        }

        logger.info("永锋物流Rfid报警socket拉取网关:{}读取启动配置参数:{}", getInstanceVo().getRunId(), socketParam);

        closePrevState();
        shouldRun = new AtomicBoolean(true);

        String parameter = socketParam.getOtherParameter();
        Set<String> targetServerSet = new HashSet<String>();
        targetServerSet.add(String.format("%s:%s", socketParam.getPeerIp(), socketParam.getPeerPort()));
        RfidCustomParam customParam = null;
        if (parameter != null) {
            customParam = JSON.parseObject(parameter, RfidCustomParam.class);
            if (customParam != null) {
                /**
                 * RFID服务端参数去重
                 */
                customParam.setServerList(customParam.getServerList().stream().distinct().collect(Collectors.toList()));
                for (String server : customParam.getServerList()) {
                    targetServerSet.add(server.trim());
                }
            }
        }

        int index = 1;
        for (String server : targetServerSet) {
            // 复制已有参数
            PullSocketParam serverParam = JSON.parseObject(JSON.toJSONString(socketParam), PullSocketParam.class);

            serverParam.setPeerIp(Strings.split(server, ":")[0]);
            serverParam.setPeerPort(Integer.valueOf(Strings.split(server, ":")[1]));

            // 启动线程
            RfidTaskStartVo startVo = new RfidTaskStartVo();
            startVo.setDeviceId(deviceId);
            startVo.setGatewayBase(this);
            startVo.setServiceProvider(serviceProvider);
            startVo.setSocketParam(serverParam);
            startVo.setShouldRun(shouldRun);
            startVo.setCustomParam(customParam);

            RfidClient fireClient = new RfidClient(startVo);
            RfidDaemonTask daemonTask = new RfidDaemonTask(fireClient, startVo);
            startVo.setRfidDaemonTask(daemonTask);
            Thread thread = new Thread(daemonTask, "Fire-Daemon-Task-runid-" + instanceVo.getRunId() + "-s" + index++);
            thread.start();
        }


        state = GatewayState.RUNNING;
    }

    @Override
    public void shutdown() {
        if (state == GatewayState.CLOSED) {
            return;
        }

        closePrevState();

        logger.info("永锋物流Rfid报警socket拉取网关:{}关闭中", getInstanceVo().getRunId());

        state = GatewayState.CLOSED;

        logger.info("永锋物流Rfid报警socket拉取网关:{}关闭成功", getInstanceVo().getRunId());
    }

    private void closePrevState() {
        if (shouldRun != null) {
            shouldRun.set(false);
            shouldRun = null;
        }
    }

    @Override
    public Set<String> getActiveDeviceIds() {
        Set<String> set = new HashSet<String>();
        if (deviceId != null) {
            set.add(deviceId);
        }
        return set;
    }
}
