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

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.AbstractTableModel;

import org.musoft.limo.application.Application;
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.gui.util.M4ObjectComparator;
import edu.udo.cs.miningmart.m4.Column;
import edu.udo.cs.miningmart.m4.ColumnStatistics2;
import edu.udo.cs.miningmart.m4.Columnset;
import edu.udo.cs.miningmart.m4.M4Interface;
import edu.udo.cs.miningmart.m4.utils.Print;

/**
 * A <code>JDialog</code> to show the statistics of a <code>Columnset</code>.
 * 
 * @author Daniel Hakenjos
 * @version $Id: StatisticsDialog.java,v 1.5 2006/04/11 14:10:17 euler Exp $
 */
public class StatisticsDialog extends JDialog implements ActionListener{
	
	private MiningMartApplication app;
	
	private Columnset columnset;
	
	private Vector columns;
	
	private JButton closeButton, updateButton;
	
	private JTable statalltable,stat1table,stat2table;
	
	public StatisticsDialog(MiningMartApplication app, Columnset columnset){
		super(app,true);
		this.app=app;
		this.columnset=columnset;
		try {
			this.columnset.updateStatistics();

			this.columns=new Vector();
			this.columns.addAll(columnset.getColumns());
			Collections.sort(columns,new M4ObjectComparator());
		} catch (M4Exception error) {
			M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
		}
		
		initComponents();
		this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
	
		this.pack();
	
		setSize(750, 600);
	
		Dimension size = this.getSize();
	
		this.setLocation(
			(Toolkit.getDefaultToolkit().getScreenSize().width - size.width)
				/ 2,
			(Toolkit.getDefaultToolkit().getScreenSize().height - size.height)
				/ 2);
		this.setVisible(true);
	}
	
	private void initComponents(){
		
		JPanel toppanel=new JPanel();
		toppanel.setLayout(new BorderLayout(5,5));
		toppanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
		this.getContentPane().add(toppanel);

		//Info
		JPanel infopanel=new JPanel();
		infopanel.setLayout(new GridLayout(2,1,5,5));
		infopanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
		toppanel.add(infopanel,BorderLayout.NORTH);	

		JLabel label=new JLabel();
		label.setText(Resource.getString("COLUMNSET")+" - "+Resource.getString("STATISTICS"));
		Font font=new Font("SansSerif",Font.BOLD,15);
		label.setFont(font);
		label.setHorizontalAlignment(SwingConstants.CENTER);	
		infopanel.add(label);

		label=new JLabel();
		label.setText(columnset.getName());
		font=new Font("SansSerif",Font.PLAIN,13);
		label.setFont(font);
		label.setHorizontalAlignment(SwingConstants.CENTER);	
		label.setForeground(Color.BLUE);
		infopanel.add(label);

		//Button		
		
		updateButton=new JButton(Resource.getString("UPDATE"));
		updateButton.addActionListener(this);
		if (app.getViewMode()!=Application.EDITOR){
			updateButton.setEnabled(false);			
		}

		closeButton=new JButton(Resource.getString("CLOSE"));
		closeButton.addActionListener(this);

		JPanel buttonPanel=new JPanel();
		buttonPanel.setLayout(new BoxLayout(buttonPanel,BoxLayout.X_AXIS));
		buttonPanel.add(Box.createHorizontalGlue());
		
		buttonPanel.add(updateButton);
		buttonPanel.add(Box.createRigidArea(new Dimension(5, 0)));		
		buttonPanel.add(closeButton);
		toppanel.add(buttonPanel,BorderLayout.SOUTH);

		JPanel midpanel=new JPanel();
		midpanel.setLayout(new BorderLayout(5,5));		
		toppanel.add(midpanel,BorderLayout.CENTER);
	

		//Statistics all
		statalltable=new JTable();
		statalltable.setSelectionMode(javax.swing.ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		statalltable.getTableHeader().setReorderingAllowed(false);
		statalltable.setRowHeight(statalltable.getRowHeight() + 2);
		statalltable.setModel(new StatisticsAllTableModel());
		JScrollPane scrollpane=new JScrollPane(statalltable);
		scrollpane.setPreferredSize(new Dimension(scrollpane.getWidth(),36));
		midpanel.add(scrollpane,BorderLayout.NORTH);
										
		JPanel centerPanel=new JPanel();
		centerPanel.setLayout(new GridLayout(2,1,5,5));
		midpanel.add(centerPanel,BorderLayout.CENTER);

		//Statistics1
		JPanel stat1panel=new JPanel();
		stat1panel.setLayout(new BorderLayout(5,5));
		centerPanel.add(stat1panel);
		
		label=new JLabel();
		label.setText(Resource.getString("STATISTICS_NUMERICAL"));
		font=new Font("SansSerif",Font.BOLD,12);
		label.setFont(font);
		label.setHorizontalAlignment(SwingConstants.CENTER);	
		stat1panel.add(label,BorderLayout.NORTH);

		stat1table=new JTable();
		stat1table.setSelectionMode(javax.swing.ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		stat1table.getTableHeader().setReorderingAllowed(false);
		stat1table.setRowHeight(stat1table.getRowHeight() + 2);
		stat1table.setModel(new Statistics1TableModel());
		stat1panel.add(new JScrollPane(stat1table),BorderLayout.CENTER);
		
		//Statistics2
		JPanel stat2panel=new JPanel();
		stat2panel.setLayout(new BorderLayout(5,5));
		centerPanel.add(stat2panel);
		
		label=new JLabel();
		label.setText(Resource.getString("STATISTICS_DISTRIBUTION"));
		font=new Font("SansSerif",Font.BOLD,12);
		label.setFont(font);
		label.setHorizontalAlignment(SwingConstants.CENTER);	
		stat2panel.add(label,BorderLayout.NORTH);

		stat2table=new JTable();
		stat2table.setSelectionMode(javax.swing.ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		stat2table.getTableHeader().setReorderingAllowed(false);
		stat2table.setRowHeight(stat2table.getRowHeight() + 2);
		stat2table.setModel(new Statistics2TableModel());
		stat2panel.add(new JScrollPane(stat2table),BorderLayout.CENTER);

	}
	
	
	private void updateStatistics(){
		try {
			this.columnset.clearStatistics();
			this.columnset.updateStatistics();
		} catch (M4Exception error) {
			M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
		}
		
		((Statistics2TableModel) stat2table.getModel()).initDistribution();
		((AbstractTableModel) statalltable.getModel()).fireTableDataChanged();
		((AbstractTableModel) stat1table.getModel()).fireTableDataChanged();
		((AbstractTableModel) stat2table.getModel()).fireTableDataChanged();

		app.getModel().setDirty(true);
	}
	

	/* (non-Javadoc)
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent event) {
		if (!(event.getSource() instanceof JButton))
			return;
		JButton source=(JButton) event.getSource();
		
		if (source.getText().equals(closeButton.getText())){
			dispose();
		}
		if (source.getText().equals(updateButton.getText())){
			updateStatistics();
		}
	}


	private class StatisticsAllTableModel extends AbstractTableModel{
		
			/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getColumnClass(int)
		 */
		public Class getColumnClass(int columnIndex) {
			return Integer.class;
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getColumnName(int)
		 */
		public String getColumnName(int column) {
			switch(column){
				case 0: return Resource.getString("STATISTICS_TUPLES");
				case 1: return Resource.getString("STATISTICS_COLUMNS");
				case 2: return Resource.getString("STATISTICS_ORDINAL");
				case 3: return Resource.getString("STATISTICS_NOMINAL");
				case 4: return Resource.getString("STATISTICS_TIME");
				default: return ":-)";
			}
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#isCellEditable(int, int)
		 */
		public boolean isCellEditable(int rowIndex, int columnIndex) {
			return false;
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getColumnCount()
		 */
		public int getColumnCount() {
			return 5;
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getRowCount()
		 */
		public int getRowCount() {
			return 1;
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getValueAt(int, int)
		 */
		public Object getValueAt(int rowIndex, int columnIndex) {
			try{
				switch(columnIndex){
					case 0: return new Integer(columnset.getStatisticsAll());
					case 1: return new Integer(columnset.getColumns().size());
					case 2: return new Integer(columnset.getStatisticsOrdinal());
					case 3: return new Integer(columnset.getStatisticsNominal());
					case 4: return new Integer(columnset.getStatisticsTime());
					default: return new Integer(0);
				}
			}catch(M4Exception error){
				M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
			}
			return new Integer(0);
		}

}

	private class Statistics1TableModel extends AbstractTableModel{
		
		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getColumnClass(int)
		 */
		public Class getColumnClass(int columnIndex) {
			switch (columnIndex){
				case 0: return String.class;
				case 1: return Integer.class;
				case 2: return Integer.class;
				case 3: return String.class;
				case 4: return String.class;
				case 5: return Double.class;
				case 6: return Double.class;
				case 7: return Double.class;
				case 8: return Double.class;
				case 9: return String.class;
				default: return String.class;
			}
		}


    	/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getColumnName(int)
		 */
		public String getColumnName(int column) {
			switch (column){
				case 0: return Resource.getString("STATISTICS_COLUMNNAME");
				case 1: return Resource.getString("STATISTICS_UNIQUE");
				case 2: return Resource.getString("STATISTICS_MISSING");
				case 3: return Resource.getString("STATISTICS_MIN");
				case 4: return Resource.getString("STATISTICS_MAX");
				case 5: return Resource.getString("STATISTICS_AVG");
				case 6: return Resource.getString("STATISTICS_MEDIAN");
				case 7: return Resource.getString("STATISTICS_STDEV");
				case 8: return Resource.getString("STATISTICS_VARIANCE");
				case 9: return Resource.getString("STATISTICS_MODAL");
				default: return ":-)";
			}
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#isCellEditable(int, int)
		 */
		public boolean isCellEditable(int rowIndex, int columnIndex) {
			return false;
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getColumnCount()
		 */
		public int getColumnCount() {
			return 10;
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getRowCount()
		 */
		public int getRowCount() {
			return columns.size();
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getValueAt(int, int)
		 */
		public Object getValueAt(int rowIndex, int columnIndex) {
			try {
				Column column=(Column) columns.get(rowIndex);

				switch (columnIndex){
					case 0: return column.getName();
					case 1: return new Integer(column.getNumberOfUniqueValues());
					case 2: return new Integer(column.getNumberOfMissingValues());
					case 3:{
						if ((column.getMinValue()==null)||(column.getMinValue().length()==0)){
							return ""; 
						}
						return column.getMinValue();
					}
					case 4:{ 
						if ((column.getMaxValue()==null)||(column.getMaxValue().length()==0)){
							return ""; 
						}
						return column.getMaxValue();
					}
					case 5:{ 
						if ((column.getAverageValue()==null)||(column.getAverageValue().length()==0)){
							return new Double(Double.NaN); 
						}
						return new Double(column.getAverageValue());
					}
					case 6:{ 
						if ((column.getMedianValue()==null)||(column.getMedianValue().length()==0)){
							return new Double(Double.NaN); 
						}
						return new Double(column.getMedianValue());
					}
					case 7:{ 
						if ((column.getStandardDeviation()==null)||(column.getStandardDeviation().length()==0)){
							return new Double(Double.NaN); 
						}
						return new Double(column.getStandardDeviation());
					}
					case 8:{ 
						if ((column.getVariance()==null)||(column.getVariance().length()==0)){
							return new Double(Double.NaN); 
						}
						return new Double(column.getVariance());
					}
					case 9:{ 
						if (column.getModalValue()==null){
							return ""; 
						}
						return column.getModalValue();
					}
					default: return null;
				}

			} catch (M4Exception error){
				M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
			}
			
			return null;
		}

	}

	private class Statistics2TableModel extends AbstractTableModel{
		
		private Vector distribution;
		
		public Statistics2TableModel(){
			initDistribution();
		}
		
		public void initDistribution(){
			distribution=new Vector();
			Column column;
			Collection dists;
			for(int i=0;i<columns.size();i++){			
				column=(Column) columns.get(i);
				try {
					dists=column.getDistributionStatistics();
				} catch (M4Exception error) {
					M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
					dists=new LinkedList();
				}
				distribution.addAll(dists);
			}
		}
		
		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getColumnClass(int)
		 */
		public Class getColumnClass(int columnIndex) {
			switch (columnIndex){
				case 0: return String.class;
				case 1: return String.class;
				case 2: return Integer.class;
				case 3: return Double.class;
				case 4: return Double.class;
				default: return String.class;
			}
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getColumnName(int)
		 */
		public String getColumnName(int column) {
			switch (column){
				case 0: return Resource.getString("STATISTICS_COLUMNNAME");
				case 1: return Resource.getString("STATISTICS_VALUE");
				case 2: return Resource.getString("STATISTICS_COUNT");
				case 3: return Resource.getString("STATISTICS_MIN");
				case 4: return Resource.getString("STATISTICS_MAX");
				default: return ":-)";
			}
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#isCellEditable(int, int)
		 */
		public boolean isCellEditable(int rowIndex, int columnIndex) {
			return false;
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getColumnCount()
		 */
		public int getColumnCount() {
			return 5;
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getRowCount()
		 */
		public int getRowCount() {
			return distribution.size();
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getValueAt(int, int)
		 */
		public Object getValueAt(int rowIndex, int columnIndex) {
			ColumnStatistics2 stat2=(ColumnStatistics2) distribution.get(rowIndex);
			switch (columnIndex){
				case 0: return stat2.getTheColumn().getName();
				case 1: return stat2.getDistributionValue();
				case 2: return new Integer(stat2.getDistributionCount());
				case 3: return new Double(stat2.getDistributionMinimum());
				case 4: return new Double(stat2.getDistributionMaximum());
				default: return ":-)";
			}
		}

	}

}
/*
 * Historie
 * --------
 *
 * $Log: StatisticsDialog.java,v $
 * Revision 1.5  2006/04/11 14:10:17  euler
 * Updated license text.
 *
 * Revision 1.4  2006/04/06 16:31:16  euler
 * Prepended license remark.
 *
 * Revision 1.3  2006/01/13 01:19:46  scholz
 * improved statistics computation
 *
 * Revision 1.2  2006/01/12 20:35:18  scholz
 * bugfix statistics
 *
 * Revision 1.1  2006/01/03 09:54:25  hakenjos
 * Initial version!
 *
 */

/*
Revision 1.4  2005/12/13 09:32:34  hakenjos
Initial version!

Revision 1.3  2005/11/24 09:50:28  hakenjos
Names etc. replaced with resource-access

Revision 1.2  2005/11/17 10:57:26  hakenjos
*** empty log message ***

Revision 1.1  2005/11/10 10:48:44  hakenjos
*** empty log message ***

 */
