package com.alibaba.otter.canal.admin.handler;

import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.group.ChannelGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.otter.canal.admin.netty.AdminNettyUtils;
import com.alibaba.otter.canal.protocol.AdminPacket;
import com.alibaba.otter.canal.protocol.AdminPacket.Handshake;
import com.alibaba.otter.canal.protocol.AdminPacket.Packet;
import com.google.protobuf.ByteString;

/**
 * handshake交互
 * 
 * @author agapple 2019年8月24日 下午10:58:34
 * @since 1.1.4
 */
public class HandshakeInitializationHandler extends SimpleChannelHandler {

    // support to maintain socket channel.
    private ChannelGroup childGroups;

    public HandshakeInitializationHandler(ChannelGroup childGroups){
        this.childGroups = childGroups;
    }

    private static final Logger logger = LoggerFactory.getLogger(HandshakeInitializationHandler.class);

    public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        // add new socket channel in channel container, used to manage sockets.
        if (childGroups != null) {
            childGroups.add(ctx.getChannel());
        }

        final byte[] seed = org.apache.commons.lang3.RandomUtils.nextBytes(8);
        byte[] body = Packet.newBuilder()
            .setType(AdminPacket.PacketType.HANDSHAKE)
            .setVersion(AdminNettyUtils.VERSION)
            .setBody(Handshake.newBuilder().setSeeds(ByteString.copyFrom(seed)).build().toByteString())
            .build()
            .toByteArray();

        AdminNettyUtils.write(ctx.getChannel(), body, new ChannelFutureListener() {

            public void operationComplete(ChannelFuture future) throws Exception {
                logger.info("remove unused channel handlers after authentication is done successfully.");
                ctx.getPipeline().get(HandshakeInitializationHandler.class.getName());
                ClientAuthenticationHandler handler = (ClientAuthenticationHandler) ctx.getPipeline()
                    .get(ClientAuthenticationHandler.class.getName());
                handler.setSeed(seed);
            }

        });
        logger.info("send handshake initialization packet to : {}", ctx.getChannel());
    }
}
