package com.cm.socket;

import com.cm.socket.decoder.MessageDecoder;
import com.cm.socket.encoder.MessageEncoder;
import com.cm.socket.pojo.Message;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.ScheduledFuture;

import java.util.concurrent.TimeUnit;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: Client
 * @Description:
 * @Author: WangGeng
 * @Date: 2020/7/4 18:20
 * @Version: 1.0
 **/
public class Client {

    public static void main(String[] args) {
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        final int[] sendCount = {0};
        try {
            bootstrap.group(eventLoopGroup);
            bootstrap.channel(NioSocketChannel.class);
            bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
            bootstrap.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                        @Override
                        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
                            System.out.println("服务器连接失败");
                            super.channelInactive(ctx);
                        }
                    });
                    ch.pipeline().addLast(new MessageEncoder());
                    ch.pipeline().addLast(new MessageDecoder());
                    ch.pipeline().addLast(new SimpleChannelInboundHandler<Message>() {

                        @Override
                        public void channelActive(ChannelHandlerContext ctx) throws Exception {
                            super.channelActive(ctx);
                            ping(ctx.channel());
                        }

                        private void ping(Channel channel) {
                            ScheduledFuture<?> schedule = channel.eventLoop().schedule(new Runnable() {
                                @Override
                                public void run() {
                                    if (channel.isActive()) {
                                        System.out.println("向服务器发送ping");
                                        Message ping = new Message();
                                        ping.setStart((byte) 0x01);
                                        ping.setType((byte) 0x01);
                                        ping.setContent("ping");
                                        channel.writeAndFlush(ping);
                                    } else {
                                        System.err.println("连接断开");
                                        channel.closeFuture();
                                        throw new RuntimeException();
                                    }
                                }
                            }, 3, TimeUnit.SECONDS);
                            schedule.addListener(new GenericFutureListener() {
                                @Override
                                public void operationComplete(Future future) throws Exception {
                                    if (future.isSuccess()) {
                                        ping(channel);
                                    }
                                }
                            });
                        }

                        @Override
                        protected void channelRead0(ChannelHandlerContext ctx, Message msg) throws Exception {
                            System.out.println(msg.getContent());
//                            if (sendCount[0] < 4) {
//                                Thread.sleep(5000);
//                                Message message = new Message();
//                                message.setStart((byte) 0x01);
//                                message.setType((byte) 0x02);
//                                message.setContent("你好服务器" + sendCount[0] + "!");
//                                ctx.channel().writeAndFlush(message);
//                                sendCount[0]++;
//                            } else {
//                                ctx.close();
//                            }
                        }

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

                }
            });
            ChannelFuture channelFuture = bootstrap.connect("localhost", 9999).addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (!future.isSuccess()) {
                        future.channel().pipeline().fireChannelInactive();
                    }
                }
            });
            Message message = new Message();
            message.setStart((byte) 0x01);
            message.setType((byte) 0x02);
            message.setContent("你好服务器!");
            channelFuture.channel().writeAndFlush(message);
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            eventLoopGroup.shutdownGracefully();
        }
    }

}
