package com.zt.plat.module.qms.iot.tcpserver;

import com.zt.plat.module.qms.iot.tcpserver.core.*;
import com.zt.plat.module.qms.iot.tcpserver.core.IotClientSessionContext;
import com.zt.plat.module.qms.iot.tcpserver.core.IotDeviceSessionContext;
import com.zt.plat.module.qms.iot.tcpserver.device.RedisSessionComponent;
import com.zt.plat.module.qms.iot.tcpserver.proxy.ProxyProtocolDecoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import tech.zzjc.tio.common.starter.annotation.TioServerAioListener;
import tech.zzjc.tio.core.ChannelContext;
import tech.zzjc.tio.core.Tio;
import tech.zzjc.tio.core.intf.Packet;
import tech.zzjc.tio.server.intf.ServerAioListener;

/**
 * <b>IotServerAioListener</b>
 * <p>
 * 更新历史：
 * <pre> 版本         更新时间            更新者        更新内容<hr/>
 * V1.0      2019年9月11日          王兴荣         Add</pre>
 * <b>Copyright (C)  云南志者竟成科技有限公司</b> 
 * <p>
 * @author 王兴荣 &lt;xingrong_wang@will-way.cn&gt;
 * @version V1.0 
 * @since 2019年9月11日
 */
@Slf4j
@TioServerAioListener
public class IotServerAioListener implements ServerAioListener {
    
//    @Autowired
//    private IDeviceMeasurePointService deviceMeasurePointService;
    
//    @Autowired
//    private IMeasurePointService measurePointService;
    @Autowired public RedisSessionComponent redisSessionComponent;

    @Override
    public void onAfterConnected(ChannelContext channelContext, boolean isConnected, boolean isReconnect) throws Exception {
        log.info("onAfterConnected channelContext:{}, isConnected:{}, isReconnect:{}", channelContext, isConnected, isReconnect);
        //连接后，需要把连接会话对象设置给channelContext
        channelContext.set(IotClientSessionContext.DEFAULT_CLIENT_SESSION_CONTEXT_KEY, new IotClientSessionContext());
        channelContext.set(IotDeviceSessionContext.DEFAULT_DEVICE_SESSION_CONTEXT_KEY, new IotDeviceSessionContext());
        //设置为支持代理协议
        ProxyProtocolDecoder.enableProxyProtocol(channelContext);
    }

    @Override
    public void onAfterDecoded(ChannelContext channelContext, Packet packet, int packetSize) throws Exception {
        log.debug("onAfterDecoded");
    }

    @Override
    public void onAfterReceivedBytes(ChannelContext channelContext, int receivedBytes) throws Exception {
        log.debug("onAfterReceivedBytes");
    }

    @Override
    public void onAfterSent(ChannelContext channelContext, Packet packet, boolean isSentSuccess) throws Exception {
        log.debug("onAfterSent channelContext:{}, isSentSuccess:{}", channelContext, isSentSuccess);
    }

    @Override
    public void onAfterHandled(ChannelContext channelContext, Packet packet, long cost) throws Exception {
        log.debug("onAfterHandled");
    }

    @Override
    public void onBeforeClose(ChannelContext channelContext, Throwable throwable, String remark, boolean isRemove) throws Exception {
        
        //连接断开，更新数据库连接状态
        IotClientSessionContext iotClientSessionContext = (IotClientSessionContext) channelContext.get(IotClientSessionContext.DEFAULT_CLIENT_SESSION_CONTEXT_KEY);
        IotDeviceSessionContext sessionContext = (IotDeviceSessionContext) channelContext.get(IotDeviceSessionContext.DEFAULT_DEVICE_SESSION_CONTEXT_KEY);

        String deviceId = sessionContext.getDeviceId();
        log.info("onBeforeClose deviceId:" + deviceId);
        //设备断开，清除redis记录
        if(!ObjectUtils.isEmpty(deviceId)){
            redisSessionComponent.deleteByDeviceId(deviceId);
        }

        //客户端断开，清除控制
        Object deviceCode = channelContext.get(ChannelContextConstant.CONTROL_DEVICE_ID);
        if(!ObjectUtils.isEmpty(deviceCode)){
            redisSessionComponent.clearControlByDeviceCode(deviceCode.toString(), channelContext);
        }
        //解绑业务ID
        Tio.unbindBsId(channelContext);
        //解绑群组
        Tio.unbindGroup(channelContext);
        //解绑用户
        Tio.unbindUser(channelContext);
        //解绑token
        Tio.unbindToken(channelContext);
        //移除
        IotDataUtils.removeIot(channelContext);

        log.info(channelContext.get("realClientIp") + ":" + channelContext.get("realClientPort") + "  onBeforeClose");
    }

    @Override
    public boolean onHeartbeatTimeout(ChannelContext channelContext, Long interval, int heartbeatTimeoutCount) {
        log.debug("onHeartbeatTimeout");
        return false;
    }

}
