package com.its.vds.xnettcp.center.handler;

import com.its.app.utils.NettyUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@ChannelHandler.Sharable
public class CenterTcpServerIdleStateHandler extends IdleStateHandler {

    public CenterTcpServerIdleStateHandler(int readerIdleTimeSeconds, int writerIdleTimeSeconds, int allIdleTimeSeconds) {
        super(readerIdleTimeSeconds, writerIdleTimeSeconds, allIdleTimeSeconds);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        String ipAddress = NettyUtils.getRemoteIpAddress(ctx.channel());
        int port = NettyUtils.getRemotePort(ctx.channel());
        log.info("CenterTcpServerIdleStateHandler, Connect: {}", NettyUtils.getRemoteAddress(ctx.channel()));
    }

    /*
     *  클라이언트와의 연결 종료 처리
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        String ipAddress = NettyUtils.getRemoteIpAddress(ctx.channel());
        int port = NettyUtils.getRemotePort(ctx.channel());
        log.info("CenterTcpServerIdleStateHandler, Disconnect: {}", NettyUtils.getRemoteAddress(ctx.channel()));

        super.channelInactive(ctx);
    }

    /*
     *  Remote 에서 연결을 강제로 종료하면 이벤트 발생
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        String ipAddress = NettyUtils.getRemoteIpAddress(ctx.channel());
        int port = NettyUtils.getRemotePort(ctx.channel());
        log.info("CenterTcpServerIdleStateHandler, exceptionCaught: {}", NettyUtils.getRemoteAddress(ctx.channel()));
        super.exceptionCaught(ctx, cause);
    }

    /*
     *  클라이언트와의 연결 종료를 위해 호출하는 함수
     */
    public static void disconnectChannel(Channel channel) {
        String ipAddress = NettyUtils.getRemoteIpAddress(channel);
        int port = NettyUtils.getRemotePort(channel);
        log.info("disconnectChannel: {}", NettyUtils.getRemoteAddress(channel));
        //////////////////////////////////
        // 클라이언트와의 연결을 종료한다.
        //////////////////////////////////
        if (!channel.isActive()) {
            log.error("disconnectChannel: [{}], channel already closed.", ipAddress);
            return;
        }

        channel.flush();
        ChannelFuture f = channel.disconnect().awaitUninterruptibly();
        if (!f.isDone() || !f.isSuccess()) {
            log.error("disconnectChannel: [{}], isDone: {}, isSuccess: {}", ipAddress, f.isDone(), f.isSuccess());
        }
    }

}
