package com.cisdi.data.DIClient;

import com.alibaba.fastjson.JSON;
import com.cisdi.data.DIClient.bean.DIClientCnfg;
import com.cisdi.data.DIClient.bean.PDIOVo;
import com.cisdi.data.DIClient.gateway.DBReader;
import com.cisdi.data.DIClient.gateway.DBTask;
import com.cisdi.data.common.exception.BusinessException;
import com.cisdi.data.sdk.consts.ServiceName;
import com.cisdi.data.sdk.enums.GatewayState;
import com.cisdi.data.sdk.gateway.base.SocketGatewayBase;
import com.cisdi.data.sdk.param.ListenSocketParam;
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 com.google.common.collect.Sets;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.SQLException;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

public class DIClientGateway extends SocketGatewayBase {
    private static Logger logger = LoggerFactory.getLogger(DIClientGateway.class);

    private String deviceId;
    private DBTask dbTask = null;

    private AtomicLong lastTime=new AtomicLong(0);
    private AtomicInteger no=new AtomicInteger(0);
    @Override
    public ExeResultVo sendReturnMessage(SocketReturnMessage returnMsg) {
        ExeResultVo rt = new ExeResultVo();



        PDIOVo pdioVo = new PDIOVo();
        pdioVo.setQueueId(returnMsg.getMsgKey());
        pdioVo.setData(new String(returnMsg.getData()));
        Long thisTime=System.currentTimeMillis();
        if(thisTime>lastTime.get())
        {
            lastTime.set(thisTime);
            no.set(0);
            pdioVo.setSerialNo(0);
            pdioVo.setTimeStamp(thisTime);
        }
        else if(thisTime==lastTime.get())
        {
            pdioVo.setSerialNo(no.incrementAndGet());
            pdioVo.setTimeStamp(thisTime);
        }
        else
        {
            pdioVo.setTimeStamp(lastTime.get());
            pdioVo.setSerialNo(no.incrementAndGet());
        }


        pdioVo.setHeader("cisdi");
        pdioVo.setStatus("N");
        dbTask.sendMessage(pdioVo);

        rt.setSuccess(true);
        rt.setMessage("DIClient下发数据成功，消息体为" + JSON.toJSONString(pdioVo));
        logger.info("DIClient下发数据成功，消息体为" + JSON.toJSONString(pdioVo));
        return rt;
    }

    @Override
    public void start() {
        if (state == GatewayState.RUNNING) {
            return;
        }
        ListenSocketParam socketParam = JSON.parseObject(getInstanceVo().getParameter(), ListenSocketParam.class);

        String otherParameter = socketParam.getOtherParameter();
        DIClientCnfg diClientCnfg = null;
        // 处理分组
        if (StringUtils.isNotBlank(otherParameter)) {
            diClientCnfg = JSON.parseObject(otherParameter, DIClientCnfg.class);
        }
        if (diClientCnfg == null) {
            throw new BusinessException("网关Id:" + instanceVo.getRunId() + "为DIClient网关，请配置正确的DIClient配置");
        }

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

        if (deviceVos.size() > 1) {
            throw new BusinessException("网关Id:" + instanceVo.getRunId() + "为DIClient网关，只允许关联一个设备Id");
        }

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

        if (StringUtils.isEmpty(deviceId)) {
            throw new BusinessException("runId=" + getInstanceVo().getRunId() + "未正确配置网关和设备关联");
        }
        logger.info("DIClient网关:{}读取启动配置参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());


        boolean open = false;
        DBReader dbReader = new DBReader(diClientCnfg.getDriverClassName(), diClientCnfg.getUrl(), diClientCnfg.getUser(), diClientCnfg.getPwd());
        open = dbReader.connectionInternal(0);
        if (open == true) {
            dbTask = new DBTask(serviceProvider, this, dbReader, diClientCnfg.getCycleTime(), deviceId);
            dbTask.start();
            state = GatewayState.RUNNING;
            logger.info("DIClient网关:{}启动成功 参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
        } else {
            logger.info("DIClient网关:{}启动失败 参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
        }
    }

    @Override
    public void shutdown() {
        if (state == GatewayState.CLOSED) {
            return;
        }
        try {
            dbTask.close();
            state = GatewayState.CLOSED;
            logger.info("网关:" + instanceVo.getRunId() + "关闭成功", instanceVo.getRunId());
        } catch (SQLException e) {
            logger.error("网关:" + instanceVo.getRunId() + "关闭失败" + e.getLocalizedMessage());
        }

    }

    @Override
    public Set<String> getActiveDeviceIds() {

        Set<String> set = Sets.newConcurrentHashSet();

        if (StringUtils.isNotEmpty(deviceId)) {
            set.add(deviceId);
        }

        return set;
    }
}
