/*
 * Created on 09.02.2004 22:08:19
 *
 * Multimediale Algorithmen und Datenstrukturen Assessments
 */
package mauda.feedback;

import mauda.*;
import mauda.operation.*;
import mauda.treeoperationview.*;
import mauda.feedback.select.*;
import mauda.feedback.types.*;

import java.util.*;
/**
 * Extends Exercise-class to hold Feedback-specific information.
 * 
 * @author Markus Krebs
 */
public class FeedbackExercise extends Exercise implements ExerciseUpdateListener {

	private SimpleFeedback feedback;
	private FeedbackPanel feedbackPanel;
	private TreeOperationView treeOperationView;
	
	// Fürs Laden von Aufgaben
	private HashMap feedbackConfig;
	private Vector treeOperationViewConfig;
	
	/**
	 * Creates a FeedbackExercise
	 * @param type plugin-name-id
	 */
	public FeedbackExercise(String type) {
		super(type);		//feedbackPanel = new JPanel();

		treeOperationView = new TreeOperationView(this);
		addExerciseUpdateListener(treeOperationView);
		
		addExerciseUpdateListener(this);

		feedbackPanel = new FeedbackPanel(this);
	}
	/**
	 * Sets the feedback-type of the exercise
	 * @param feedback SimpleFeedback
	 * @see mauda.feedback.types.ImmediateFeedbackAndErrorCorrection
	 * @see mauda.feedback.types.ErrorFlagging
	 * @see mauda.feedback.types.DemandFeedback
	 * @see mauda.feedback.types.NoTutor
	 * @see mauda.feedback.types.FaultFeedback
	 */
	public void setFeedback(SimpleFeedback feedback) {
		this.feedback = feedback;
		if(feedback instanceof DemandFeedback) {
			DemandFeedback df = (DemandFeedback)feedback;
			treeOperationView.getNodePopup().removeItem(DemandFeedback.requestMenuItem);
			treeOperationView.getNodePopup().addItem(DemandFeedback.requestMenuItem, df);
		} else {
			treeOperationView.getNodePopup().removeItem(DemandFeedback.requestMenuItem);
		}
		// Bei Feedback-Wechsel Meta-Daten richtig setzen
		int fbid = feedback.getFeedbackTypeID();
		String n = FeedbackSelector.getFeedbackTypeNameFromID(fbid);
		metaData.setEditorFeedback(n);		
	}
	/**
	 * Feedback-Typ zurückgeben
	 * @return Current feedback-type
	 * @see mauda.feedback.FeedbackExercise#setFeedback(SimpleFeedback)
	 */
	public SimpleFeedback getFeedback() {
		return feedback;
	}
	/**
	 * Gets the panel the feedback uses to display its messages.
	 * This is the complete right-panel of Work-Editor.
	 * @return FeedackPanel
	 */
	public FeedbackPanel getFeedbackPanel() {
		return feedbackPanel;
	}
	/**
	 * Gets the <code>TreeOperationView</code>
	 * @return TreeOperationView
	 */
	public TreeOperationView getTreeOperationView() {
		return treeOperationView;
	}
	
	/**
	 * Saves the a exercise that is <i>in process</i> to a
	 * xml-file
	 * @param filename Filename
	 */
	public void saveWork(String filename) {
		//System.out.println("SAVE-WORK:");
		
		// Dinge ermitteln die gespeichert werden sollen
		
		int fbid = feedback.getFeedbackTypeID();
		//System.out.println("  FEEDBACK: "+FeedbackSelector.getFeedbackTypeNameFromID(fbid));
		
		OperationQueue init = feedback.getInitOperationQueue();
		OperationQueue todo = feedback.getTodoOperationQueue();
		OperationRecorder or = getOperationRecorder();
		OperationQueue acco = or.getAllTodoOperationQueue();
		//System.out.println("  INIT:         "+init);
		//System.out.println("  TO-DO:         "+todo);
		//System.out.println("  ACCOMPLISHED: "+acco);
		//System.out.println("  FEEDBACK-SPECIFIC: "+feedback.save());
		//System.out.println("  TOVIEW: "+getTreeOperationView().save());

		// Jetzt alles speichern

		HashMap ht = new HashMap();
		
		// Folgendes einstellen wird bereits beim Laden erledigt,
		// aber es kann ja gewechselt werden!
		metaData.setEditorFeedback(FeedbackSelector.getFeedbackTypeNameFromID(fbid));
		
		// Herausgenommen, damit die Ratings beim Speichern nicht verändert werden!
		//metaData.setInitRating(init.getRating());
		//metaData.setTodoRating(todo.getRating());
		
		//metaData.inputDialog();

		// Meta-Daten
		ht.put("Meta-Data", metaData.save());
		// Rest	
		ht.put("InitOperations", init.save());
		ht.put("TodoOperations", todo.save());
		ht.put("AccomplishedOperations", acco.save());
		ht.put("FeedbackSpecific", feedback.save());
		ht.put("TreeOperationView", getTreeOperationView().save());
		ht.put("Ratings", getOperationExecuter().getRatings().save());	
		
		Vector v = new Vector();
		v.add(ht);
		boolean result = XMLFileAccess.save(filename, v);
		if(!result) javax.swing.JOptionPane.showMessageDialog(MAUDA.getApplicationMainFrame(), "Cant save file: '"+filename+"' !\n\n"+"--> File not saved!");
		else setModified(false);
	}
	/**
	 * Loads an exercise that is <i>in process</i> from a
	 * HashMap-representation
	 * @param ht HashMap-representation
	 * @return true if save was successful, false otherwise
	 */
	public boolean loadWork(HashMap ht) {
		reset();
		removeExerciseUpdateListener(feedback);

		// Meta-Daten
		metaData.load(ht.get("Meta-Data"));
		difficulty = metaData.getDifficulty();
		setDifficulty(difficulty);

		setMode(metaData.getMode());
		//javax.swing.JOptionPane.showMessageDialog(MAUDA.getApplicationMainFrame(), "Mode: "+m);
		
		// if-Zeile für Abwärtskompatibilität
		if(ht.containsKey("Ratings"))
			getOperationExecuter().getRatings().load((Vector)ht.get("Ratings"));
	
		OperationQueue init = new OperationQueue();
		OperationQueue todo = new OperationQueue();
		OperationQueue acco = new OperationQueue();
		init.load((Vector)ht.get("InitOperations"));
		todo.load((Vector)ht.get("TodoOperations"));
		acco.load((Vector)ht.get("AccomplishedOperations"));
		
		// Folgendes erst nach dem Abspielen aller Operationen
		// durchführen
		feedbackConfig = (HashMap)ht.get("FeedbackSpecific");
		treeOperationViewConfig = (Vector)ht.get("TreeOperationView");
		
		// ================================================
		// Ab hier aus MenuToolBarListener.openFile(filename)
		
		// Einstellen des Feedbacks aus Meta-Daten
		int type = FeedbackSelector.getIDFromFeedbackTypeName(metaData.getEditorFeedback());
		switch(type) {
			case FeedbackSelector.IFAEC :
				feedback = new ImmediateFeedbackAndErrorCorrection(this);
				break;
			case FeedbackSelector.ERROR_FLAGGING :
				feedback = new ErrorFlagging(this);
				break;
			case FeedbackSelector.DEMAND_FEEDBACK :
				feedback = new DemandFeedback(this);
				break;
			case FeedbackSelector.NO_TUTOR :
				feedback = new NoTutor(this);
				break;
			case FeedbackSelector.FAULT_FEEDBACK :
				feedback = new FaultFeedback(this);
				break;
			default :
				System.out.println("Unrecognized feedback!!! BREAK!!!");
				return false;
				//break;				
		}			
		feedback.setInitOperationQueue(init);
		feedback.setTodoOperationQueue(todo);
		feedback.configurated = false;

		addExerciseUpdateListener(feedback);
		feedback.displayMessage("FEEDBACK", "");	// Muss vor TASK stehen! (wegen automatischem Switchen im JTabbedPane)
		feedback.displayMessage("TASK", 
			"<b>Loading Exercise.</b><br><br>"+
			"Please wait ..."
		);
		setFeedback(feedback);

		// Jetzt InitOps ausführen
		Vector exOps = new Vector();

		exOps.add(new ExerciseUpdateEvent(this, ExerciseUpdateEvent.DSOBJECT_HIDE));
		exOps.addAll((Vector)init.toVector().clone());
		
		ExerciseUpdateEvent eue = new ExerciseUpdateEvent(this, ExerciseUpdateEvent.SPECIAL);
		eue.setMessage("GO_IN_TODO-MODE");
		exOps.add(eue);

		// Event für das Löschen der Init-Operationen
		exOps.add(new ExerciseUpdateEvent(this,ExerciseUpdateEvent.CLEAR_PRECEDING));
		exOps.add(new ExerciseUpdateEvent(this,ExerciseUpdateEvent.DSOBJECT_SHOW));
		exOps.add(new ExerciseUpdateEvent(this,ExerciseUpdateEvent.FINISHED_LOADING));
		
		// Jetzt die von-Hand-ausgeführten Operationen aus-
		// führen
		for(int i=0; i<acco.length(); i++) {
			Operation op = acco.get(i);
			exOps.add(op);
			SubOperationQueue soq = op.getSubOperationQueue();
			for(int j=0; j<soq.length(); j++)
				exOps.add(soq.get(j));
		}
		
		// Irgendein Event erzeugen, ab dem feedback.load
		// durchgeführt wird
		eue = new ExerciseUpdateEvent(this, ExerciseUpdateEvent.SPECIAL);
		eue.setMessage("FEEDBACK_CONFIG");
		exOps.add(eue);

		//System.out.println("EXOPS: "+exOps);

		getUndoRedo().clear();
		setDSObject(getUndoRedo().getDSObject());
		getOperationRecorder().clear();

		// Jetzt Init-Operations ausführen
		commit(exOps);
		setModified(false);
		
		return true;
	}
	/* (non-Javadoc)
	 * @see mauda.ExerciseUpdateListener#exerciseUpdate(mauda.ExerciseUpdateEvent)
	 */
	public void exerciseUpdate(ExerciseUpdateEvent e) {
		// Abfragen ab wann die Aufgabe fertig geladen ist
		// (nach selbst-ausgeführten Operationen)
		if(e.getID() == ExerciseUpdateEvent.SPECIAL) {
			if(e.getMessage().equals("FEEDBACK_CONFIG")) {
				feedback.load(feedbackConfig);
				getTreeOperationView().load(treeOperationViewConfig);
				if(!(feedback instanceof FaultFeedback))
					getTreeOperationView().enableStop();
			} else if(e.getMessage().equals("FAULT_STATE-CONFIG")) {
				((FaultFeedback)feedback).stateConfig();
			}
		}
	}
}
