/*
 * Created on 13.01.2004 17:47:02
 *
 * Multimediale Algorithmen und Datenstrukturen Assessments
 */
package generation;

import mauda.*;
import mauda.plugin.*;
import mauda.operation.*;
import mauda.utils.FileLocation;

import java.util.*;
/**
 * Generates automatically exercises and stores them to local filesystem
 * 
 * @author Markus Krebs
 */
public class AutoGenerator {
	
	private String initFilename = "init.xml";
	private String scrambleFilename = "scramble.xml";
	private String autoGenFilename = "autogen.xml";
	private String ratingFilename = "rating.xml";
	
	private int mode;
	
	private SimpleExercise exercise;

	/**
	 * Starts the AutoGenerator
	 * 
	 * @param type The type of exercise to created. E.g.: FibHeap
	 * @param diffStr The difficulty
	 * @param modeStr The mode: NORMAL (NormalMode) or FAULT (FaultMode)
	 * @param saveGeneratedExercise TRUE when the new generated exercise has to be saved, false otherwise
	 */
	public AutoGenerator(String type, String diffStr, String modeStr, boolean saveGeneratedExercise) {
		FileLocation.config();
		
		exercise = new SimpleExercise();
		PlugInHandler plugInHandler = new PlugInHandler(exercise);
		
		// Angaben testen
		boolean plugInOk = false;
		String[] plugInNames = plugInHandler.getAvailablePlugIns();
		for(int i=0; i<plugInNames.length; i++) {
			if(type.equals(plugInNames[i])) plugInOk = true;
		}
		if(!plugInOk) {
			System.out.println("ERROR: Unknown PlugIn-Name: "+type);
			System.exit(0);
		} else if(Difficulties.getID(diffStr) == Difficulties.UNKNOWN) {
			System.out.println("ERROR: Unknown Difficulty: "+diffStr);
			System.exit(0);
		} else if(ExerciseMode.getID(modeStr) == ExerciseMode.UNKNOWN) {
			System.out.println("ERROR: Unknown Mode: "+modeStr);
			System.exit(0);
		}

		// PlugIn laden
		plugInHandler.load(type);
		exercise.setDifficulty(Difficulties.getID(diffStr));
		exercise.getMetaData().setSource("AutoGenerator");
		exercise.getMetaData().setComment("Generated by 'AutoGenerator.java'.");
		exercise.setMode(ExerciseMode.getID(modeStr));
		automatic();
		if(saveGeneratedExercise) save();
		System.out.println("Exercise Ready!");
	}
	/**
	 * Save Exercise by a calculated Filename
	 */
	private void save() {
		String filename = FileLocation.genFilename(
								FileLocation.unworkedPath,
								FileLocation.unworkedPrefix);
		exercise.save(filename);
	}
	
	/**
	 * Get the Exercise as HashMap for loading in WorkEditor
	 * 
	 * @return The Hashmap that contains the exercise
	 */
	public HashMap getExercise() {
		HashMap hm = exercise.save(null);
		//exercise.getMetaData().inputDialog();
		return hm;
	}
	
	/**
	 * Method to load, a queue of operations from the given
	 * filename. This method is used to load the config-files for
	 * Init, Scramble and Autogen.
	 * 
	 * @param filename
	 * @return The OperationQueue of the file
	 */
	private OperationQueue loadConfig(String filename) {
		Vector v = XMLFileAccess.load(filename);
		if(v==null) {
			System.err.println("Cant load '"+filename+"'!");
			System.err.println("No automatic generation of exercises possible without this file!");
			return null;
		} 
		OperationQueue oq = new OperationQueue();
		oq.load((Vector)v.firstElement());
		return oq;		
	}
	/**
	 * A call to this method starts generating a new exercise from
	 * the parameters that were transmitted to the AutoGenerator-
	 * Konstruktor.
	 */
	private void automatic() {
		System.out.println("Loading files...");
		String d = exercise.getDataDirectory();
		OperationQueue initOQ = loadConfig(d + initFilename);
		OperationQueue scrambleOQ = loadConfig(d + scrambleFilename);
		OperationQueue autoGenOQ = loadConfig(d + autoGenFilename);

		System.out.println("Call to GeneralAnalyst.fullAutomatic(...)");
		OperationQueue[] oq =
			GeneralAnalyst.fullAutomatic(exercise.getDSObject(),
				initOQ,
				scrambleOQ,
				autoGenOQ,
				exercise.getDifficulty(),
				exercise.getMode());
		exercise.getOperationRecorder().setTodoPosition(oq[0].length());
		OperationQueue exeOQ = new OperationQueue();
		exeOQ.addAll(oq[0]);
		exeOQ.addAll(oq[1]);
		// Alle Operationen durch Exercise laufen lassen,
		// so dass OperationRecorder gefüllt wird.
		// --> wird für die spätere Speicherung benötigt
		System.out.println("Execute Operations on Exercise");
		Enumeration en = exeOQ.toVector().elements();
		while(en.hasMoreElements()) {
			Object o = en.nextElement();
			//System.out.println("  - "+o);
			exercise.operationExecuted(o);
		}
		
		//System.out.println("Saving Exercise...");
		/* 
		exercise.commit(exeOQ);
		*/
	}

	/**
	 * Starts the AutoGenerator
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		if(args.length!=3) {
			System.out.println("Usage: AutoGenerator Type Difficulty Mode");
			System.out.println("    Type = e.g. FibHeap");
			System.out.println("    Difficulty = EASY | MEDIUM | HARD");
			System.out.println("    Mode = NORMAL | FAULT");
			System.exit(0);
		}
		String type = args[0];
		String diff = args[1];
		String mode = args[2];
		new AutoGenerator(type, diff, mode, true);
	}
}
