package org.framework.lazy.cloud.network.heartbeat.client.netty.tcp.handler;


import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOption;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.client.netty.InternalNetworkClientPermeateClientVisitor;
import org.framework.lazy.cloud.network.heartbeat.client.netty.tcp.advanced.ClientHandleTcpDistributeClientTransferServerPermeateChannelConnectionSuccessfulTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.client.netty.tcp.socket.NettyTcpClientPermeateClientVisitorTransferSocket;
import org.framework.lazy.cloud.network.heartbeat.client.netty.tcp.socket.NettyTcpClientPermeateServerVisitorTransferSocket;
import org.framework.lazy.cloud.network.heartbeat.common.constant.TcpMessageType;
import org.framework.lazy.cloud.network.heartbeat.common.NettyCommunicationIdContext;
import org.framework.lazy.cloud.network.heartbeat.common.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.NettyRealIdContext;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;

import java.util.UUID;

@Slf4j
public class NettyTcpClientPermeateClientVisitorHandler extends SimpleChannelInboundHandler<ByteBuf> {
    private final InternalNetworkClientPermeateClientVisitor internalNetworkClientPermeateClientVisitor;
//    private final NettyChannelPool nettyChannelPool = new DefaultNettyChannelPool(10);

    public NettyTcpClientPermeateClientVisitorHandler(InternalNetworkClientPermeateClientVisitor internalNetworkClientPermeateClientVisitor) {
        this.internalNetworkClientPermeateClientVisitor = internalNetworkClientPermeateClientVisitor;
    }

    /**
     * @param ctx
     * @throws Exception
     * @see NettyTcpClientPermeateServerVisitorTransferSocket
     * @see ClientHandleTcpDistributeClientTransferServerPermeateChannelConnectionSuccessfulTypeAdvanced
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 访客连接上代理服务器了
        Channel visitorChannel = ctx.channel();
        // 先不读取访客数据
        visitorChannel.config().setOption(ChannelOption.AUTO_READ, false);


        // 生成访客ID
        String visitorId = UUID.randomUUID().toString();
        // 绑定访客真实通道
        NettyRealIdContext.pushReal(visitorChannel, visitorId);
        // 当前通道绑定访客ID
        ChannelAttributeKeyUtils.buildVisitorId(visitorChannel, visitorId);

        // 判断是否有可用的通道 如果没有创建新的通道
//        Channel transferChannel = nettyChannelPool.availableChannel(visitorId);
        // 创建访客连接客户端通道
        NettyTcpClientPermeateClientVisitorTransferSocket.buildTransferServer(internalNetworkClientPermeateClientVisitor,visitorChannel);
        log.info("客户端渗透客户端访客:【{}】端口连接成功了",visitorId);
        super.channelActive(ctx);
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, ByteBuf buf) {

        // 访客通道
        Channel visitorChannel = ctx.channel();

        String visitorId = ChannelAttributeKeyUtils.getVisitorId(visitorChannel);
        Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(visitorChannel);
        byte[] bytes = new byte[buf.readableBytes()];
        buf.readBytes(bytes);
        // 获取客户端通道，而后进行数据下发
        log.debug("【客户端渗透客户端】访客端口成功接收数据:{}", new String(bytes));

        // 使用访客的通信通道
        Integer visitorPort = internalNetworkClientPermeateClientVisitor.getVisitorPort();
        String clientId = internalNetworkClientPermeateClientVisitor.getNettyClientProperties().getClientId();
        NettyProxyMsg nettyProxyMsg = new NettyProxyMsg();
        nettyProxyMsg.setType(TcpMessageType.TCP_REPORT_CLIENT_PERMEATE_CLIENT_TRANSFER_REQUEST);
        nettyProxyMsg.setVisitorId(visitorId);
        nettyProxyMsg.setClientId(clientId);
        nettyProxyMsg.setVisitorPort(visitorPort);
        nettyProxyMsg.setData(bytes);
        nextChannel.writeAndFlush(nettyProxyMsg);
        log.debug("【客户端渗透客户端】访客端口成功发送数据了");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        String visitorId = ChannelAttributeKeyUtils.getVisitorId(channel);
        String clientId = ChannelAttributeKeyUtils.getClientId(channel);
        if (StringUtil.isNullOrEmpty(visitorId)) {
            super.channelInactive(ctx);
            return;
        }
        Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(channel);
        // 通信通道自动读写打开 ，然后关闭通信通道

        if (nextChannel != null && nextChannel.isActive()) {

//            nextChannel.config().setOption(ChannelOption.AUTO_READ, true);

            //  通知客户端 关闭访问通道、真实通道
            NettyProxyMsg myMsg = new NettyProxyMsg();
            myMsg.setType(TcpMessageType.TCP_REPORT_CLIENT_PERMEATE_CLIENT_TRANSFER_CLOSE);
            nextChannel.writeAndFlush(myMsg);
        }
        // 关闭 访客通信通道、访客真实通道
        NettyRealIdContext.clear(visitorId);
        NettyCommunicationIdContext.clear(visitorId);
        log.warn("【客户端渗透客户端】访客:【{}】端口断开连接",visitorId);
        super.channelInactive(ctx);
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {

        if (ctx.channel().isWritable()) {
            log.debug("Channel is writable again");
            // 恢复之前暂停的操作，如写入数据
        } else {
            log.debug("Channel is not writable");
            // 暂停写入操作，等待可写状态
        }
        log.info("channelWritabilityChanged!");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        log.error("exceptionCaught");
    }
}