package me.sucixr.kitin.network.bandwidth;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufHolder;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;

/**
 * Netty outbound handler that tallies the byte size of every frame written toward a client into
 * the global {@link BandwidthMeter}. Sits at the pipeline head, so by the time a write reaches it
 * the message is the final framed {@link ByteBuf} about to hit the socket — i.e. true on-wire size.
 *
 * <p>Sharable is intentionally NOT set: one instance per connection pipeline, matching Paper's
 * per-connection handler style. The work is a single field read + atomic add, negligible overhead.
 */
public final class OutboundByteCounter extends ChannelOutboundHandlerAdapter {

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        int bytes = readableBytes(msg);
        if (bytes > 0) {
            BandwidthMeter.recordOutbound(bytes);
        }
        super.write(ctx, msg, promise);
    }

    private static int readableBytes(Object msg) {
        if (msg instanceof ByteBuf buf) {
            return buf.readableBytes();
        }
        if (msg instanceof ByteBufHolder holder) {
            return holder.content().readableBytes();
        }
        return 0;
    }
}
