package protocolsupport.protocol.pipeline.version.v_legacy;

import org.bukkit.ChatColor;

import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.DecoderException;
import protocolsupport.api.ProtocolType;
import protocolsupport.api.ProtocolVersion;
import protocolsupport.api.events.ServerPingResponseEvent;
import protocolsupport.protocol.packet.handler.AbstractStatusListener;
import protocolsupport.protocol.serializer.StringSerializer;
import protocolsupport.utils.netty.Allocator;

@Sharable
public class LegacyLoginAndPingHandler extends SimpleChannelInboundHandler<ByteBuf> {

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, ByteBuf input)  {
		int packetId = input.readUnsignedByte();
		if (packetId == 0xFE) {
			writePing(ctx.channel());
		} else if (packetId == 0x02) {
			writeLoginKick(ctx.channel());
		} else {
			throw new DecoderException("Unknown packet id "+packetId + " in legacy login and ping handler");
		}
	}

	private static void writeLoginKick(Channel channel) {
		ByteBuf buf = Allocator.allocateBuffer();
		try {
			buf.writeByte(0xFF);
			StringSerializer.writeString(buf, ProtocolVersion.getOldest(ProtocolType.PC), "Outdated client");
			channel.pipeline().firstContext().writeAndFlush(buf).addListener(ChannelFutureListener.CLOSE);
			buf = null;
		} finally {
			if (buf != null) {
				buf.release();
			}
		}
	}

	private static void writePing(Channel channel) {
		AbstractStatusListener.executeTask(() -> {
			ServerPingResponseEvent revent = AbstractStatusListener.createResponse(channel);
			ByteBuf buf = Allocator.allocateBuffer();
			try {
				buf.writeByte(0xFF);
				StringSerializer.writeString(buf, ProtocolVersion.getOldest(ProtocolType.PC), ChatColor.stripColor(revent.getMotd())+"§"+revent.getPlayers().size()+"§"+revent.getMaxPlayers());
				channel.pipeline().firstContext().writeAndFlush(buf).addListener(ChannelFutureListener.CLOSE);
				buf = null;
			} finally {
				if (buf != null) {
					buf.release();
				}
			}
		});
	}

}

@@ -2038,16 +2038,46 @@
 ));%0A%09%09%09%09
+ChannelHandlerContext first = 
 channel.
@@ -2093,32 +2093,69 @@
 ).firstContext()
+;%0A%09%09%09%09if (first != null) %7B%0A%09%09%09%09%09first
 .writeAndFlush(b
@@ -2204,16 +2204,17 @@
 E);%0A%09%09%09%09
+%09
 buf = nu
@@ -2217,16 +2217,22 @@
 = null;%0A
+%09%09%09%09%7D%0A
 %09%09%09%7D fin

Check if pipeline still exist before trying to send data