package org.nl.config.lucene.remote.impl;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.Future;
import org.nl.config.lucene.remote.AbstraceServer;
import org.nl.config.lucene.remote.coder.LogConsumerHandler;

import java.net.SocketAddress;

import static java.util.concurrent.TimeUnit.MILLISECONDS;

/*
 * @author ZZQ
 * @Date 2024/1/22 10:01
 */
public class ClientServer extends AbstraceServer {

    private static EventLoopGroup group  = new NioEventLoopGroup();

    public ClientServer(SocketAddress address) {
        super(address);
    }

    // 非阻塞IO线程组
    @Override
    public void doOpen() {
        server = new Bootstrap();
        server.group(group)
                .option(ChannelOption.SO_KEEPALIVE, true)
                .option(ChannelOption.TCP_NODELAY, true)
                .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                .channel(NioSocketChannel.class);

        server.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline()
                        .addLast("client-idle-handler", new IdleStateHandler(500, 0,0 , MILLISECONDS))
                        .addLast(new LengthFieldPrepender(2))
                        .addLast( new LogConsumerHandler());
            }
        });
    }

    @Override
    public void doDestroy() {
        super.doDestroy();
        Future<?> bossGroupShutdownFuture = group.shutdownGracefully();
        bossGroupShutdownFuture.syncUninterruptibly();
    }

    @Override
    public void doConnect() {
        try {
            ChannelFuture connect = ((Bootstrap) server).connect(address);
            connect.syncUninterruptibly();
            channel = connect.channel();
        } catch (Throwable t) {
            this.doDestroy();
            throw t;
        }
    }


}
