/*
 * Created on 10.01.2004 17:58:02
 *
 * Multimediale Algorithmen und Datenstrukturen Assessments
 */
package mauda;

import mauda.utils.Prop;

import java.util.*;
import javax.swing.*;
import java.awt.*;

/**
 * Stores meta-data of exercises.
 * 
 * @author Markus Krebs
 */
public class MetaData {
	
	// Welche Eingaben sollen erlaubt sein
	/**
	 * Allow inputs on all fields in the meta-data
	 */
	public static final int ALL = 0;
	/**
	 * Allow inputs only to the Creator-Field (Creator of the exercise)
	 */
	public static final int CREATOR = 1;
	/**
	 * Allow inputs only to the Editor-Field (Student who work on the exercise)
	 */
	public static final int EDITOR = 2;
	/**
	 * Allow inputs only to the Evaluator-Field (Tutor who evaluated the exercise)
	 */
	public static final int EVALUATOR = 3;
	
	private static int displayMode = ALL;

	// Allgemein
	private String type;
	private int difficulty;
	private int mode;

	// Creator
	private String source;
	private String date;
	private int initRating;
	private int todoRating;
	private String comment;
	
	// Editor
	private String editorName;
	private String editorDate;
	private String editorState;
	private String editorFeedback;
	private String editorComment;
	
	// Evaluator
	private String evaluatorName;
	private String evaluatorDate;
	private String evaluatorState;
	private String evaluatorScore;
	private String evaluatorJEAFilename;
	private String evaluatorComment;
		
	/**
	 * Creates a MetaData-Object
	 */
	public MetaData() {
		
		date = getActualDateTime();
				
		source = "Generator";
		type = "unknown";
		difficulty = -1;
		comment = "";
		initRating = -1;
		todoRating = -1;
		mode = ExerciseMode.NORMAL;
		
		editorName = "";
		editorDate = "";
		editorState ="unworked";
		editorFeedback = "";
		editorComment = "";
		
		evaluatorName = "";
		evaluatorDate = "";
		evaluatorState = "not evaluated";
		evaluatorScore = "";
		evaluatorJEAFilename = "";
		evaluatorComment = "";
	}
	
	/**
	 * Sets the display-mode.
	 * @param m
	 * @see mauda.MetaData#ALL
	 * @see mauda.MetaData#CREATOR
	 * @see mauda.MetaData#EDITOR
	 * @see mauda.MetaData#EVALUATOR
	 */
	public static void setDisplayMode(int m) { displayMode = m; }
	/**
	 * Gets the display-mode
	 * @return display-mode-ID
	 * @see mauda.MetaData#setDisplayMode(int)
	 */
	public static int getDisplayMode() { return displayMode; }
	
	/**
	 * Returns a string-representation of this meta-data, which
	 * can be used e.g. in the filechooses's preview-panel.
	 * @return string-representation of this meta-data
	 */
	public String getPreviewString() {
		String msg = type+"\n";
		msg += Difficulties.getString(difficulty)+"\n";
		msg += ExerciseMode.getString(mode)+"\n";
		switch(displayMode) {
			case CREATOR :
				msg += source+"\n"+date+"\n"+comment;
				break;
			case EDITOR :
				msg += editorName+"\n"+editorDate+"\n"+editorState+"\n"+editorFeedback+"\n"+editorComment;
				break;
			case EVALUATOR :
				msg += evaluatorName+"\n"+evaluatorDate+"\n"+evaluatorState+"\n"+evaluatorScore+"\n"+evaluatorComment;
				break;
			default :
				msg += "ERROR";
				break;
		}
		return msg;		
	}

	private String getActualDateTime() {
		// Datum
		Calendar c = Calendar.getInstance();
		int day = c.get(Calendar.DAY_OF_MONTH);
		int month = c.get(Calendar.MONTH)+1;
		int year = c.get(Calendar.YEAR);
		String s = (day<10?"0":"")+day+"."+(month<10?"0":"")+month+"."+year;
		// Zeit
		int hour = c.get(Calendar.HOUR_OF_DAY);
		int min = c.get(Calendar.MINUTE);
		int sec = c.get(Calendar.SECOND);
		String time = (hour<10?"0":"")+hour+":"+(min<10?"0":"")+min+":"+(sec<10?"0":"")+sec;
		s += " "+time;
		return s;		
	}
	
	// Allgemein =============================================
	/**
	 * Sets the type of the exercise, e.g. Fibonacci-Heap
	 * @param t plugin-type-name
	 */
	public void setType(String t) { type = t; }
	/**
	 * Gets the type of the exercise
	 * @return type of exercise
	 */
	public String getType() { return type; }
	/**
	 * Sets the diffculty of the exercise
	 * @param d difficulty-ID
	 * @see mauda.Difficulties
	 */
	public void setDifficulty(int d) { difficulty = d; }
	/**
	 * Gets the difficulty of the exercise
	 * @return difficulty-id
	 */
	public int getDifficulty() { return difficulty; }
	/**
	 * Sets the mode of the exercise, e.g. NORMAL or FAULT 
	 * @param m mode-ID
	 * @see mauda.ExerciseMode
	 */
	public void setMode(int m) { mode = m; }
	/**
	 * Gets the mode of the exercise
	 * @return mode-ID
	 */
	public int getMode() { return mode; }	
	
	// Creator ===============================================
	/**
	 * Sets the Creator-Name of the exercise, e.g. AutoGenerator, Tutorname, etc.
	 * @param s Creator-Name
	 */
	public void setSource(String s) { source = s; }
	/**
	 * Sets the rating of the init-operations
	 * @param r Overall-rating of the init-operations
	 */
	public void setInitRating(int r) { initRating = r; }
	/**
	 * Gets the init-rating
	 * @return init-rating
	 * @see mauda.MetaData#setInitRating(int)
	 */
	private int getInitRating() { return initRating; }
	/**
	 * Sets the rating of the todo-operations
	 * @param r Overall-rating of the todo-operations
	 */
	public void setTodoRating(int r) { todoRating = r; }
	/**
	 * Gets the todo-rating
	 * @return todo-rating
	 * @see mauda.MetaData#setTodoRating(int)
	 */
	private int getTodoRating() { return todoRating; }
	/**
	 * Sets a comment the creator has for this exercise
	 * @param c comment
	 */
	public void setComment(String c) { comment = c; }
	
	// Editor ================================================
	/**
	 * Sets the name of the student who works on the exercise
	 * @param n student-name
	 */
	public void setEditorName(String n) { editorName = n; }
	/**
	 * Actualizes the date/time of processing the exercise
	 */
	public void actualizeEditorDate() { editorDate = getActualDateTime(); }
	/**
	 * Sets the current working-state of the editor
	 * @param s working-state: "unworked", "in process" or "completed" 
	 */
	public void setEditorState(String s) { editorState = s; }
	/**
	 * Gets the current working-state of the editor
	 * @return working-state
	 * @see mauda.MetaData#setEditorState(String)
	 */
	public String getEditorState() { return editorState; }
	/**
	 * Sets the type of feedback the student chosen
	 * @param s Feedback-Type-String
	 */
	public void setEditorFeedback(String s) { editorFeedback = s; }
	/**
	 * Gets the type of feedback the student chosen
	 * @return Feedback-Type-String
	 */
	public String getEditorFeedback() { return editorFeedback; }
	
	// Evaluator =============================================
	/**
	 * Sets the name of the person who evaluated the exercise.
	 * Setting to "AutoEvaluator" means that the exercise was
	 * automatically evaluated by the programm.
	 * @param s Evaluator-Name
	 */
	public void setEvaluatorName(String s) { evaluatorName = s; }
	/**
	 * Gets the name of the evaluator
	 * @return Evaluator-name
	 */
	public String getEvaluatorName() { return evaluatorName; }
	/**
	 * Actualizes the date/time of processing the exercise
	 */
	public void actualizeEvaluatorDate() { evaluatorDate = getActualDateTime(); }
	/**
	 * Sets the current evaluation-state of the exercise
	 * @param s evaluation-state: "not evaluated" or "evaluated"
	 */
	public void setEvaluatorState(String s) { evaluatorState = s; }
	/**
	 * Gets the current evaluation-state
	 * @return evaluation-state
	 * @see mauda.MetaData#setEvaluatorState(String)
	 */
	public String getEvaluatorState() { return evaluatorState; }
	/**
	 * Sets the reached score of an evaluated exercise. Normally
	 * this field have to filled with x of 100, e.g. 89.0 of 100
	 * @param s reached score
	 */
	public void setEvaluatorScore(String s) { evaluatorScore = s; }
	/**
	 * Sets the filename of the jedas-recording-animation-file,
	 * that the current exercise is associated to.
	 * @param s jedas-recorder-animation-filename
	 */
	public void setEvaluatorJEAFilename(String s) { evaluatorJEAFilename = s; }
	/**
	 * Gets the filename of the jedas-recording-animation-file 
	 * @return filename of the jedas-recording-animation-file
	 */
	public String getEvaluatorJEAFilename() { return evaluatorJEAFilename; }
	
	
	/**
	 * Converts the meta-data in a format for saving-purposes
	 * @return HashMap-representation of the meta-data
	 */
	public HashMap save() {
		HashMap meta = new HashMap();
		// Allgemein
		meta.put("Type", type);
		meta.put("Difficulty", Difficulties.getString(difficulty));
		meta.put("Mode", ExerciseMode.getString(mode));
		// Creator
		meta.put("Source", source);
		meta.put("Date", date);
		meta.put("Rating", initRating+" / "+todoRating);
		meta.put("Comment", comment);
		// Editor
		meta.put("EditorName", editorName);
		meta.put("EditorDate", editorDate);
		meta.put("EditorState", editorState);
		meta.put("EditorFeedback", editorFeedback);
		meta.put("EditorComment", editorComment);
		// Evaluator
		meta.put("EvaluatorName", evaluatorName);
		meta.put("EvaluatorDate", evaluatorDate);
		meta.put("EvaluatorState", evaluatorState);
		meta.put("EvaluatorScore", evaluatorScore);
		meta.put("EvaluatorJEAFilename", evaluatorJEAFilename);
		meta.put("EvaluatorComment", evaluatorComment);
		return meta;		
	}
	/**
	 * Fills this meta-data-object with values from HashMap-
	 * representation of the meta-data. This is used for loading
	 * meta-data from a xml-file.
	 * @param o HashMap-representation of meta-data
	 */
	public void load(Object o) {
		HashMap meta = (HashMap)o;
		// Allgemein		
		type = (String)meta.get("Type");
		difficulty = Difficulties.getID((String)meta.get("Difficulty"));
		mode = ExerciseMode.getID((String)meta.get("Mode"));
		// Creator
		source = (String)meta.get("Source");
		date = (String)meta.get("Date");
		String ratings = (String)meta.get("Rating");
		StringTokenizer st = new StringTokenizer(ratings);
		initRating = Integer.parseInt(st.nextToken());
		String dummy = st.nextToken();
		todoRating = Integer.parseInt(st.nextToken());
		comment = (String)meta.get("Comment");
		// Editor
		editorName = (String)meta.get("EditorName");
		editorDate = (String)meta.get("EditorDate");
		editorState = (String)meta.get("EditorState");
		if(editorState == null) editorState = "unworked";	// Abwärstkompatibilität
		editorFeedback = (String)meta.get("EditorFeedback");
		editorComment = (String)meta.get("EditorComment");
		// Evaluator
		evaluatorName = (String)meta.get("EvaluatorName");
		evaluatorDate = (String)meta.get("EvaluatorDate");
		evaluatorState = (String)meta.get("EvaluatorState");
		if(evaluatorState == null) evaluatorState = "not evaluated";	// Abwärstkompatibilität
		evaluatorScore = (String)meta.get("EvaluatorScore");
		evaluatorJEAFilename = (String)meta.get("EvaluatorJEAFilename");
		evaluatorComment = (String)meta.get("EvaluatorComment");
	}
	
	/**
	 * Displays an input-dialog-window, where the user can input
	 * several values. The write access to different fields might
	 * be denied which depends on the display-mode of the meta-data.
	 * @return true if Meta-Data have been changed, false otherwise
	 * @see mauda.MetaData#setDisplayMode(int)
	 */
	public boolean inputDialog() {
		// Angaben vor Editierung
		HashMap restoreMetaData = save();		

		// Allgemein
		JTextField typeIn = new JTextField(type, 24);
		typeIn.setEditable(false);
		JTextField difficultyIn = new JTextField(Difficulties.getString(difficulty), 24);
		difficultyIn.setEditable(false);
		JTextField modeIn = new JTextField(ExerciseMode.getString(mode), 24);
		modeIn.setEditable(false);
		// Creator
		JTextField sourceIn = new JTextField(source);
		JTextField dateIn = new JTextField(date);
		JTextField ratingIn = new JTextField(initRating+" / "+todoRating);
		ratingIn.setEditable(false);
		JTextArea commentIn = new JTextArea(comment, 5, 24);
		commentIn.setLineWrap(true);
		// Editor
		JTextField editorNameIn = new JTextField(editorName);
		JTextField editorDateIn = new JTextField(editorDate);
		JTextField editorStateIn = new JTextField(editorState);
		editorStateIn.setEditable(false);
		JTextField editorFeedbackIn = new JTextField(editorFeedback);
		editorFeedbackIn.setEditable(false);
		JTextArea editorCommentIn = new JTextArea(editorComment, 5, 24);
		editorCommentIn.setLineWrap(true);
		// Evaluator
		JTextField evaluatorNameIn = new JTextField(evaluatorName);
		JTextField evaluatorDateIn = new JTextField(evaluatorDate);
		JTextField evaluatorStateIn = new JTextField(evaluatorState);
		evaluatorStateIn.setEditable(false);
		JTextField evaluatorScoreIn = new JTextField(evaluatorScore);
		JTextField evaluatorJEAFilenameIn = new JTextField(evaluatorJEAFilename);
		JTextArea evaluatorCommentIn = new JTextArea(evaluatorComment, 5, 24);
		evaluatorCommentIn.setLineWrap(true);
				
		JPanel mainPanel = new JPanel();
		mainPanel.setLayout(new BorderLayout());
		
		
		// Allgemein
		JPanel p = new JPanel();

		GridBagLayout gbl = new GridBagLayout();
		GridBagConstraints c = new GridBagConstraints();
		p.setLayout(gbl);
		c.fill = GridBagConstraints.BOTH;
		c.insets = new Insets(2,2,2,2);
		
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataType")),gbl, c, 0,0,1,1));
		p.add(newGridElement(typeIn,gbl, c, 1,0,1,1));
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataDifficulty")),gbl, c, 0,1,1,1));
		p.add(newGridElement(difficultyIn,gbl, c, 1,1,1,1));
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataMode")),gbl, c, 0,2,1,1));
		p.add(newGridElement(modeIn,gbl, c, 1,2,1,1));
		
		mainPanel.add(p, BorderLayout.NORTH);
		
		// TabbedPane
		JTabbedPane tabbedPane = new JTabbedPane();
		mainPanel.add(tabbedPane, BorderLayout.CENTER);
		
		// Creator
		p = new JPanel();		
		gbl = new GridBagLayout();
		c = new GridBagConstraints();
		p.setLayout(gbl);
		c.fill = GridBagConstraints.BOTH;
		c.insets = new Insets(2,2,2,2);
		// Bemerkung: Breite der 2. Spalte wird durch Breite
		// des JTextAreas bestimmt (siehe oben: Textbreite)
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataSource")),gbl, c, 0,0,1,1));
		p.add(newGridElement(sourceIn,gbl, c, 1,0,1,1));
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataDate")),gbl, c, 0,1,1,1));
		p.add(newGridElement(dateIn,gbl, c, 1,1,1,1));
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataRating")),gbl, c, 0,2,1,1));
		p.add(newGridElement(ratingIn,gbl, c, 1,2,1,1));
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataComment")),gbl, c, 0,3,1,1));
		p.add(newGridElement(new JScrollPane(commentIn),gbl, c, 1,3,1,1));
		
		tabbedPane.add(Prop.get(this, "MetaDataCreatorTab"), p);
		
		// Editor
		p = new JPanel();		
		gbl = new GridBagLayout();
		c = new GridBagConstraints();
		p.setLayout(gbl);
		c.fill = GridBagConstraints.BOTH;
		c.insets = new Insets(2,2,2,2);
		// Bemerkung: Breite der 2. Spalte wird durch Breite
		// des JTextAreas bestimmt (siehe oben: Textbreite)
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataEditorName")),gbl, c, 0,0,1,1));
		p.add(newGridElement(editorNameIn,gbl, c, 1,0,1,1));
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataEditorDate")),gbl, c, 0,1,1,1));
		p.add(newGridElement(editorDateIn,gbl, c, 1,1,1,1));
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataEditorState")),gbl, c, 0,2,1,1));
		p.add(newGridElement(editorStateIn,gbl, c, 1,2,1,1));
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataEditorFeedback")),gbl, c, 0,3,1,1));
		p.add(newGridElement(editorFeedbackIn,gbl, c, 1,3,1,1));
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataEditorComment")),gbl, c, 0,4,1,1));
		p.add(newGridElement(new JScrollPane(editorCommentIn),gbl, c, 1,4,1,1));
		
		tabbedPane.add(Prop.get(this, "MetaDataEditorTab"), p);
		
		// Evaluator
		p = new JPanel();		
		gbl = new GridBagLayout();
		c = new GridBagConstraints();
		p.setLayout(gbl);
		c.fill = GridBagConstraints.BOTH;
		c.insets = new Insets(2,2,2,2);
		// Bemerkung: Breite der 2. Spalte wird durch Breite
		// des JTextAreas bestimmt (siehe oben: Textbreite)
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataEvaluatorName")),gbl, c, 0,0,1,1));
		p.add(newGridElement(evaluatorNameIn,gbl, c, 1,0,1,1));
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataEvaluatorDate")),gbl, c, 0,1,1,1));
		p.add(newGridElement(evaluatorDateIn,gbl, c, 1,1,1,1));
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataEvaluatorState")),gbl, c, 0,2,1,1));
		p.add(newGridElement(evaluatorStateIn,gbl, c, 1,2,1,1));
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataEvaluatorJEAFilename")),gbl, c, 0,3,1,1));
		p.add(newGridElement(evaluatorJEAFilenameIn,gbl, c, 1,3,1,1));
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataEvaluatorScore")),gbl, c, 0,4,1,1));
		p.add(newGridElement(evaluatorScoreIn,gbl, c, 1,4,1,1));
		p.add(newGridElement(new JLabel(Prop.get(this, "MetaDataEvaluatorComment")),gbl, c, 0,5,1,1));
		p.add(newGridElement(new JScrollPane(evaluatorCommentIn),gbl, c, 1,5,1,1));
		
		tabbedPane.add(Prop.get(this, "MetaDataEvaluatorTab"), p);
		
		// Je nach Benutzer: Eingaben sperren
		if(displayMode != ALL) {
			if(displayMode != CREATOR) {
				sourceIn.setEditable(false);
				dateIn.setEditable(false);
				ratingIn.setEditable(false);
				commentIn.setEditable(false);
			}
			if(displayMode != EDITOR) {
				editorNameIn.setEditable(false);
				editorDateIn.setEditable(false);
				editorStateIn.setEditable(false);
				editorFeedbackIn.setEditable(false);
				editorCommentIn.setEditable(false);
			}
			if(displayMode != EVALUATOR) {
				evaluatorNameIn.setEditable(false);
				evaluatorDateIn.setEditable(false);
				evaluatorStateIn.setEditable(false);
				evaluatorScoreIn.setEditable(false);
				evaluatorJEAFilenameIn.setEditable(false);
				evaluatorCommentIn.setEditable(false);
			}
		}
		int index = 0;
		switch(displayMode) {
			case CREATOR : index = 0; break;
			case EDITOR : index = 1; break;
			case EVALUATOR : index = 2; break;
		}
		tabbedPane.setSelectedIndex(index);

		// Jetzt anzeigen
		
		//JOptionPane.showMessageDialog(MAUDA.getApplicationMainFrame(), p);
		//String title = Prop.get("DialogDiscardActiveExerciseTitle");
		String title = Prop.get(this, "MetaDataTitle");
		int result = JOptionPane.showConfirmDialog(MAUDA.getApplicationMainFrame(), mainPanel, title, JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE);
		if(result == JOptionPane.OK_OPTION) {
			// Allgemein --------
			//type = typeIn.getText();
			//difficulty = Difficulties.getDifficultyInt(difficultyIn.getText());
			//String mode = modeIn.getText();
			// Creator ----------
			source = sourceIn.getText();
			date = dateIn.getText();
			//String ratings = ratingIn.getText(); initRating = ... / todoRating = ...
			comment = commentIn.getText();
			// Editor -----------
			editorName = editorNameIn.getText();
			editorDate = editorDateIn.getText();
			editorState = editorStateIn.getText();
			editorFeedback = editorFeedbackIn.getText();
			editorComment = editorCommentIn.getText();
			// Evaluator
			evaluatorName = evaluatorNameIn.getText();
			evaluatorDate = evaluatorDateIn.getText();
			evaluatorState = evaluatorStateIn.getText();
			evaluatorScore = evaluatorScoreIn.getText();
			evaluatorJEAFilename = evaluatorJEAFilenameIn.getText();
			evaluatorComment = evaluatorCommentIn.getText();
			
			HashMap nowMetaData = save();
			if(!restoreMetaData.equals(nowMetaData)) {
				// Es wurde in den Meta-Daten etwas verändert!
				//JOptionPane.showMessageDialog(MAUDA.getApplicationMainFrame(), "CHANGED");
				return true;
			}
		}
		return false;
	}
	private JComponent newGridElement(JComponent comp, GridBagLayout gbl, GridBagConstraints c, int gx, int gy, int gw, int gh) {
		c.gridx = gx;
		c.gridy = gy;
		c.gridwidth = gw;
		c.gridheight = gh;
		gbl.setConstraints(comp, c);
		return comp;
	}
}
