package com.zivilon.cindercore.mixins;

import cpw.mods.fml.common.network.NetworkRegistry;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.common.network.internal.FMLNetworkHandler;
import cpw.mods.fml.common.registry.GameData;
import cpw.mods.fml.common.registry.GameData.GameDataSnapshot;
import cpw.mods.fml.common.registry.EntityRegistry;
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
import cpw.mods.fml.common.network.internal.FMLMessage;

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

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.UUID;
import net.minecraft.block.Block;
import net.minecraft.entity.ai.attributes.ServersideAttributeMap;
import net.minecraft.entity.boss.EntityDragon;
import net.minecraft.entity.item.EntityBoat;
import net.minecraft.entity.item.EntityEnderCrystal;
import net.minecraft.entity.item.EntityEnderEye;
import net.minecraft.entity.item.EntityEnderPearl;
import net.minecraft.entity.item.EntityExpBottle;
import net.minecraft.entity.item.EntityFallingBlock;
import net.minecraft.entity.item.EntityFireworkRocket;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.item.EntityItemFrame;
import net.minecraft.entity.item.EntityMinecart;
import net.minecraft.entity.item.EntityPainting;
import net.minecraft.entity.item.EntityTNTPrimed;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.passive.IAnimals;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.entity.projectile.EntityEgg;
import net.minecraft.entity.projectile.EntityFireball;
import net.minecraft.entity.projectile.EntityFishHook;
import net.minecraft.entity.projectile.EntityPotion;
import net.minecraft.entity.projectile.EntitySmallFireball;
import net.minecraft.entity.projectile.EntitySnowball;
import net.minecraft.entity.projectile.EntityWitherSkull;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.EntityLeashKnot;
import net.minecraft.entity.EntityTrackerEntry;
import net.minecraft.init.Items;
import net.minecraft.item.ItemMap;
import net.minecraft.item.ItemStack;
import net.minecraft.network.Packet;
import net.minecraft.network.play.server.S04PacketEntityEquipment;
import net.minecraft.network.play.server.S0APacketUseBed;
import net.minecraft.network.play.server.S0CPacketSpawnPlayer;
import net.minecraft.network.play.server.S0EPacketSpawnObject;
import net.minecraft.network.play.server.S0FPacketSpawnMob;
import net.minecraft.network.play.server.S10PacketSpawnPainting;
import net.minecraft.network.play.server.S11PacketSpawnExperienceOrb;
import net.minecraft.network.play.server.S12PacketEntityVelocity;
import net.minecraft.network.play.server.S14PacketEntity;
import net.minecraft.network.play.server.S18PacketEntityTeleport;
import net.minecraft.network.play.server.S19PacketEntityHeadLook;
import net.minecraft.network.play.server.S1BPacketEntityAttach;
import net.minecraft.network.play.server.S1CPacketEntityMetadata;
import net.minecraft.network.play.server.S1DPacketEntityEffect;
import net.minecraft.network.play.server.S20PacketEntityProperties;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.MathHelper;
import net.minecraft.world.storage.MapData;

import org.apache.logging.log4j.Logger;

import com.zivilon.cindercore.interfaces.IFMLNetworkHandlerMixin;
import com.zivilon.cindercore.mixins.MixinFMLNetworkHandler;
import com.zivilon.cindercore.util.NetworkUtil;

@Mixin(EntityTrackerEntry.class)
public abstract class MixinEntityTrackerEntry {
    private EntityPlayerMP capturedPlayer;

    @Shadow public Entity myEntity;
    @Shadow public int lastHeadMotion;


    @Inject(method = "tryStartWachingThis", at = @At("HEAD"), locals = LocalCapture.CAPTURE_FAILHARD)
    private void onTryStartWatchingThis(EntityPlayerMP player, CallbackInfo ci) {
        this.capturedPlayer = player;
    }

    @Redirect(method = "tryStartWachingThis", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/EntityTrackerEntry;func_151260_c()Lnet/minecraft/network/Packet;"))
    private Packet redirectFunc_151260_c(EntityTrackerEntry instance) {
        return this.customFunc_151260_c(this.capturedPlayer);
    }

    private Packet customFunc_151260_c(EntityPlayerMP player) {
        if (this.myEntity.isDead) {
            System.err.println("Fetching addPacket for removed entity");
        }

       Packet pkt = NetworkUtil.getEntitySpawningPacket(myEntity, player);

       if (pkt != null) {
            return pkt;
        }
        if (this.myEntity instanceof EntityItem) {
            return new S0EPacketSpawnObject(this.myEntity, 2, 1);
        } else if (this.myEntity instanceof EntityPlayerMP) {
            return new S0CPacketSpawnPlayer((EntityPlayer)this.myEntity);
        } else if (this.myEntity instanceof EntityMinecart) {
            EntityMinecart entityminecart = (EntityMinecart)this.myEntity;
            return new S0EPacketSpawnObject(this.myEntity, 10, entityminecart.getMinecartType());
        } else if (this.myEntity instanceof EntityBoat) {
            return new S0EPacketSpawnObject(this.myEntity, 1);
        } else if (!(this.myEntity instanceof IAnimals) && !(this.myEntity instanceof EntityDragon)) {
            if (this.myEntity instanceof EntityFishHook) {
                EntityPlayer entityplayer = ((EntityFishHook)this.myEntity).field_146042_b;
                return new S0EPacketSpawnObject(this.myEntity, 90, entityplayer != null ? entityplayer.getEntityId() : this.myEntity.getEntityId());
            } else if (this.myEntity instanceof EntityArrow) {
                Entity entity = ((EntityArrow)this.myEntity).shootingEntity;
                return new S0EPacketSpawnObject(this.myEntity, 60, entity != null ? entity.getEntityId() : this.myEntity.getEntityId());
            } else if (this.myEntity instanceof EntitySnowball) {
                return new S0EPacketSpawnObject(this.myEntity, 61);
            } else if (this.myEntity instanceof EntityPotion) {
                return new S0EPacketSpawnObject(this.myEntity, 73, ((EntityPotion)this.myEntity).getPotionDamage());
            } else if (this.myEntity instanceof EntityExpBottle) {
                return new S0EPacketSpawnObject(this.myEntity, 75);
            } else if (this.myEntity instanceof EntityEnderPearl) {
                return new S0EPacketSpawnObject(this.myEntity, 65);
            } else if (this.myEntity instanceof EntityEnderEye) {
                return new S0EPacketSpawnObject(this.myEntity, 72);
            } else if (this.myEntity instanceof EntityFireworkRocket) {
                return new S0EPacketSpawnObject(this.myEntity, 76);
            } else {
                S0EPacketSpawnObject s0epacketspawnobject;

                if (this.myEntity instanceof EntityFireball) {
                    EntityFireball entityfireball = (EntityFireball)this.myEntity;
                    s0epacketspawnobject = null;
                    byte b0 = 63;

                    if (this.myEntity instanceof EntitySmallFireball) {
                        b0 = 64;
                    } else if (this.myEntity instanceof EntityWitherSkull) {
                        b0 = 66;
                    }

                    if (entityfireball.shootingEntity != null) {
                        s0epacketspawnobject = new S0EPacketSpawnObject(this.myEntity, b0, ((EntityFireball)this.myEntity).shootingEntity.getEntityId());
                    } else {
                        s0epacketspawnobject = new S0EPacketSpawnObject(this.myEntity, b0, 0);
                    }

                    s0epacketspawnobject.func_149003_d((int)(entityfireball.accelerationX * 8000.0D));
                    s0epacketspawnobject.func_149000_e((int)(entityfireball.accelerationY * 8000.0D));
                    s0epacketspawnobject.func_149007_f((int)(entityfireball.accelerationZ * 8000.0D));
                    return s0epacketspawnobject;
                } else if (this.myEntity instanceof EntityEgg) {
                    return new S0EPacketSpawnObject(this.myEntity, 62);
                } else if (this.myEntity instanceof EntityTNTPrimed) {
                    return new S0EPacketSpawnObject(this.myEntity, 50);
                } else if (this.myEntity instanceof EntityEnderCrystal) {
                    return new S0EPacketSpawnObject(this.myEntity, 51);
                } else if (this.myEntity instanceof EntityFallingBlock) {
                    EntityFallingBlock entityfallingblock = (EntityFallingBlock)this.myEntity;
                    return new S0EPacketSpawnObject(this.myEntity, 70, Block.getIdFromBlock(entityfallingblock.func_145805_f()) | entityfallingblock.field_145814_a << 16);
                } else if (this.myEntity instanceof EntityPainting) {
                    return new S10PacketSpawnPainting((EntityPainting)this.myEntity);
                } else if (this.myEntity instanceof EntityItemFrame) {
                    EntityItemFrame entityitemframe = (EntityItemFrame)this.myEntity;
                    s0epacketspawnobject = new S0EPacketSpawnObject(this.myEntity, 71, entityitemframe.hangingDirection);
                    s0epacketspawnobject.func_148996_a(MathHelper.floor_float((float)(entityitemframe.field_146063_b * 32)));
                    s0epacketspawnobject.func_148995_b(MathHelper.floor_float((float)(entityitemframe.field_146064_c * 32)));
                    s0epacketspawnobject.func_149005_c(MathHelper.floor_float((float)(entityitemframe.field_146062_d * 32)));
                    return s0epacketspawnobject;
                } else if (this.myEntity instanceof EntityLeashKnot) {
                    EntityLeashKnot entityleashknot = (EntityLeashKnot)this.myEntity;
                    s0epacketspawnobject = new S0EPacketSpawnObject(this.myEntity, 77);
                    s0epacketspawnobject.func_148996_a(MathHelper.floor_float((float)(entityleashknot.field_146063_b * 32)));
                    s0epacketspawnobject.func_148995_b(MathHelper.floor_float((float)(entityleashknot.field_146064_c * 32)));
                    s0epacketspawnobject.func_149005_c(MathHelper.floor_float((float)(entityleashknot.field_146062_d * 32)));
                    return s0epacketspawnobject;
                } else if (this.myEntity instanceof EntityXPOrb) {
                    return new S11PacketSpawnExperienceOrb((EntityXPOrb)this.myEntity);
                } else {
                    throw new IllegalArgumentException("Don\'t know how to add " + this.myEntity.getClass() + "!");
                }
            }
        } else {
            this.lastHeadMotion = MathHelper.floor_float(this.myEntity.getRotationYawHead() * 256.0F / 360.0F);
            return new S0FPacketSpawnMob((EntityLivingBase)this.myEntity);
        }
    }
}
