/*
 * Created on 26.02.2004 17:53:38
 *
 * Multimediale Algorithmen und Datenstrukturen Assessments
 */
package mauda.feedback.types;

import mauda.*;
import mauda.feedback.FeedbackExercise;
import mauda.feedback.FeedbackObject;
import mauda.feedback.SimpleFeedback;
import mauda.feedback.select.*;
import mauda.operation.*;

import java.util.*;

/**
 * Provides the logic for <i>Error Flagging</i>
 * 
 * @author Markus Krebs
 */
public class ErrorFlagging extends SimpleFeedback {
	
	private static final int type = FeedbackSelector.ERROR_FLAGGING;

	private static final String specialGetNext = "Get next ...";
	private static final String specialFinishOp = "Finish Operation ...";
	private static final String specialFinishEx = "Finish exercise ...";
	
	/**
	 * Creates a ErrorFlagging-Feedback
	 * @param exercise
	 */
	public ErrorFlagging(FeedbackExercise exercise) {
		super(exercise);
		specialState = specialGetNext;
	}
	
	protected void jumpEvent(int delta) {
		super.jumpEvent(delta);
		updateBackForwardButtons();
		//System.out.println("IF&EC: opDelta = "+opCounter);
		//System.out.println("       todoPosition = "+todoPosition);
		if(counter>=0) {
			OperationRecorder or = exercise.getOperationRecorder();
			SimpleOperation so = (SimpleOperation)or.getCurrentOperation();
			String msg = feedbackGenerator.genMessage(
						"information.gif",
						"<b>Jump</b> to "+so.out());
			if(so instanceof SubOperation) {
				msg = makeNextLink(msg);
				displayMessage("FEEDBACK", msg);
				setSpecialButtonText(specialFinishOp);
				specialState = specialFinishOp;
				// ALT
				//counter--; interactiveEvent();
				// NEU
				updateBackForwardButtons();
				FeedbackObject fo = callKB();
			} else if (so instanceof Operation) {
				displayMessage("FEEDBACK", msg);
				setSpecialButtonText(specialFinishOp);
				specialState = specialGetNext;
				todoPosition--;	// Wird bei interactiveEvent wieder erhöht
				counter--;		// dito
				doInteractiveEvent();
			}
			exercise.setInteractiveMode(Exercise.SUBOPERATION);
		} else {
			String msg = feedbackGenerator.genMessage(
							"information.gif",
							"<b>Jump</b> to beginning");
			displayMessage("FEEDBACK", msg);
			setSpecialButtonText(specialGetNext);
			specialState = specialGetNext;
			exercise.setInteractiveMode(Exercise.NOPOPUP);						 
		}
		//System.out.println("todoPosition = "+todoPosition);
		updateTaskMessage(); 
	}
	
	protected void specialPressed() {
		String msg = null;
		// EXERCISE-START
		if(specialState == specialGetNext) { // || specialState == specialFinishOp) {
			if(todoPosition>=0) checkForFailure();
			//todoPosition++;	// wird bei interactiveEvent erledigt
			//counter++;		// dito
			Operation op = (Operation)todoOperationQueue.get(todoPosition+1).clone();
			op.setExecution(false);
			msg = feedbackGenerator.genMessage(
						"explanation.gif",
						"Perform the SubOperations for:");
			msg +=	"<ul><li><b>"+op.out()+"</b></li></ul>"+
					"by pressing the right mouse button in the drawing-area, and selecting the correct suboperation."+
					"<br><br>"+
					"When you have finished all suboperations, please click the <b><i>"+specialFinishOp+"</i></b> button.";
			displayMessage("FEEDBACK", msg);
			exercise.commit(op);	// <-- löst OPERATION_EXECUTED aus --> interactiveEvent
			setSpecialButtonText(specialFinishOp);
			//specialState = specialFinishOp;
			exercise.setInteractiveMode(Exercise.SUBOPERATION);
			exercise.getTreeOperationView().enableJumping();
			// -> WAIT_FOR_FIRST
			return;
		} else if(specialState == specialFinishEx) {
			finishedExercise();
			return;			
		}
		// Folgendes wenn: specialFinishOp
		finishSwitch();
	}
	protected void demandPressed() { }
	protected void forwardPressed() { exercise.forward(); }
	protected void backPressed() {
		Object actop = exercise.getOperationRecorder().getCurrentOperation(); 
		String msg;
		if(specialState == specialGetNext || specialState == specialFinishEx) {
			setSpecialButtonText(specialFinishOp);
			specialState = specialFinishOp;
			exercise.setInteractiveMode(Exercise.SUBOPERATION);
			msg = feedbackGenerator.genMessage(
					"information.gif",
					"<b>Back</b> "+specialFinishOp);
			msg = makeNextLink(msg);
			displayMessage("FEEDBACK", msg);
			updateBackForwardButtons();
			callKB();
			return; 
		}
		exercise.back();
	}
	
	// =========================================================================
	protected void forwardEvent() {
		counter++;
		super.forwardEvent();
		updateBackForwardButtons();
		FeedbackObject fo = callKB();
		Object o = exercise.getOperationRecorder().getCurrentOperation();
		String msg;
		if(o instanceof Operation) todoPosition++;
		msg = feedbackGenerator.genMessage(
				"information.gif",
				"<b>Forward</b> "+((SimpleOperation)o).out());
		msg = makeNextLink(msg);
		displayMessage("FEEDBACK", msg);
	}
	
	// =========================================================================
	protected void backEvent() {
		counter--;
		super.backEvent();
		updateBackForwardButtons();
		FeedbackObject fo = callKB();
		Object o = exercise.getOperationRecorder().getNextOperation();
		if(o instanceof Operation) todoPosition--;
		String msg = feedbackGenerator.genMessage(
				"information.gif",
				"<b>Back</b> "+((SimpleOperation)o).out());
		msg = makeNextLink(msg);
		displayMessage("FEEDBACK", msg);
	}
	
	// =========================================================================
	protected void interactiveEvent() {
		Object o = exercise.getOperationRecorder().getCurrentOperation();
		if(o instanceof Operation) {
			todoPosition++;
			updateTaskMessage();
			specialState = specialFinishOp;
			return;
		}

		// Fehler im Tree markieren		
		//exercise.getTreeOperationView().markCorrectness();
		
		// Jetzt kann aktuelle Operation nur eine SubOperation sein
		
		updateBackForwardButtons();
		FeedbackObject fo = callKB();

		String msg = feedbackGenerator.genMessage(
				"information.gif",
				"<b>Execute</b> "+((SimpleOperation)o).out());
		displayMessage("FEEDBACK", msg);

		if(differentOperation) {
			cutFirstFailureFeedbackObjects();
			checkForFailure();
		}
	}
	
	
	// =========================================================================
	
	private void finishSwitch() {
		
		OperationRecorder or = exercise.getOperationRecorder();
		
		// Alle nachfolgenden abschneiden (hatte ich früher mit TreeOperationView.cutTree() gemacht: war aber falsch!
		ExerciseUpdateEvent eue = new ExerciseUpdateEvent(exercise, ExerciseUpdateEvent.CLEAR_FOLLOWING);
		exercise.sendExerciseUpdateMessages(eue);
		
		exercise.getTreeOperationView().markCorrectness(true,true);

		exercise.setInteractiveMode(Exercise.NOPOPUP);

		String msg = "";

		// Ersten Fehler ab der aktuellen Operation holen
		int opnr = or.getCurrentOperationNr();
		Failure f = or.getLimitedFailure(or.getOffset(opnr,-1));
		//Failure f = or.getFirstFailure();
		if(f!=null && f.getDescription() == Failure.MISSING_SUBOP) {
			// Bei MISSING_SUBOP sofort Fehler anzeigen
			mauda.plugin.KBFormulaEvaluator kbfe = feedbackGenerator.getKBFormulaEvaluator();
			kbfe.setFinishOperationState(true);
			FeedbackObject fo = callKB();
			kbfe.setFinishOperationState(false);
			msg = fo.getNextMessage();
			msg += "<p>If you want you can press <i><b>Back</b></i> and perform the missing suboperations.</p>";
			evaluator.log(currentFeedbackObject);
		} else {
			if(f==null || f.getOffset()>or.getCurrentOffset()+1) {
				msg = feedbackGenerator.genMessage(
							"correct_v.gif",
							"<b>Well done.</b>",
							null,
							"You have performed all SubOperations correctly.");
			} else {
				// Feedback zu erstem Fehler anzeigen
				FeedbackObject fo = null;
				if(firstFailureFeedbackObjects.size()>todoPosition)
					fo = (FeedbackObject)firstFailureFeedbackObjects.elementAt(todoPosition);
				// fo == null dürfte eigenlicht nicht vorkommen
				//if(fo==null) fo = callKB();
				msg = fo.getNextMessage();
				currentFeedbackObject = fo;
				// ALT
				/*
				Operation op = (Operation)or.getOperation(opnr);
				msg = feedbackGenerator.genMessage(
							"incorrect_x.gif",
							"<b>There are errors</b> in "+op.out());
				*/
				// 
				msg += "<p>If you want you can press <i><b>Back</b></i> and correct the errors.</p>";
			}
		}
		if(todoPosition==todoOperationQueue.length()-1) {
			msg += "<p>Press <b><i>"+specialFinishEx+"</i></b> to complete the exercise.</p>";
			setSpecialButtonText(specialFinishEx);
			specialState = specialFinishEx;
		} else {
			msg += "<p>Press <b><i>"+specialGetNext+"</i></b> to process the next Operation.</p>";
			setSpecialButtonText(specialGetNext);
			specialState = specialGetNext;
		}
		displayMessage("FEEDBACK", msg);
		setBackEnabled(true);	// Damit Back von FinishOp möglich ist
		// Vom Anfang bis hier makeNextLink aktivieren
		setFeedbackBound();
	}

	protected void finishedLoading() {
		super.finishedLoading();
		String msg = genOpToPerformMessage();		
		msg += getFeedbackDescription();
		msg += "<br>";
		msg += "To perform the first operation, please click the <b><i>'"+specialGetNext+"'</i></b> button below.";
		displayMessage("TASK", msg);
		
		setSpecialButtonText(specialGetNext);
		setSpecialEnabled(true);
	}
	protected String getFeedbackDescription() {
		return "Errors will be reported after pressing <i>"+specialFinishOp+"</i> but not corrected.";
	}
	
	protected void linkClicked(String href) {
		super.linkClicked(href);
	}
	
	/* (non-Javadoc)
	 * @see mauda.feedback.SimpleFeedback#getFeedbackTypeID()
	 */
	public int getFeedbackTypeID() { return type; }

	/* (non-Javadoc)
	 * @see mauda.feedback.SimpleFeedback#save()
	 */
	public HashMap save() {
		HashMap hm = super.save();
		return hm;
	}
	/* (non-Javadoc)
	 * @see mauda.feedback.SimpleFeedback#load(java.util.HashMap)
	 */
	public void load(HashMap hm) {
		super.load(hm);
	}
}
