package com.its.op.xnettcp.client;

import com.its.op.xnettcp.client.listener.NettyTcpClientCloseListener;
import com.its.op.xnettcp.client.listener.NettyTcpClientConnectListener;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

@Slf4j
@Getter
@Setter
@RequiredArgsConstructor
public class NettyTcpClientVds implements Callable<Object> {

    private final String ipAddress;
    private final int    port;
    private final int    reconnectTime;
    private final NettyTcpClientVdsBootstrapFactory bootstrapFactory;
    private Bootstrap clientBootstrap = null;
    private ChannelFuture channelFuture = null;
    private NettyTcpClientConnectListener connectListener = null;
    private NettyTcpClientCloseListener closeListener = null;

    @Override
    public Object call() {
        log.info("NettyTcpClientVds start: {}, {}", this.ipAddress, this.port);
        if (this.clientBootstrap == null) {
            this.clientBootstrap = this.bootstrapFactory.createBootstrap();
        }

        log.info("VDS Server try connect: {}, {}", this.ipAddress, this.port);
        if (this.channelFuture != null && this.channelFuture.channel() != null) {
            this.channelFuture.channel().close();
            this.channelFuture = null;
        }
        this.channelFuture = this.clientBootstrap.connect(new InetSocketAddress(this.ipAddress, this.port));
        this.channelFuture.addListener(new ChannelFutureListener() {
            // 연결에 대한 리스너 추가
            @Override
            public void operationComplete(ChannelFuture future) {
                if (future.isSuccess()) {
                    log.info("VDS Server Channel open");
                    channelOpen(future.channel());
                } else {
                    log.error("Could not connect to VDS Server, {}", future.cause().toString());
                }
            }
        });
        this.channelFuture.channel().closeFuture().addListener(new ChannelFutureListener() {
            // 종료에 대한 리스너 추가
            @Override
            public void operationComplete(ChannelFuture future) {
                //log.warn("operationComplete: channelClosed, {}", future.toString());
                channelClosed(future.channel());
            }
        });
        return null;
    }

    public Channel getChannel() {
        return this.channelFuture != null ? this.channelFuture.channel() : null;
    }

    protected void channelOpen(Channel channel) {
        log.info("VDS Server channelOpen: channel {}, channelFuture.channel {}", channel, this.channelFuture.channel());
    }

    protected synchronized void channelClosed(Channel channel) {
        log.error("VDS Server channelClosed: channel {}, channelFuture.channel {}", channel, this.channelFuture.channel());
        this.channelFuture.channel().close();
        this.channelFuture.channel().eventLoop().schedule(this, this.getReconnectTime(), TimeUnit.SECONDS);
    }

}
