package com.github.lunatrius.schematica.handler.client;

import com.github.lunatrius.schematica.Schematica;
import com.github.lunatrius.schematica.client.gui.GuiSchematicControl;
import com.github.lunatrius.schematica.client.gui.GuiSchematicLoad;
import com.github.lunatrius.schematica.client.gui.GuiSchematicSave;
import com.github.lunatrius.schematica.reference.Reference;
import com.github.lunatrius.schematica.world.SchematicWorld;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityClientPlayerMP;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraftforge.common.ForgeHooks;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;

import static cpw.mods.fml.common.gameevent.InputEvent.KeyInputEvent;
import static cpw.mods.fml.common.gameevent.InputEvent.MouseInputEvent;

public class KeyInputHandler {
	public static final String CATEGORY = "schematica.key.category";
	public static final String LOAD = "schematica.key.load";
	public static final String SAVE = "schematica.key.save";
	public static final String CONTROL = "schematica.key.control";

	private static final KeyBinding KEY_BINDING_LOAD = new KeyBinding(LOAD, Keyboard.KEY_DIVIDE, CATEGORY);
	private static final KeyBinding KEY_BINDING_SAVE = new KeyBinding(SAVE, Keyboard.KEY_MULTIPLY, CATEGORY);
	private static final KeyBinding KEY_BINDING_CONTROL = new KeyBinding(CONTROL, Keyboard.KEY_SUBTRACT, CATEGORY);

	public static final KeyBinding[] KEY_BINDINGS = new KeyBinding[] {
			KEY_BINDING_LOAD, KEY_BINDING_SAVE, KEY_BINDING_CONTROL
	};

	private final Minecraft minecraft = Minecraft.getMinecraft();

	@SubscribeEvent
	public void onKeyInput(KeyInputEvent event) {
		for (KeyBinding keyBinding : KEY_BINDINGS) {
			if (keyBinding.isPressed()) {
				if (this.minecraft.currentScreen == null) {
					GuiScreen guiScreen = null;
					if (keyBinding == KEY_BINDING_LOAD) {
						guiScreen = new GuiSchematicLoad(this.minecraft.currentScreen);
					} else if (keyBinding == KEY_BINDING_SAVE) {
						guiScreen = new GuiSchematicSave(this.minecraft.currentScreen);
					} else if (keyBinding == KEY_BINDING_CONTROL) {
						guiScreen = new GuiSchematicControl(this.minecraft.currentScreen);
					}

					if (guiScreen != null) {
						this.minecraft.displayGuiScreen(guiScreen);
					}
				}
			}
		}
	}

	@SubscribeEvent
	public void onMouseInput(MouseInputEvent event) {
		if (this.minecraft.gameSettings.keyBindPickBlock.isPressed()) {
			try {
				final SchematicWorld schematic = Schematica.proxy.getActiveSchematic();

				if (schematic != null) {
					final boolean revert = pickBlock(schematic, 1.0f);
					if (revert) {
						final int eventButton = Mouse.getEventButton();
						KeyBinding.onTick(eventButton - 100);
					}
				}
			} catch (Exception e) {
				Reference.logger.error("Could not pick block!", e);
			}
		}
	}

	private boolean pickBlock(final SchematicWorld schematic, final float partialTicks) {
		final MovingObjectPosition objectMouseOver = rayTrace(schematic, partialTicks);
		boolean revert = false;

		// Minecraft.func_147112_ai
		if (objectMouseOver != null) {
			final EntityClientPlayerMP player = this.minecraft.thePlayer;

			if (objectMouseOver.typeOfHit == MovingObjectPosition.MovingObjectType.MISS) {
				revert = true;
			}

			if (!ForgeHooks.onPickBlock(objectMouseOver, player, schematic)) {
				return revert;
			}

			if (player.capabilities.isCreativeMode) {
				final int slot = player.inventoryContainer.inventorySlots.size() - 9 + player.inventory.currentItem;
				this.minecraft.playerController.sendSlotPacket(player.inventory.getStackInSlot(player.inventory.currentItem), slot);
			}
		}

		return revert;
	}

	private MovingObjectPosition rayTrace(final SchematicWorld schematic, final float partialTicks) {
		final EntityLivingBase renderViewEntity = this.minecraft.renderViewEntity;
		final double blockReachDistance = this.minecraft.playerController.getBlockReachDistance();

		final double posX = renderViewEntity.posX;
		final double posY = renderViewEntity.posY;
		final double posZ = renderViewEntity.posZ;

		renderViewEntity.posX -= schematic.position.x;
		renderViewEntity.posY -= schematic.position.y;
		renderViewEntity.posZ -= schematic.position.z;

		final Vec3 vecPosition = renderViewEntity.getPosition(partialTicks);
		final Vec3 vecLook = renderViewEntity.getLook(partialTicks);
		final Vec3 vecExtendedLook = vecPosition.addVector(vecLook.xCoord * blockReachDistance, vecLook.yCoord * blockReachDistance, vecLook.zCoord * blockReachDistance);

		renderViewEntity.posX = posX;
		renderViewEntity.posY = posY;
		renderViewEntity.posZ = posZ;

		return schematic.func_147447_a(vecPosition, vecExtendedLook, false, false, true);
	}
}

@@ -2767,16 +2767,43 @@
 matic();
+%0A%09%09%09%09boolean revert = true;
 %0A%0A%09%09%09%09if
@@ -2834,22 +2834,8 @@
 %09%09%09%09
-final boolean 
 reve
@@ -2864,24 +2864,30 @@
 ic, 1.0f);%0A%09
+%09%09%09%7D%0A%0A
 %09%09%09%09if (reve
@@ -2888,25 +2888,24 @@
  (revert) %7B%0A
-%09
 %09%09%09%09%09final i
@@ -2945,17 +2945,16 @@
 tton();%0A
-%09
 %09%09%09%09%09Key
@@ -2988,23 +2988,16 @@
 - 100);%0A
-%09%09%09%09%09%7D%0A
 %09%09%09%09%7D%0A%09%09

Make sure to revert the key press if there is no schematic loaded.