package jguard.client.network;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import cucky.jGuard.lib.LogFile;
import cucky.jGuard.lib.Message;
import io.netty.channel.ChannelOption;
import jguard.client.gui.Window;

public class NetworkClient {

    private String server;
    private int port;

    private Channel channel;

    public NetworkClient(String server, int port) {
        this.server = server;
        this.port = port;
    }


    public void start() {

        LogFile.printInfo("Pripojuji ....");
        Window.setStatusBarMessage("Připojuji ...");

        EventLoopGroup group = new NioEventLoopGroup();
        
        try {
            SslContext sslCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();

            Bootstrap bootstrap = new Bootstrap().group(group)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer() {
                        @Override
                        protected void initChannel(Channel channel) throws Exception {
                            ChannelPipeline pipeline = channel.pipeline();
                            // pro zabezpecene pripojeni
                            pipeline.addLast("ssl", sslCtx.newHandler(channel.alloc(), NetworkClient.this.server, NetworkClient.this.port));

                            pipeline.addLast("decoder", new ObjectDecoder(ClassResolvers.weakCachingConcurrentResolver(getClass().getClassLoader())));
                            pipeline.addLast("encoder", new ObjectEncoder());

                            pipeline.addLast("handler", new ClientAdapterHandler());
                        }

                    });

            channel = bootstrap.connect(server, port).sync().channel();

        } catch (Exception e) {
            LogFile.printErr("Client exception: " + e.getMessage());
        } finally {
            //group.shutdownGracefully(); // pokud se odkomentuje nejde se připojit k serveru 
        }

    }

    public void send(int type, Object obj) {
        channel.writeAndFlush(new Message(type, obj));
    }

    public Channel getChannel() {
        return channel;
    }

    public void disconnect() {
        if (channel != null) {
            channel.disconnect();
            channel.close();
        }
    }

    public boolean isConnected() {
        try {
            return channel.isRegistered();
        } catch (Exception e) {
            return false;
        }
    }
}
