package net.minecraft.src.weasel.lang;


import net.minecraft.src.NBTTagCompound;
import net.minecraft.src.PC_INBT;
import net.minecraft.src.weasel.InstructionList;
import net.minecraft.src.weasel.Weasel;
import net.minecraft.src.weasel.exception.WeaselRuntimeException;
import net.minecraft.src.weasel.exception.PauseRequestedException;


/**
 * Weasel instruction
 * 
 * @author MightyPork
 * @copy (c) 2012
 */
public abstract class Instruction implements PC_INBT {

	private int address = -1;

	/**
	 * Execute the instruction
	 * 
	 * @param engine the weasel engine
	 * @param instructionList the instruction list the instruction is in
	 * @throws PauseRequestedException thrown at the end of instruction if
	 *             Weasel Engine should pause program and wait for external
	 *             resume call.
	 * @throws WeaselRuntimeException thrown if execution of this instruction
	 *             failed.
	 */
	public abstract void execute(Weasel engine, InstructionList instructionList) throws PauseRequestedException, WeaselRuntimeException;

	/**
	 * Set instruction address in {@link InstructionList}
	 * 
	 * @param address address
	 * @return this
	 */
	public final Instruction setAddress(int address) {
		this.address = address;
		return this;
	}

	/**
	 * Get {@link InstructionList} address in {@link InstructionList}
	 * 
	 * @return address
	 */
	public final int getAddress() {
		return this.address;
	}

	private InstructionType type;

	/**
	 * Get isntruction type
	 * @return type
	 */
	public final InstructionType getType() {
		return type;
	}

	/**
	 * Set instruction type
	 * @param type
	 * @return this
	 */
	public final Instruction setType(InstructionType type) {
		this.type = type;
		return this;
	}
	
	

	public static final NBTTagCompound saveInstructionToNBT(Instruction instruction, NBTTagCompound tag) {
		tag.setInteger("type", instruction.getType().index);
		instruction.writeToNBT(tag);
		return tag;
	}

	public static final Instruction loadInstructionFromNBT(NBTTagCompound tag) {
		switch (tag.getInteger("type")) {
			case 1:
				//return (Instruction) new InstructionLabel().loadFromNBT(tag);
		}
		return null;
	}


	/**
	 * Type of an instruction
	 * 
	 * @author MightyPork
	 */
	protected enum InstructionType {

		LABEL(1), CALL(2), FUNCTION(3), SET(4), PUSH(5), POP(6), IF(7), CALL_HW(8), END(9), PAUSE(10);

		private InstructionType(int i) {
			index = i;
		}

		public int index;
	}

}
