package deobf;

import java.nio.charset.Charset;
import wecui.WorldEditCUI;
import wecui.render.RenderEntity;
import wecui.render.RenderHooks;
import java.util.Map;

import net.minecraft.client.Minecraft;
import wecui.Updater;
import wecui.event.ChannelEvent;
import wecui.obfuscation.DataPacketList;
import wecui.obfuscation.Obfuscation;
import wecui.render.region.CuboidRegion;

/**
 * Main ModLoader class. Initializes the mod, enabling CUI communication 
 * between server and client, in addition to enabling rendering.
 * 
 * TODO: Move Configuration.yml to WEConfig.yml
 * 
 * @author lahwran
 * @author yetanotherx
 */
public class mod_WorldEditCUI extends BaseMod {

    protected WorldEditCUI controller;
    protected WorldClient lastWorld;
    protected EntityPlayerSP lastPlayer;
    protected boolean gameStarted = false;
    public final static Charset UTF_8_CHARSET = Charset.forName("UTF-8");

    public mod_WorldEditCUI() {
        this.controller = new WorldEditCUI(ModLoader.getMinecraftInstance());
        this.controller.initialize();

        ModLoader.registerEntityID(RenderEntity.class, "CUI", ModLoader.getUniqueEntityId());

        ModLoader.setInGameHook(this, true, true);
        ModLoader.registerPacketChannel(this, "WECUI");
    }

    @Override
    public void load() {
    }

    /**
     * Checks if the world or player has changed from the last time we checked.
     * If it's changed, spawn a new render entity and update accordingly.
     * 
     * It also checks if initialization tasks have been done, such as checking
     * for updates, resetting the region, and registering reflection for the
     * outgoing command handler.
     * 
     * @param partialticks
     * @param mc
     * @return 
     */
    @Override
    public boolean onTickInGame(float partialticks, Minecraft mc) {

        if (Obfuscation.getWorld(mc) != lastWorld || Obfuscation.getPlayer(mc) != lastPlayer) {
            controller.getObfuscation().spawnEntity();

            lastWorld = Obfuscation.getWorld(mc);
            lastPlayer = Obfuscation.getPlayer(mc);

            if (!gameStarted) {
                gameStarted = true;

                new Updater(controller).start();
                this.controller.setSelection(new CuboidRegion(controller));

                DataPacketList.register(controller);
            }
        }
        return true;
    }

    /**
     * Called when the client receives a CUI packet from the server. 
     * @param handler
     * @param packet 
     */
    @Override
    public void clientCustomPayload(NetClientHandler handler, Packet250CustomPayload packet) {
        ChannelEvent channelevent = new ChannelEvent(controller, new String(Obfuscation.getBytesFromPacket(packet), UTF_8_CHARSET));
        controller.getEventManager().callEvent(channelevent);
    }

    /**
     * Called when the client connects to a server. Sends the protocol version 
     * in a channel message to the server.
     * @param handler 
     */
    @Override
    public void clientConnect(NetClientHandler handler) {
        byte[] buffer = ("v|" + WorldEditCUI.protocolVersion).getBytes(UTF_8_CHARSET);
        ModLoader.clientSendPacket(Obfuscation.newPayloadPacket("WECUI", buffer.length, buffer));
    }

    /**
     * Tells the renderer that all RenderEntity's should be rendered with the
     * RenderHooks class.
     * @param map 
     */
    @Override
    @SuppressWarnings("unchecked")
    public void addRenderer(Map map) {
        map.put(RenderEntity.class, new RenderHooks(controller));
    }

    @Override
    public String getVersion() {
        return WorldEditCUI.getVersion();
    }
}

@@ -901,16 +901,61 @@
 UTF-8%22);
+%0A    protected int entityUpdateTickCount = 0;
 %0A%0A    pu
@@ -2379,32 +2379,287 @@
 ;%0A            %7D%0A
+        %7D else %7B%0A            if( entityUpdateTickCount %3E 500 ) %7B%0A                entityUpdateTickCount = 0;%0A                Obfuscation.setEntityPositionToPlayer(mc, lastPlayer);%0A            %7D else %7B%0A                ++entityUpdateTickCount;%0A            %7D%0A
         %7D%0A      

Update the entity to the player's position every 500 ticks. The game tends to throw up when trying to render an entity 5000 blocks away, but it's not necessary to update every tick, as the position of the entity really doesn't matter.