/*
 * Decompiled with CFR 0.152.
 * 
 * Could not load the following classes:
 *  io.netty.channel.ChannelFuture
 *  io.netty.channel.ChannelFutureListener
 *  io.netty.channel.ChannelHandler
 *  io.netty.channel.ChannelHandlerContext
 *  io.netty.channel.ChannelPipeline
 *  io.netty.handler.proxy.Socks4ProxyHandler
 *  io.netty.handler.proxy.Socks5ProxyHandler
 *  io.netty.handler.timeout.TimeoutException
 *  meteordevelopment.orbit.ICancellable
 *  net.minecraft.class_12239
 *  net.minecraft.class_124
 *  net.minecraft.class_2535
 *  net.minecraft.class_2548
 *  net.minecraft.class_2561
 *  net.minecraft.class_2596
 *  net.minecraft.class_2598
 *  net.minecraft.class_5250
 *  net.minecraft.class_8042
 *  net.minecraft.class_8762
 *  org.jetbrains.annotations.Nullable
 *  org.spongepowered.asm.mixin.Mixin
 *  org.spongepowered.asm.mixin.injection.At
 *  org.spongepowered.asm.mixin.injection.At$Shift
 *  org.spongepowered.asm.mixin.injection.Inject
 *  org.spongepowered.asm.mixin.injection.callback.CallbackInfo
 *  org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable
 */
package meteordevelopment.meteorclient.mixin;

import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.proxy.Socks4ProxyHandler;
import io.netty.handler.proxy.Socks5ProxyHandler;
import io.netty.handler.timeout.TimeoutException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Iterator;
import meteordevelopment.meteorclient.MeteorClient;
import meteordevelopment.meteorclient.events.packets.PacketEvent;
import meteordevelopment.meteorclient.events.world.ServerConnectEndEvent;
import meteordevelopment.meteorclient.systems.modules.Modules;
import meteordevelopment.meteorclient.systems.modules.misc.AntiPacketKick;
import meteordevelopment.meteorclient.systems.modules.world.HighwayBuilder;
import meteordevelopment.meteorclient.systems.proxies.Proxies;
import meteordevelopment.meteorclient.systems.proxies.Proxy;
import meteordevelopment.orbit.ICancellable;
import net.minecraft.class_12239;
import net.minecraft.class_124;
import net.minecraft.class_2535;
import net.minecraft.class_2548;
import net.minecraft.class_2561;
import net.minecraft.class_2596;
import net.minecraft.class_2598;
import net.minecraft.class_5250;
import net.minecraft.class_8042;
import net.minecraft.class_8762;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(value={class_2535.class})
public abstract class ClientConnectionMixin {
    @Inject(method={"method_10770(Lio/netty/channel/ChannelHandlerContext;Lnet/minecraft/class_2596;)V"}, at={@At(value="INVOKE", target="Lnet/minecraft/class_2535;method_10759(Lnet/minecraft/class_2596;Lnet/minecraft/class_2547;)V", shift=At.Shift.BEFORE)}, cancellable=true)
    private void onHandlePacket(ChannelHandlerContext channelHandlerContext, class_2596<?> packet, CallbackInfo ci) {
        if (packet instanceof class_8042) {
            class_8042 bundle = (class_8042)packet;
            Iterator it = bundle.method_48324().iterator();
            while (it.hasNext()) {
                if (!((PacketEvent.Receive)MeteorClient.EVENT_BUS.post((ICancellable)new PacketEvent.Receive((class_2596)it.next(), (class_2535)this))).isCancelled()) continue;
                it.remove();
            }
        } else if (((PacketEvent.Receive)MeteorClient.EVENT_BUS.post((ICancellable)new PacketEvent.Receive(packet, (class_2535)this))).isCancelled()) {
            ci.cancel();
        }
    }

    @Inject(method={"method_10747(Lnet/minecraft/class_2561;)V"}, at={@At(value="HEAD")})
    private void disconnect(class_2561 disconnectReason, CallbackInfo ci) {
        if (Modules.get().get(HighwayBuilder.class).isActive()) {
            class_5250 text = class_2561.method_43470((String)"%n%n%s[%sHighway Builder%s] Statistics:%n".formatted(class_124.field_1080, class_124.field_1078, class_124.field_1080));
            text.method_10852((class_2561)Modules.get().get(HighwayBuilder.class).getStatsText());
            ((class_5250)disconnectReason).method_10852((class_2561)text);
        }
    }

    @Inject(method={"method_52271(Ljava/net/InetSocketAddress;Lnet/minecraft/class_12239;Lnet/minecraft/class_2535;)Lio/netty/channel/ChannelFuture;"}, at={@At(value="HEAD")})
    private static void onConnect(InetSocketAddress address, class_12239 backend, class_2535 connection, CallbackInfoReturnable<ChannelFuture> cir) {
        MeteorClient.EVENT_BUS.post((Object)ServerConnectEndEvent.get(address));
    }

    @Inject(at={@At(value="HEAD")}, method={"method_10752(Lnet/minecraft/class_2596;Lio/netty/channel/ChannelFutureListener;)V"}, cancellable=true)
    private void onSendPacketHead(class_2596<?> packet, @Nullable ChannelFutureListener channelFutureListener, CallbackInfo ci) {
        if (((PacketEvent.Send)MeteorClient.EVENT_BUS.post((ICancellable)new PacketEvent.Send(packet, (class_2535)this))).isCancelled()) {
            ci.cancel();
        }
    }

    @Inject(method={"method_10752(Lnet/minecraft/class_2596;Lio/netty/channel/ChannelFutureListener;)V"}, at={@At(value="TAIL")})
    private void onSendPacketTail(class_2596<?> packet, @Nullable ChannelFutureListener channelFutureListener, CallbackInfo ci) {
        MeteorClient.EVENT_BUS.post((Object)new PacketEvent.Sent(packet, (class_2535)this));
    }

    @Inject(method={"exceptionCaught"}, at={@At(value="HEAD")}, cancellable=true)
    private void exceptionCaught(ChannelHandlerContext context, Throwable throwable, CallbackInfo ci) {
        AntiPacketKick apk = Modules.get().get(AntiPacketKick.class);
        if (!(throwable instanceof TimeoutException) && !(throwable instanceof class_2548) && apk.catchExceptions()) {
            if (apk.logExceptions.get().booleanValue()) {
                apk.warning("Caught exception: %s", throwable);
            }
            ci.cancel();
        }
    }

    @Inject(method={"method_48311"}, at={@At(value="RETURN")})
    private static void onAddHandlers(ChannelPipeline pipeline, class_2598 side, boolean local, class_8762 packetSizeLogger, CallbackInfo ci) {
        if (side != class_2598.field_11942 || local) {
            return;
        }
        Proxy proxy = Proxies.get().getEnabled();
        if (proxy == null) {
            return;
        }
        switch (proxy.type.get()) {
            case Socks4: {
                pipeline.addFirst(new ChannelHandler[]{new Socks4ProxyHandler((SocketAddress)new InetSocketAddress(proxy.address.get(), (int)proxy.port.get()), proxy.username.get())});
                break;
            }
            case Socks5: {
                pipeline.addFirst(new ChannelHandler[]{new Socks5ProxyHandler((SocketAddress)new InetSocketAddress(proxy.address.get(), (int)proxy.port.get()), proxy.username.get(), proxy.password.get())});
            }
        }
    }
}

