/*
 * 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.application;

import java.awt.Color;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Vector;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

import org.jhotdraw.util.Iconkit;
import org.musoft.limo.application.Application;
import org.musoft.limo.application.IconCommandMenu;
import org.musoft.limo.application.Resource;
import org.musoft.limo.drawing.ModelDrawingView;

import edu.udo.cs.miningmart.exception.M4Exception;
import edu.udo.cs.miningmart.gui.concepteditor.ColumnsetPanel;
import edu.udo.cs.miningmart.gui.concepteditor.ConnectionPanel;
import edu.udo.cs.miningmart.gui.concepteditor.CreateRelationDialog;
import edu.udo.cs.miningmart.gui.concepteditor.FeaturePanel;
import edu.udo.cs.miningmart.gui.concepteditor.MappingPanel;
import edu.udo.cs.miningmart.gui.model.MiningMartRelation;
import edu.udo.cs.miningmart.m4.Chain;
import edu.udo.cs.miningmart.m4.Concept;
import edu.udo.cs.miningmart.m4.M4Interface;
import edu.udo.cs.miningmart.m4.Step;
import edu.udo.cs.miningmart.m4.utils.Print;

/**
 * A ModelDrawingView for MiningMart with methods for adding MiningMartSelectionListener.
 * @author Daniel Hakenjos
 * @version $Id: MiningMartDrawingView.java,v 1.10 2006/04/11 14:10:16 euler Exp $
 */
public class MiningMartDrawingView
	extends ModelDrawingView
	implements MouseListener {

	private LinkedList selectionlistener;
	private MiningMartApplication application;

	/**
	 * Constructor for MiningMartDrawingView.
	 */
	public MiningMartDrawingView(MiningMartApplication application) {
		super(application);
		this.application = application;
		selectionlistener = new LinkedList();
		addMouseListener(this);
	}

	/**
	 * Adds a <code>MiningMartSelectionListener</code>.
	 */
	public void addMiningMartSelectionListener(MiningMartSelectionListener listener) {
		selectionlistener.add(listener);
		super.addFigureSelectionListener(listener);
	}

	/**
	 * Removes a <code>MiningMartSelectionListener</code>.
	 */
	public void removeMiningMartSelectionListener(MiningMartSelectionListener listener) {
		selectionlistener.remove(listener);
		super.removeFigureSelectionListener(listener);
	}

	/**
	 * Rmoves all <code>MiningMartSelectionListener</code>.
	 */
	public void removeAllMiningMartSelectionListener() {
		MiningMartSelectionListener listener;
		for (int s = getMiningMartSelectionListenerCount() - 1; s >= 0; s--) {
			listener = getMiningMartSelectionListener(s);
			selectionlistener.remove(listener);
			super.removeFigureSelectionListener(listener);
		}
	}

	/**
	 * Gets the number of all <code>MiningMartSelectionListener</code>.
	 */
	public int getMiningMartSelectionListenerCount() {
		return selectionlistener.size();
	}

	/**
	 * Gets a <code>MiningMartSelectionListener</code> by the index.
	 */
	public MiningMartSelectionListener getMiningMartSelectionListener(int index) {
		return (MiningMartSelectionListener) selectionlistener.get(index);
	}

	/**
	 * @see java.awt.Component#getBackground()
	 */
	public Color getBackground() {
		return Resource.getColor("DRAWING_VIEW_BACKGROUNDCOLOR");
	}

	/**
	 * The <code>MiningMartSelectionListener</code> are also informed.
	 * @see CH.ifa.draw.standard.StandardDrawingView#fireSelectionChanged()
	 */
	protected void fireSelectionChanged() {
		
		//application.figureSelectionChanged(this);
		
		MiningMartSelectionListener listener;
		for (int s = getMiningMartSelectionListenerCount() - 1; s >= 0; s--) {
			listener = getMiningMartSelectionListener(s);
			listener.figureSelectionChanged(this);
		}
		super.fireSelectionChanged();
	}

	/**
	 * Not used.
	 * @see java.awt.event.MouseListener#mouseClicked(MouseEvent)
	 */
	public void mouseClicked(MouseEvent e) {
		if ((e.getModifiers() == MouseEvent.BUTTON1_MASK)&&(e.getClickCount()==2)){
			//handles double clicks with the left mouse-button
			
			//there should be only one MinigMartSelectionListener
			MiningMartSelectionListener listener =
				(MiningMartSelectionListener) selectionlistener.getFirst();
			if (listener.isAnythingSelected()){
				if (listener.isMiningMartStepSelected()){
					application.showStepSettings(listener.getSelectedMiningMartStep());
				}
				if (listener.isStepTransitionSelected()){
					application.promptShowAllTransitions();	
				}

			}
		}
	}

	/**
	 * Not used.
	 * @see java.awt.event.MouseListener#mouseEntered(MouseEvent)
	 */
	public void mouseEntered(MouseEvent e) {
	}

	/**
	 * Not used.
	 * @see java.awt.event.MouseListener#mouseExited(MouseEvent)
	 */
	public void mouseExited(MouseEvent e) {
	}

	/**
	 * Not used.
	 * @see java.awt.event.MouseListener#mouseReleased(MouseEvent)
	 */
	public void mouseReleased(MouseEvent e) {
	}

	/**
	 * @see java.awt.event.MouseListener#mousePressed(MouseEvent)
	 */
	public void mousePressed(MouseEvent e) {
		if (e.getModifiers() == MouseEvent.BUTTON3_MASK) {
			if (application.getEditorMode()==MiningMartApplication.CASE_MODE){
				createCaseJPopupMenu(e.getX(), e.getY());
			}else{
				createConceptJPopupMenu(e.getX(), e.getY());
			}
		}
	}

	/**
	 * Creates a JPopupMenu and shows it at the specified coordinates.
	 */
	public void createCaseJPopupMenu(int x, int y) {
		Iconkit kit = Iconkit.instance();
		JPopupMenu menu = new JPopupMenu();

		//there should be only one MinigMartSelectionListener
		MiningMartSelectionListener listener =
			(MiningMartSelectionListener) selectionlistener.getFirst();

		if (application.getViewMode()==Application.EDITOR){
			application.setPointForOperator(new Point(x,y));
			IconCommandMenu operators=((MiningMartMenuBar) application.getJMenuBar()).getOperatorsMenu();
			menu.add(operators);
		}

		ExecutableMenuItem menuitem;
		if (listener.isAnythingSelected()) {
			
			if (listener.isStepTransitionSelected()){
/*				menuitem =
					new ExecutableMenuItem(
						Resource.getString("MENU_INSERT_SHOW_CONCEPT"),
						new ImageIcon(
							kit.loadImageResource(
								Resource.getString(
									"MENU_ICON_INSERT_SHOW_CONCEPT"))),listener) {
					public void execute() {
						StepTransition trans=getListener().getSelectedStepTransition();
						if (trans.getStart() instanceof MiningMartStep){
							Concept concept=null;

							try{
								ModelFigureElement start=trans.getStart();
								if (start instanceof MiningMartStep){
									Step step=((MiningMartStep) start).getStep();
									OpParam input=null,output=null;
									Iterator iter=step.getTheOperator().getOpParamsIterator();
									OpParam opparam;
									while (iter.hasNext()){
										opparam=(OpParam) iter.next();
										if (opparam.getName().equals("TheInputConcept")){
											input=opparam;
										}else
										if (opparam.getName().equals("TheOutputConcept")){
											output=opparam;
										}
									}
						
									if (output!=null){
										Collection params=step.getParameter(output,0);
										if ((params!=null)&&(params.size()>0)){
											iter=params.iterator();
											if (iter.hasNext()){
												concept=(Concept) iter.next();
											}
										}
									}else if (input !=null){
										Collection params=step.getParameter(input,0);
										if ((params!=null)&&(params.size()>0)){
											iter=params.iterator();
											if (iter.hasNext()){
												concept=(Concept) iter.next();
											}
										}
									}
								}
							
							}catch(M4Exception error){
								M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
								concept=null;
							}


							if (concept!=null){
								application.showConceptEditor();
								MiningMartApplication.conceptEditor.getDialogManager().showConceptDialog(concept);
							}
						}
					}
				};
				menu.add(menuitem);
				*/

			}
			
			//if a figure is selected then
			// 1) Show step settings
			if (listener.isMiningMartStepSelected()) {
				menuitem =
					new ExecutableMenuItem(
						Resource.getString("MENU_INSERT_SHOW_STEPSETTINGS"),
						new ImageIcon(
							kit.loadImageResource(
								Resource.getString(
									"MENU_ICON_INSERT_SHOW_STEPSETTINGS"))),listener) {
					public void execute() {
						application.showStepSettings(
							getListener().getSelectedMiningMartStep());
					}
				};
				menu.add(menuitem);

				menuitem =
					new ExecutableMenuItem(
						Resource.getString("MENU_INSERT_SHOW_DATAMODEL"),
						new ImageIcon(
							kit.loadImageResource(
								Resource.getString(
									"MENU_ICON_INSERT_SHOW_DATAMODEL"))),listener) {
					public void execute() {
						MiningMartApplication app=application;
						MiningMartSelectionListener listener=this.getListener();
						
						String casename=app.getModel().getName();
						if (app.getEditorMode()==MiningMartApplication.CONCEPT_MODE){
							casename=M4Interface.getCurrentCase().getName();
						}
						
						// collect the names of the concepts to be displayed:
						Step step=listener.getSelectedMiningMartStep().getStep();
						Iterator it = null;
						try {
							it = step.getResultingDataModel().iterator();
						} catch (M4Exception e) {
							M4Interface.print.doPrint(Print.ERROR,e.getMessage(),e);
						}
						Vector conceptNames = new Vector();
						while (it.hasNext()) {
							Concept myCon = (Concept) it.next();
							conceptNames.add(myCon.getName());
						}
						boolean editing=app.getViewMode()==Application.EDITOR;
						// close case editor view (also clears M4 cache):
						if (!app.promptClose()){
							return;
						}
						
						// open concept editor with only the given concepts:
						app.setDataModel(conceptNames);
						app.setEditorMode(MiningMartApplication.CONCEPT_MODE);
						app.promptOpen(casename,editing);
					}
				};
				menu.add(menuitem);
			}

			// 2) Dissolve Chain
			if (listener.isMiningMartChainSelected()) {
				menuitem =
					new ExecutableMenuItem(
						Resource.getString("MENU_INSERT_UNMERGE_CHAIN"),
						new ImageIcon(
							kit.loadImageResource(
								Resource.getString(
									"MENU_ICON_INSERT_UNMERGE_CHAIN")))) {
					public void execute() {
						application.promptUnmergeChain();
					}
				};
				menu.add(menuitem);

				menuitem =
					new ExecutableMenuItem(
						Resource.getString("MENU_INSERT_SHOW_CHAINCONCEPTS"),
						new ImageIcon(
							kit.loadImageResource(
								Resource.getString(
									"MENU_ICON_INSERT_SHOW_DATAMODEL"))),listener) {
					public void execute() {
						MiningMartApplication app=application;
						MiningMartSelectionListener listener=this.getListener();
						
						String casename=app.getModel().getName();
						if (app.getEditorMode()==MiningMartApplication.CONCEPT_MODE){
							casename=M4Interface.getCurrentCase().getName();
						}

						// collect the names of the concepts to be displayed:
						Chain chain=listener.getSelectedMiningMartChain().getChain();
						Iterator it = null;
						try {
							it = chain.getInvolvedConcepts().iterator();
						} catch (M4Exception e) {
							M4Interface.print.doPrint(Print.ERROR,e.getMessage(),e);
						}
						Vector conceptNames = new Vector();
						while (it.hasNext()) {
							Concept myCon = (Concept) it.next();
							conceptNames.add(myCon.getName());
						}
						boolean editing=app.getViewMode()==Application.EDITOR;
						if (!app.promptClose()){
							return;
						}
						
						// open concept editor with only the given concepts:
						app.setDataModel(conceptNames);
						app.setEditorMode(MiningMartApplication.CONCEPT_MODE);
						app.promptOpen(casename,editing);
					}
				};
				menu.add(menuitem);
			}

			// 3) Delete
			menuitem =
				new ExecutableMenuItem(
					Resource.getString("MENU_EDIT_DELETE"),
					new ImageIcon(
						kit.loadImageResource(
							Resource.getString("MENU_ICON_EDIT_DELETE"))), listener) {
				public void execute() {
					if (getListener().isMiningMartChainSelected()){
						getListener().getSelectedMiningMartChain().destroy();
					}else if (getListener().isMiningMartStepSelected()){
						getListener().getSelectedMiningMartStep().destroy();
					}else if (getListener().isStepTransitionSelected()){
						getListener().getSelectedStepTransition().destroy();
					}
					((MiningMartDrawingView) application.getMainPane().getDrawingView()).repaint();
				}
			};
			if (application.getViewMode()==Application.EDITOR){
				menu.add(menuitem);
			}

		} else {
			//if nothing is selected
			// 1) Add Operator

		}

		if (menu.getComponents().length>0){
			menu.addSeparator();
		}
		//In both cases
		//
		// 1) Close Tab
			menuitem =
				new ExecutableMenuItem(
					Resource.getString("MENU_WINDOW_CLOSE_TAB"),
					new ImageIcon(
						kit.loadImageResource(
							Resource.getString("MENU_ICON_WINDOW_CLOSE_TAB")))) {
				public void execute() {
					application.getMainPane().remove(application.getMainPane().getCurrentPanel());
				}
			};
			menu.add(menuitem);


		menu.pack();

		menu.show(this, x, y);
	}

	/**
	 * Creates a JPopupMenu and shows it at the specified coordinates.
	 */
	public void createConceptJPopupMenu(int x, int y) {
		Iconkit kit = Iconkit.instance();
		JPopupMenu menu = new JPopupMenu();

		//there should be only one MinigMartSelectionListener
		MiningMartSelectionListener listener =
			(MiningMartSelectionListener) selectionlistener.getFirst();

		if (application.getViewMode()==Application.EDITOR){
			//new Copncept
		}
		
		ExecutableMenuItem menuitem;
		if (listener.isMiningMartConceptSelected()){
			
			menuitem =new ExecutableMenuItem( "Show BaseAttributes",
					new ImageIcon(kit.loadImageResource(Resource.getString("MENU_ICON_SHOW_FEATURE"))), listener) {
				public void execute() {
					FeaturePanel panel=new FeaturePanel(application,getListener().getSelectedMiningMartConcept(), true);
					application.showConceptPanel(panel);
				}
			};
			menu.add(menuitem);
			
			menuitem =new ExecutableMenuItem( "Show MultiColumnFeatures",
					new ImageIcon(kit.loadImageResource(Resource.getString("MENU_ICON_SHOW_FEATURE"))), listener) {
				public void execute() {
					FeaturePanel panel=new FeaturePanel(application,getListener().getSelectedMiningMartConcept(), false);
					application.showConceptPanel(panel);
				}
			};
			menu.add(menuitem);

			if (listener.getSelectedMiningMartConcept().getConcept().getType().equals(Concept.TYPE_DB)){
				menuitem =new ExecutableMenuItem( "Create Connection",
						new ImageIcon(kit.loadImageResource(Resource.getString("MENU_ICON_CONCEPT_CONNECTION"))), listener) {
					public void execute() {
						ConnectionPanel panel=new ConnectionPanel(application,getListener().getSelectedMiningMartConcept().getConcept());
						application.showConceptPanel(panel);
					}
				};
				menu.add(menuitem);
				
				Concept concept=listener.getSelectedMiningMartConcept().getConcept();
				int nrcolumnsets=0;
				try{
					Collection coll=concept.getColumnSets();
					if (coll!=null){
						nrcolumnsets=coll.size();
					}
				}catch(Exception e){
					nrcolumnsets=0;
				}
				if (nrcolumnsets!=0){
					menuitem =new ExecutableMenuItem( "Show Mapping",
							new ImageIcon(kit.loadImageResource(Resource.getString("MENU_ICON_CONCEPT_MAPPING"))), listener) {
						public void execute() {
							MappingPanel panel=new MappingPanel(application,getListener().getSelectedMiningMartConcept().getConcept());
							application.showConceptPanel(panel);
						}
					};
					menu.add(menuitem);
				}
			}

			menuitem =new ExecutableMenuItem( "Show Columnsets",
					new ImageIcon(kit.loadImageResource(Resource.getString("MENU_ICON_SHOW_FEATURE"))), listener) {
				public void execute() {
					ColumnsetPanel panel=new ColumnsetPanel(application,getListener().getSelectedMiningMartConcept().getConcept());
					application.showConceptPanel(panel);
				}
			};
			menu.add(menuitem);			

			/*
			menuitem =new ExecutableMenuItem( "Show estimated statistics",
					new ImageIcon(kit.loadImageResource(Resource.getString("MENU_ICON_SHOW_FEATURE"))), listener) {
				public void execute() {
					Concept con = getListener().getSelectedMiningMartConcept().getConcept();					
					new EstimatedStatisticsDialog(application,con);				
				}
			};
			menu.add(menuitem);
			*/
		}
		
		if (listener.isMiningMartRelationSelected()){
			
			menuitem =new ExecutableMenuItem( "Edit Relation...",
					new ImageIcon(kit.loadImageResource(Resource.getString("MENU_ICON_SHOW_FEATURE"))), listener) {
				public void execute() {
					MiningMartRelation mmartrelation=getListener().getSelectedMiningMartRelation();
					new CreateRelationDialog(application,mmartrelation);
				}
			};

			menu.add(menuitem);

		}

		if (listener.isAnythingSelected()) {
			
			// 3) Delete
			menuitem =new ExecutableMenuItem( Resource.getString("MENU_EDIT_DELETE"),
					new ImageIcon(kit.loadImageResource(Resource.getString("MENU_ICON_EDIT_DELETE"))), listener) {
				public void execute() {
					if (getListener().isMiningMartChainSelected()){
						getListener().getSelectedMiningMartChain().destroy();
					}else if (getListener().isMiningMartStepSelected()){
						getListener().getSelectedMiningMartStep().destroy();
					}else if (getListener().isStepTransitionSelected()){
						getListener().getSelectedStepTransition().destroy();
					}else if (getListener().isMiningMartConceptSelected()){
						getListener().getSelectedMiningMartConcept().destroy();
					}else if (getListener().isMiningMartProjectionSelected()){
						getListener().getSelectedMiningMartProjection().destroy();
					}else if (getListener().isMiningMartRelationSelected()){
						getListener().getSelectedMiningMartRelation().destroy();
					}else if (getListener().isMiningMartSubConceptSelected()){
						getListener().getSelectedMiningMartSubConcept().destroy();
					}
					((MiningMartDrawingView) application.getMainPane().getDrawingView()).repaint();
				}
			};
			if (application.getViewMode()==Application.EDITOR){
				menu.add(menuitem);
			}

		} else {
	
		}

		if (menu.getComponents().length>0){
			menu.addSeparator();
		}

		// 1) Close Tab
			menuitem =
				new ExecutableMenuItem(
					Resource.getString("MENU_WINDOW_CLOSE_TAB"),
					new ImageIcon(
						kit.loadImageResource(
							Resource.getString("MENU_ICON_WINDOW_CLOSE_TAB")))) {
				public void execute() {
					application.getMainPane().remove(application.getMainPane().getCurrentPanel());
				}
			};
			menu.add(menuitem);


		menu.pack();

		menu.show(this, x, y);
	}


	/**
	* A JMenuItem that executes itself.
	* For your own JMenuItem you must overwrite the <code>execute()</code>-method
	* @see #execute()
	*/
	private class ExecutableMenuItem extends JMenuItem implements ActionListener {
		private MiningMartSelectionListener listener;

		public ExecutableMenuItem(String text, Icon icon) {
			super(text, icon);
			addActionListener(this);
		}


		public ExecutableMenuItem(String text, Icon icon, MiningMartSelectionListener listener) {
			super(text, icon);
			this.listener=listener;
			addActionListener(this);
		}

		public ExecutableMenuItem(String text, Icon icon, char mnemonic) {
			super(text, icon);
			this.setMnemonic(mnemonic);
			addActionListener(this);
		}

		/**
		 * @see java.awt.event.ActionListener#actionPerformed(ActionEvent)
		 */
		public void actionPerformed(ActionEvent e) {
			execute();
		}

		/**
		 * For your own MenuItem you must overwrite this method.
		 */
		public void execute() {
		}
		
		public MiningMartSelectionListener getListener(){
			return listener;
		}

	}

}
/*
$Log: MiningMartDrawingView.java,v $
Revision 1.10  2006/04/11 14:10:16  euler
Updated license text.

Revision 1.9  2006/04/06 16:31:15  euler
Prepended license remark.

Revision 1.8  2006/01/27 17:27:17  euler
Bugfix

Revision 1.7  2006/01/24 14:03:49  euler
Added display of concepts involved in a chain.

Revision 1.6  2006/01/24 12:31:45  euler
Added recognition of key type for new columns.
Removed EstimatedStatistics from context menu
because they are in too basic status for the release.

Revision 1.5  2006/01/18 16:58:58  euler
Added some basic estimations of statistics.
Will need improvements.

Revision 1.4  2006/01/12 09:31:45  hakenjos
Edit Relation...

Revision 1.3  2006/01/10 07:29:49  hakenjos
Show Mapping available if at least one ColumnSet exists.

Revision 1.2  2006/01/03 11:29:14  hakenjos
Delete Concept, SubConcept, Relation and Projection in Contextmenu.

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

*/
