package com.cisdi.data.HJ212;

import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.cisdi.data.HJ212.gateway.AliveCheckTask;
import com.cisdi.data.HJ212.gateway.Hj212ChannelInitializer;
import com.cisdi.data.HJ212.gateway.Hj212FrameDecoder;
import com.cisdi.data.HJ212.gateway.Hj212IoSession;
import com.cisdi.data.HJ212.gateway.Hj212SessionFactory;
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.gateway.netty.IoSession;
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
import com.cisdi.data.sdk.gateway.netty.TcpIoService;
import com.cisdi.data.sdk.gateway.netty.impl.DefaultTcpIoService;
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;

/**
 *  扬尘监测网络设备  HJ212协议数据接入
 * @author cup
 *
 */
public class YfHj212SocketGateway extends SocketGatewayBase {
	private static Logger logger = LoggerFactory.getLogger(YfHj212SocketGateway.class);
	private TcpIoService ioService = null;
	private SessionFactory sessionFactory = null;
	private AtomicBoolean shouldRun = null;
	private String deviceId;
	
	@Override
	public ExeResultVo sendReturnMessage(SocketReturnMessage returnMsg) {
		throw new BusinessException("hj212网关不支持下发命令");
	}

	@Override
	public void start() {
		if(state == GatewayState.RUNNING) {
			return;
		}
		
		logger.info("hj212网关:{}读取启动配置参数:{}",instanceVo.getRunId(), getInstanceVo().getParameter());
		
		RouteService routeService = (RouteService)serviceProvider.getByName(ServiceName.Route);
		List<DeviceVo> deviceVos = routeService.findByRunId(instanceVo.getRunId());
		
		if(deviceVos.size() > 1) {
			throw new BusinessException("网关Id:" +instanceVo.getRunId() + "为hj212网关，只允许关联一个设备Id");
		}
		
		deviceId = deviceVos.size() > 0 ? deviceVos.get(0).getDeviceId() : null;
		
		if(StringUtils.isEmpty(deviceId)) {
			throw new BusinessException("runId=" + getInstanceVo().getRunId() + "未正确配置网关和设备关联");
		}
		
		DefaultTcpIoService defaultIoService = new DefaultTcpIoService();
		SessionFactory factory = new Hj212SessionFactory(deviceId);
		factory.init(serviceProvider, this);
		
		ListenSocketParam socketParam = JSON.parseObject(getInstanceVo().getParameter(), ListenSocketParam.class);
		
		Hj212ChannelInitializer<Hj212FrameDecoder> channelInitializer = 
				new Hj212ChannelInitializer<Hj212FrameDecoder>(factory);
		
		defaultIoService.init(instanceVo, factory, channelInitializer);
		
		ioService = defaultIoService;
		sessionFactory = factory;
		
		boolean open = ioService.open();
		
		if(open == true) {
			state = GatewayState.RUNNING;
			logger.info("hj212网关:{}启动成功 参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
			
			shouldRun = new AtomicBoolean(true);
			
			Integer keepAlive = socketParam.getKeepAlive();
			
			if(keepAlive == null || keepAlive < 120) {
				keepAlive = 120;
			}else if (keepAlive > 3600) {
				keepAlive = 3600;
			}
			
			AliveCheckTask task = new AliveCheckTask(keepAlive, shouldRun, factory);
			
			Thread thread = new Thread(task, "hj212-alive-check-thread-" + getInstanceVo().getRunId());
			thread.start();
		}else {
			logger.info("hj212网关:{}启动失败 参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
		}
	}

	@Override
	public void shutdown() {
		if(state == GatewayState.CLOSED) {
			return;
		}
		
		if(sessionFactory != null) {
        	for (IoSession ioSession : sessionFactory.getSessions()) {
        		Hj212IoSession imsIoSession = (Hj212IoSession)ioSession;
        		imsIoSession.close();
        	}		       	
		}
		
		boolean close = ioService.close();
		if(close == true) {
			sessionFactory = null;
			state = GatewayState.CLOSED;	
			logger.info("hj212网关:{}关闭成功", instanceVo.getRunId());
		}else {
			logger.info("hj212网关:{}关闭失败", instanceVo.getRunId());
		}
	}
	
	@Override
    public Set<String> getActiveDeviceIds(){
		Set<String> set = Sets.newHashSet();
		set.add(deviceId);
		return set;
	}
}
