/*
 * 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.Collections;
import java.util.Iterator;
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.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.BaseAttribute;
import edu.udo.cs.miningmart.m4.Concept;
import edu.udo.cs.miningmart.m4.EstimatedStatistics;
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>.
 * To include the estimated statistics functionality, uncomment the lines of 
 * code that add the point to the concept editor context menu, in the class
 * edu.udo.cs.miningmart.gui.application.MiningMartDrawingView, method
 * createConceptJPopupMenu(int x, int y).
 * 
 * @author Timm Euler
 * @version $Id: EstimatedStatisticsDialog.java,v 1.5 2006/04/11 14:10:17 euler Exp $
 */
public class EstimatedStatisticsDialog extends JDialog implements ActionListener{
			
	private Vector baseAttributes;	
	private EstimatedStatistics myEstStat;
	private String conceptName;
	private JButton closeButton;	
	private JTable statalltable,stat1table,stat2table;
	
	public EstimatedStatisticsDialog(MiningMartApplication app, Concept theConcept){
		super(app,true);
		try {
			this.conceptName = theConcept.getName();
			this.myEstStat = theConcept.getEstimatedStatistics();
			this.baseAttributes = new Vector();
			this.baseAttributes.addAll(theConcept.getAllBaseAttributes());
			Collections.sort(this.baseAttributes, 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("ESTIMATES"));
		Font font=new Font("SansSerif",Font.BOLD,15);
		label.setFont(font);
		label.setHorizontalAlignment(SwingConstants.CENTER);	
		infopanel.add(label);

		label=new JLabel();
		label.setText(this.conceptName);
		font=new Font("SansSerif",Font.PLAIN,13);
		label.setFont(font);
		label.setHorizontalAlignment(SwingConstants.CENTER);	
		label.setForeground(Color.BLUE);
		infopanel.add(label);
		
		/* This is the label for the statalltable-scrollpane (see below).
		 * Where to put it?
		label=new JLabel();
		label.setText(Resource.getString("ESTIMATED_GLOBAL"));
		font=new Font("SansSerif",Font.BOLD,12);
		label.setFont(font);
		label.setHorizontalAlignment(SwingConstants.CENTER);
		*/
		
		//Button
		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(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("ESTIMATED_ATTRIBDATA"));
		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("ESTIMATED_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);

	}	

	/* (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();
		}
	}

	// returns the String that represents the given Value, or 
	// the String representing "unknown"
	private String getEstimatedValue(int value) {
		if (value == EstimatedStatistics.VALUE_INT_UNKNOWN) {
			return Resource.getString("ESTIMATE_UNKNOWN");
		}
		else {
			return (new Integer(value)).toString();
		}
	}
	// returns the String that represents the given Value, or 
	// the String representing "unknown"
	private String getEstimatedValue(double value) {
		if ((new Double(value)).equals(new Double(EstimatedStatistics.VALUE_DOUBLE_UNKNOWN))) {
			return Resource.getString("ESTIMATE_UNKNOWN");
		}
		else {
			return (new Double(value)).toString();
		}
	}
	// returns the String that represents the given Value, or 
	// the String representing "unknown"
	private String getEstimatedValue(String value) {
		if (value == null || value.equals(EstimatedStatistics.VALUE_DISCRETE_UNKNOWN)) {
			return Resource.getString("ESTIMATE_UNKNOWN");
		}
		else {
			return value;
		}
	}
	
	private class StatisticsAllTableModel extends AbstractTableModel{
		
			/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getColumnClass(int)
		 */
		public Class getColumnClass(int columnIndex) {
			return String.class;
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getColumnName(int)
		 */
		public String getColumnName(int column) {
			switch(column){
				case 0: return Resource.getString("ESTIMATED_ROWCOUNT");
				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 1;
		}

		/* (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) {
			switch(columnIndex){
				case 0: {
					return getEstimatedValue(myEstStat.getNumberOfRows());
				}
				default: return Resource.getString("ESTIMATE_UNKNOWN");
			}
		}

}

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


    	/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getColumnName(int)
		 */
		public String getColumnName(int column) {
			switch (column){
			    case 0: return Resource.getString("ESTIMATED_ATTRIBNAME");
				case 1: return Resource.getString("ESTIMATED_MIN");
				case 2: return Resource.getString("ESTIMATED_MAX");
				case 3: return Resource.getString("ESTIMATED_MISSING");
				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 4;
		}

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

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getValueAt(int, int)
		 */
		public Object getValueAt(int rowIndex, int columnIndex) {
			BaseAttribute ba = (BaseAttribute) baseAttributes.get(rowIndex);
			String attrName = ba.getName();
			switch (columnIndex){
				case 0: return attrName;
				case 1: return getEstimatedValue(myEstStat.getLowestValue(attrName));
				case 2: return getEstimatedValue(myEstStat.getBiggestValue(attrName));
				case 3: return getEstimatedValue(myEstStat.getNumberOfMissingValues(attrName));
				default: return Resource.getString("ESTIMATE_UNKNOWN");
			}
		}
	}

	private class Statistics2TableModel extends AbstractTableModel{
		
		private String[] attribNames;
		private String[] values;
		
		public Statistics2TableModel(){
			initNameArrays();
		}
		
		public void initNameArrays(){
			// create lists with all values and their attribute names:
			Vector attrNames = new Vector();
			Vector attrValues = new Vector();
			Iterator attrIt = baseAttributes.iterator();
			while (attrIt.hasNext()) {
				BaseAttribute myBa = (BaseAttribute) attrIt.next();
				String name = myBa.getName();
				Vector vals = myEstStat.getValueList(name);
				Iterator valIt = vals.iterator();
				while (valIt.hasNext()) {
					String value = (String) valIt.next();
					attrNames.add(name);
					attrValues.add(value);
				}
			}
			// make the arrays:
			this.attribNames = new String[attrNames.size()];
			this.values = new String[attrValues.size()];
			if (this.attribNames.length != this.values.length) {
				System.err.println("Error reading estimated statistics!");
				return;
			}
			for (int i = 0; i < this.attribNames.length; i++) {
				this.attribNames[i] = (String) attrNames.get(i);
				this.values[i] = (String) attrValues.get(i);
			}
		}
		
		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getColumnClass(int)
		 */
		public Class getColumnClass(int columnIndex) {
			return String.class;
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getColumnName(int)
		 */
		public String getColumnName(int column) {
			switch (column){
				case 0: return Resource.getString("ESTIMATED_ATTRIBNAME");
				case 1: return Resource.getString("ESTIMATED_VALUE");
				case 2: return Resource.getString("ESTIMATED_OCCUR");
				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 3;
		}

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

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getValueAt(int, int)
		 */
		public Object getValueAt(int rowIndex, int columnIndex) {
			switch (columnIndex){
				case 0: return this.attribNames[rowIndex];
				case 1: return this.values[rowIndex];
				case 2: return getEstimatedValue(myEstStat.getNumberOfOccurrences(this.attribNames[rowIndex], this.values[rowIndex]));
				default: return ":-)";
			}
		}
	}
}
/*
 * Historie
 * --------
 *
 * $Log: EstimatedStatisticsDialog.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/03/30 16:07:16  scholz
 * fixed author tags for release
 *
 * Revision 1.2  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.1  2006/01/18 16:58:58  euler
 * Added some basic estimations of statistics.
 * Will need improvements.
 *
 */
