/*
 * MiningMart Version 1.0
 * 
 * Copyright (C) 2006 Martin Scholz, Timm Euler, 
 *                    Daniel Hakenjos, Katharina Morik
 *
 * Contact: miningmart@ls8.cs.uni-dortmund.de
 *
 * A list of contributing developers (other than the copyright 
 * holders) can be found at
 * http://mmart.cs.uni-dortmund.de/downloads/download.html
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program, see the file MM_HOME/LICENSE; if not, write
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA 02110-1301, USA.
 */
package edu.udo.cs.miningmart.gui.stepsettings;

import java.util.Collection;
import java.util.LinkedList;
import java.util.Vector;

import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.event.ChangeListener;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

import org.musoft.limo.application.Resource;

import edu.udo.cs.miningmart.exception.M4Exception;
import edu.udo.cs.miningmart.gui.application.MiningMartApplication;
import edu.udo.cs.miningmart.m4.M4Interface;
import edu.udo.cs.miningmart.m4.Step;
import edu.udo.cs.miningmart.m4.utils.Print;

/**
 *A <code>JTable</code> for the parameters of a <code>Step</code>.
 * @author Daniel Hakenjos
 * @version $Id: StepParameterTable.java,v 1.4 2006/04/11 14:10:13 euler Exp $
 */
public class StepParameterTable extends JTable{
	
	private MiningMartApplication app;
	
	private Step step;
	
	private StepParameterModel tablemodel;
	
	private StepParameterRenderer tablerenderer;
	
	private boolean listeningToChanges=false;
	
	private boolean editable;
	
	private Vector editors;
	
	private ChangeListener changelistener;
	
	/**
     * Constructs a new <code>StepParameterTable</code>.
	 * Call createEditorAndRenderer() after initializing.
	 */
	public StepParameterTable(MiningMartApplication app,Step step, boolean editable,ChangeListener listener){
		this.app=app;
		this.step=step;
		this.editable=editable;
		this.changelistener=listener;

		setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        setRowHeight(getRowHeight() + Resource.getInt("STEPSETTINGS_TABLE_ROW_EXTRA_HEIGHT"));
        getTableHeader().setReorderingAllowed(false);

        this.tablemodel = new StepParameterModel(step, editable);
        this.setModel(tablemodel);

        this.tablerenderer = new StepParameterRenderer(step);

        listeningToChanges=true;
	}
	
    /**
     *Creates editors and renderers for the parameters.
     */
	public void createEditorAndRenderer(){
		editors=new Vector();
		
		ParameterEditor parameditor;

		for(int row=0;row<tablemodel.getRowCount();row++){
			try{
				if (tablemodel.isInput(row)){
					if (tablemodel.getOpParam(row).isValueParameter()){
	
						if (tablemodel.getOpParam(row).isArray()){

							//Ein einzelner Wert oder One OfList
							if (tablemodel.getOpParam(row).isOneOf()){
								parameditor=new ListOneOfValueEditor(app,step,tablemodel.getOpParam(row));
							}else{
								parameditor=new ListValueEditor(app,step,tablemodel.getOpParam(row));
							}
							if (editable){
								parameditor.addChangeListener(changelistener);
							}
							editors.add(parameditor);


						}
						else{

							//Ein einzelner Wert oder One OfList
							if (tablemodel.getOpParam(row).isOneOf()){
								Collection list=tablemodel.getOpParam(row).getOneOfList();
								parameditor=new SingleOneOfValueEditor(app,step,tablemodel.getOpParam(row),list);
							}else{
								parameditor=new SingleValueEditor(app,step,tablemodel.getOpParam(row));
							}
							if (editable){
								parameditor.addChangeListener(changelistener);
							}
							editors.add(parameditor);


						}
	
					}else if (tablemodel.getOpParam(row).isConceptParameter()){

						if (tablemodel.getOpParam(row).isArray()){
							parameditor=new ListConceptEditor(app,step,tablemodel.getOpParam(row));
						}else{
							parameditor=new SingleConceptEditor(app,step,tablemodel.getOpParam(row));
						}
						if (editable){
							parameditor.addChangeListener(changelistener);
						}
						editors.add(parameditor);
										
					}else if (tablemodel.getOpParam(row).isRelationParameter()){

						if (tablemodel.getOpParam(row).isArray()){
							parameditor=new ListRelationEditor(app,step,tablemodel.getOpParam(row));
						}else{
							parameditor=new SingleRelationEditor(app,step,tablemodel.getOpParam(row));
						}
						if (editable){
							parameditor.addChangeListener(changelistener);
						}
						editors.add(parameditor);
						
					}else if (tablemodel.getOpParam(row).isBaseAttribParameter()){

						if (tablemodel.getOpParam(row).isArray()){
							parameditor=new ListBaseAttributeEditor(app,this, tablemodel.getOpParam(row));
						}else{
							parameditor=new SingleBaseAttributeEditor(app,this, tablemodel.getOpParam(row));
						}
						if (editable){
							parameditor.addChangeListener(changelistener);
						}
						editors.add(parameditor);
						
					}else if (tablemodel.getOpParam(row).isMcfParameter()){

						if (tablemodel.getOpParam(row).isArray()){
							parameditor=new ListMCFeatureEditor(app,this,tablemodel.getOpParam(row));
						}else{
							parameditor=new SingleMCFeatureEditor(app,this,tablemodel.getOpParam(row));
						}
						if (editable){
							parameditor.addChangeListener(changelistener);
						}
						editors.add(parameditor);
						
					}else if (tablemodel.getOpParam(row).isFeatureParameter()){

						if (tablemodel.getOpParam(row).isArray()){
							parameditor=new ListFeatureEditor(app,this,tablemodel.getOpParam(row));
						}else{
							parameditor=new SingleFeatureEditor(app,this,tablemodel.getOpParam(row));
						}
						if (editable){
							parameditor.addChangeListener(changelistener);
						}
						editors.add(parameditor);

					}else{
						System.out.println("Unexpected Parameter!");
						System.out.println("Step: "+step.getName());
						System.out.println("Operator: "+ step.getTheOperator().getName());
						System.out.println("OpParam: "+ tablemodel.getOpParam(row).getName());
	
						parameditor=new ParameterEditor();
						if (editable){
							parameditor.addChangeListener(changelistener);
						}
						editors.add(parameditor);
					}
				}else{
					//Output
					Collection coll=null;
					if ( ! tablemodel.getOpParam(row).isConceptParameter()) {
						try{
							coll=step.getPossibleConceptsForParam(tablemodel.getOpParam(row));
						}catch(M4Exception error){
							M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
						}
					}
					
					if ((coll!=null)&&(!coll.isEmpty())){
						//es existieren constraints fuer die Auswahl der Werte 
						
						if (tablemodel.getOpParam(row).isBaseAttribParameter()){
	
							if (tablemodel.getOpParam(row).isArray()){
								parameditor=new ListBaseAttributeEditor(app,this, tablemodel.getOpParam(row));
							}else{
								parameditor=new SingleBaseAttributeEditor(app,this, tablemodel.getOpParam(row));
							}
							if (editable){
								parameditor.addChangeListener(changelistener);
							}
							editors.add(parameditor);
							
						}else if (tablemodel.getOpParam(row).isMcfParameter()){
	
							if (tablemodel.getOpParam(row).isArray()){
								parameditor=new ListMCFeatureEditor(app,this,tablemodel.getOpParam(row));
							}else{
								parameditor=new SingleMCFeatureEditor(app,this,tablemodel.getOpParam(row));
							}
							if (editable){
								parameditor.addChangeListener(changelistener);
							}
							editors.add(parameditor);
							
						}else if (tablemodel.getOpParam(row).isFeatureParameter()){
	
							if (tablemodel.getOpParam(row).isArray()){
								parameditor=new ListFeatureEditor(app,this,tablemodel.getOpParam(row));
							}else{
								parameditor=new SingleFeatureEditor(app,this,tablemodel.getOpParam(row));
							}
							if (editable){
								parameditor.addChangeListener(changelistener);
							}
							editors.add(parameditor);
	
						}else{
							System.out.println("Unexpected Parameter!");
							System.out.println("Step: "+step.getName());
							System.out.println("Operator: "+ step.getTheOperator().getName());
							System.out.println("OpParam: "+ tablemodel.getOpParam(row).getName());

							parameditor=new ParameterEditor();
							if (editable){
								parameditor.addChangeListener(changelistener);
							}
							editors.add(parameditor);
						}						
						
					}else{
						//es existieren keine constraints
						//System.out.println("OpParam: "+tablemodel.getOpParam(row).getName());
						if (tablemodel.getOpParam(row).getMaxArg()==1){
							parameditor=new OutputEditor(app,step,tablemodel.getOpParam(row));
							if (editable){
								parameditor.addChangeListener(changelistener);
							}
							editors.add(parameditor);
						}else{
							parameditor=new ListOutputEditor(app,step,tablemodel.getOpParam(row));
							if (editable){
								parameditor.addChangeListener(changelistener);
							}
							editors.add(parameditor);
						}
					}
				}
			}catch(M4Exception error){
				M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
			}
		}

	}
	
	

	/**
	 * @see javax.swing.JTable#getCellEditor(int, int)
	 */
	public TableCellEditor getCellEditor(int row, int column) {
//		return super.getCellEditor(row, column);
		return (TableCellEditor) editors.get(row);
	}

	/**
	 * @see javax.swing.JTable#getCellRenderer(int, int)
	 */
	public TableCellRenderer getCellRenderer(int row, int column) {
		if ((column==1)&&(row<editors.size())){
			return (TableCellRenderer) editors.get(row);
		}
		return tablerenderer;
	}

	/**
	 * Sets the number of loops in the editor.
	 */ 
	public void setNrOfLoops(int nrOfLoops){
		if (nrOfLoops==0){
			nrOfLoops=1;
		}
//		System.out.println("nrOfLoops: "+nrOfLoops);
		tablemodel.setNrOfLoops(nrOfLoops);
		ParameterEditor editor;
		for(int e=0;e<editors.size();e++){
			editor=(ParameterEditor) editors.get(e);
			editor.setNumberOfLoops(nrOfLoops);
		}
	}

	
    /**
     *Sets the loopnumber
     */
	public void setLoopNumber(int loopnumber){
		tablemodel.setLoopNumber(loopnumber);
		ParameterEditor editor;
		for(int e=0;e<editors.size();e++){
			editor=(ParameterEditor) editors.get(e);
			editor.setLoopNumber(loopnumber);
		}
	}

    /**
     *Gets the <code>Step</code>.
     */
	public Step getTheStep(){
		return step;
	}

    /**
     *Gets a <code>Collection</code> of <code>Concept</code>s by their name from the specified <code>OpParam</code>-name.
     *The <code>Collection</code> contains <code>String</code>s. 
     */
	public Collection getConceptEditorValues(String opParamName){
		LinkedList values=new LinkedList();
		
		int row=tablemodel.getRowOfOpParamByName(opParamName);

		
		Object object=editors.get(row);
		if (object instanceof ListConceptEditor){
			values.addAll(((ListConceptEditor) object).getSelectedValues());
		}else if (object instanceof SingleConceptEditor){
			values.add(((SingleConceptEditor) object).getSelectedValue());
		}
	
		return values;	
	}
	
	/**
	 * Sets the <code>Collection</code>s of the input-parameters in the step.
	 */
	public void setParameterCollectionsInStep(boolean save) throws M4Exception{
		if (tablemodel.getNrOfLoops()!=step.getLoopCount()){
//			System.out.println("tablemodel loops: "+tablemodel.getNrOfLoops());
//			System.out.println("step loopcount:   "+step.getLoopCount());
			try{
				if (tablemodel.getNrOfLoops()==1){
					step.setLoopCount(0);
				}else{
					step.setLoopCount(tablemodel.getNrOfLoops());
				}
				//if (save)
				//	app.saveModel();
			}catch(M4Exception error){
				M4Interface.print.doPrint(Print.ERROR,Resource.getString("STEPSETTINGS_ERROR_SET_LOOPCOUNT")+"\n"+error.getMessage(),error);
				
				JOptionPane.showMessageDialog(
					app,
					Resource.getString("STEPSETTINGS_ERROR_SET_LOOPCOUNT")+"\n"
						+ error.getMessage(),
					Resource.getString("DIALOG_ERROR_TITLE"),
					JOptionPane.ERROR_MESSAGE);
				return;
			}
		}
		ParameterEditor editor;
		for(int e=0;e<editors.size();e++){
			editor=(ParameterEditor) editors.get(e);
			editor.setCollectionsInStep();
		}
		if (save)
			app.saveModel();
	}
	
	/**
	 * The values before editing will be displayed.
	 * They are also set to the step.
	 * This method only calls for every <code>ParameterEditor</code> the method <code>cancelEditing()</code>.
	 * @see edu.udo.cs.miningmart.m4.Step#setParameter(OpParam,Collection,int)
	 * @see edu.udo.cs.miningmart.gui.stepsettings.ParameterEditor#cancelEditing()
	 */	
	public void cancelEditing() throws M4Exception{
		//first set the old number of loops
		setNrOfLoops(tablemodel.getOldNrOfLoops());
		
		//second display the old parameter for each ParameterEditor
		ParameterEditor editor;
		for(int e=0;e<editors.size();e++){
			editor=(ParameterEditor) editors.get(e);
			editor.cancelEditing();
		}
		repaint();
	}
	

	/**
	 * Updates, renames or creates the output.
	 */	
	public void makeOutput(boolean inputchanged, boolean outputchanged, boolean loopcountlower, boolean loopcounthigher) throws M4Exception{
		Vector editoren=new Vector();

		ParameterEditor editor;
		for(int e=0;e<editors.size();e++){
			editor=(ParameterEditor) editors.get(e);
			if (!editor.getTheOpParam().isInput()){
				//Concepte zuerst anfuegen
				if (editor.getTheOpParam().isConceptParameter()){
					editoren.add(0,editor);
				}else{
					editoren.add(editor);
				}
			}
		}


		for(int i=0;i<editoren.size();i++){
			editor=(ParameterEditor) editoren.get(i);
				editor.makeOutput(inputchanged, outputchanged,loopcountlower,loopcounthigher);
		}
	}
	
	/**
	 * Gets the editor of the parameter.
	 * @return Returns a <code>Collection</code> of <code>ParameterEditor</code>.
	 */
	public Collection getEditor(){
		return editors;
	}
	
}
/*
$Log: StepParameterTable.java,v $
Revision 1.4  2006/04/11 14:10:13  euler
Updated license text.

Revision 1.3  2006/04/06 16:31:12  euler
Prepended license remark.

Revision 1.2  2006/03/16 14:53:38  euler
*** empty log message ***

Revision 1.1  2006/01/03 09:54:14  hakenjos
Initial version!

*/
