package com.zivilon.cindercore_modlist.mixins;

import java.lang.reflect.Field;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import cpw.mods.fml.common.network.handshake.FMLHandshakeMessage;
import cpw.mods.fml.common.network.handshake.FMLHandshakeServerState;
import cpw.mods.fml.common.network.handshake.NetworkDispatcher;
import cpw.mods.fml.common.network.handshake.FMLHandshakeMessage.ModList;
import cpw.mods.fml.common.network.NetworkRegistry;
import net.minecraft.entity.player.EntityPlayerMP;
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.Overwrite;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.relauncher.Side;
import java.util.Map;
import java.util.UUID;
import cpw.mods.fml.common.registry.GameData;
import cpw.mods.fml.common.registry.GameData.GameDataSnapshot;

import com.zivilon.cindercore_modlist.CinderCoreModlist;
import com.zivilon.cindercore_modlist.util.HandshakeUtils;
import com.zivilon.cindercore.network.PacketInterceptor;

@Mixin(targets = "cpw.mods.fml.common.network.handshake.FMLHandshakeServerState$3")
public abstract class MixinFMLHandshakeServerStateWAITINGCACK {

    @Overwrite
    public FMLHandshakeServerState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
    {
        if (!ctx.channel().attr(NetworkDispatcher.IS_LOCAL).get())
        {
            System.out.println("[CinderCore] Initiating modified handshake WAITINGCACK");
            // Get the player instance
            EntityPlayerMP player = null;
            try {
                // Performance loss from reflection doesn't matter on login
                NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();

                Field playerField = NetworkDispatcher.class.getDeclaredField("player");
                playerField.setAccessible(true);
                player = (EntityPlayerMP) playerField.get(dispatcher);
            } catch (NoSuchFieldException | IllegalAccessException e) {
                System.out.println("[CinderModlistCore] Reflection error in MixinFMLHandshakeServerStateWAITINGCACK");
                e.printStackTrace();
            }

            UUID uuid = player.getUniqueID();
            CinderCoreModlist.generatePlayerItemFallbackMap(uuid);
            CinderCoreModlist.generatePlayerEntityFallbackMap(uuid);
            CinderCoreModlist.generatePlayerCustomFallbackMap(uuid);
            GameDataSnapshot itemlist = GameData.buildItemDataList();
            Map<Integer, Integer> fallbacks = CinderCoreModlist.getPlayerItemFallbacks(uuid);

            // Modifying the Map
            itemlist = HandshakeUtils.modifyGameDataSnapshot(itemlist, fallbacks);

            ctx.writeAndFlush(new FMLHandshakeMessage.ModIdData(itemlist)).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
        }
        FMLHandshakeServerState currentState = FMLHandshakeServerState.WAITINGCACK;

        FMLHandshakeMessage new_msg = new FMLHandshakeMessage.HandshakeAck(currentState.ordinal());
/*        if (new_msg instanceof FMLHandshakeMessage.ClientHello) System.out.println("[CinderModlistCore] Sending instance of ClientHello");
        if (new_msg instanceof FMLHandshakeMessage.ModIdData) System.out.println("[CinderModlistCore] Sending instance of ModIdData");
        if (new_msg instanceof FMLHandshakeMessage.HandshakeAck) System.out.println("[CinderModlistCore] Sending instance of HandshakeAck");
        System.out.println("Sent");*/

        ctx.writeAndFlush(new_msg).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
        NetworkRegistry.INSTANCE.fireNetworkHandshake(ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get(), Side.SERVER);
        return FMLHandshakeServerState.COMPLETE;
    }
}

