package com.stb.www.proxifier.client.handler.tcp;

import com.stb.www.proxifier.client.TcpProxyClient;
import com.stb.www.proxifier.definition.tcp.TcpProxyDefinition;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by stb on 1/12/2017.
 */
public class TcpServerToProxyServerHandler extends ChannelInboundHandlerAdapter {

    private static final Logger log = LoggerFactory.getLogger(TcpServerToProxyServerHandler.class);

    private TcpProxyDefinition definition;
    private TcpProxyClient client;

    public TcpServerToProxyServerHandler(TcpProxyDefinition definition, TcpProxyClient client) {
        this.definition = definition;
        this.client = client;
    }

    @Override
    public void channelActive(ChannelHandlerContext context) {
        if(client.getInbound().isActive()) {
            context.channel().read();
        }
    }

    @Override
    public void channelRead(final ChannelHandlerContext context, Object msg) {
        if(client.getInbound().isActive()) {
            client.getInbound().writeAndFlush(msg).addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) {
                    if (future.isSuccess()) {
                        context.channel().read();
                    } else {
                        future.channel().close();
                    }
                }
            });
        } else {
            client.getOutbound().close();
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext context) {
        close();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext context, Throwable cause) {
        //log.error("Exception Occured: ", cause);
        context.channel().close();
        close();
    }

    private void close() {
        if (client.getInbound() != null && client.getInbound().isActive()) {
            log.info("Closing client channel");
            client.getInbound().writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
        }
    }
}
