/**
 *#########################################################################
 *
 * A component of the Gatherer application, part of the Greenstone digital
 * library suite from the New Zealand Digital Library Project at the
 * University of Waikato, New Zealand.
 *
 * <BR><BR>
 *
 * Author: John Thompson, Greenstone Digital Library, University of Waikato
 *
 * <BR><BR>
 *
 * Copyright (C) 1999 New Zealand Digital Library Project
 *
 * <BR><BR>
 *
 * 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.
 *
 * <BR><BR>
 *
 * 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.
 *
 * <BR><BR>
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *########################################################################
 */
package org.greenstone.gatherer.gui.metaaudit;

import de.qfs.lib.gui.*;
import java.awt.*;
import java.util.ArrayList;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.table.*;
import org.greenstone.gatherer.Dictionary;
import org.greenstone.gatherer.collection.CollectionTreeNode;
import org.greenstone.gatherer.metadata.MetadataAuditTableModel;


/**
 * @author John Thompson, Greenstone Digital Library, University of Waikato
 * @version 2.3
 */
public class MetaAuditTable
    extends JTable 
    implements TableModelSorterListener {

    private boolean initial_state;

    private Filter filter;

    private HeaderRenderer header_renderer;

    private MetaAuditFrame parent_frame;

    private MetaAuditRenderer cell_renderer;

    private MetadataAuditTableModel metadata_audit_table_model;

    private SortedTableHelper helper;

    static final private int MARGIN = 10;

    public MetaAuditTable(MetaAuditFrame parent_frame) {
	super();
        this.setComponentOrientation(Dictionary.getOrientation());
	this.cell_renderer = new MetaAuditRenderer();
	this.header_renderer = new HeaderRenderer();
	this.parent_frame = parent_frame;
	getTableHeader().addMouseListener(new HeaderListener(parent_frame, this));
	setAutoResizeMode(AUTO_RESIZE_OFF);
    }

    public Filter getFilter() {
	return filter;
    }


   public MetadataAuditTableModel getOriginalModel()
   {
      return metadata_audit_table_model;
   }


    public TableModelSorter getSorter() {
	return helper.getTableModelSorter();
    }

    public boolean isFiltered(int column) {
	if(filter == null) {
	    return false;
	}
	return filter.isFiltered(column);
    }

    public void newModel(CollectionTreeNode records[]) {
	if(records == null || records.length == 0) {
	    setModel(new DefaultTableModel());
	    return;
	}
	wait(true);
	initial_state = true;
	// System.err.println("Build new Model - should only be called once per click!");
	metadata_audit_table_model = new MetadataAuditTableModel();
	metadata_audit_table_model.rebuild(records);
	setModel(metadata_audit_table_model);
	filter = new Filter(metadata_audit_table_model.getColumnCount());
	helper = new SortedTableHelper (this, filter, new DefaultTableModelSorter(), header_renderer, null);
	helper.prepareTable();
	// Add renderer to columns.
	TableColumnModel column_model = getColumnModel();
	for(int i = 0; i < column_model.getColumnCount(); i++) {
	    column_model.getColumn(i).setCellRenderer(cell_renderer);
	    column_model.getColumn(i).setHeaderRenderer(header_renderer);
	}
	wait(false);
	initial_state = false;
    }

    public void tableChanged(TableModelEvent e) {
	wait(true);
	super.tableChanged(e);

	// Create storage area
	ArrayList heights[] = new ArrayList[dataModel.getRowCount()];
	int widths_value[] = new int[dataModel.getColumnCount()];
	ArrayList widths[] = new ArrayList[dataModel.getColumnCount()];

	// Iterate through cell values finding tallest and widest for each row and column respectively.
	for (int j = 0; j < dataModel.getRowCount(); j++) {
	    for (int k = 0; k < dataModel.getColumnCount(); k++) {
		Object object = dataModel.getValueAt(j, k);
		if (object instanceof ArrayList) {
		    ArrayList data = (ArrayList) object;
		    if (heights[j] == null || data.size() > heights[j].size()) {
			heights[j] = data;
		    }
		    String longest = "";
		    for (int i = 0; i < data.size(); i++) {
			String temp = data.get(i).toString();
			if (temp.length() > longest.length()) {
			    longest = temp;
			}
		    }
		    if (widths[k] == null || longest.length() > widths_value[k]) {
			widths_value[k] = longest.length();
			widths[k] = data;
		    }
		}
	    }
	}

	// Now assign the dimensions we have determined to be the largest.
	for (int l = 0; l < heights.length; l++) {
	    if (heights[l] != null) {
		Component component = cell_renderer.getTableCellRendererComponent(this, heights[l], false, false, 0, 0);
		Dimension size = component.getPreferredSize();
		setRowHeight(l, size.height);
	    }
	}
	for (int m = 0; m < widths.length; m++) {
	    if (widths[m] != null) {
		Component component = cell_renderer.getTableCellRendererComponent(this, widths[m], false, false, 0, 0);
		Dimension size = component.getPreferredSize();
		int width = size.width + MARGIN;
		if (width > (2 * parent_frame.getSize().width) / 3) {
		    width = (2 * parent_frame.getSize().width) / 3;
		}

		Component header = header_renderer.getTableCellRendererComponent(this, dataModel.getColumnName(m), false, false, 0, 0);
		if (header.getPreferredSize().width + MARGIN > width) {
		    width = header.getPreferredSize().width + MARGIN;
		}
		columnModel.getColumn(m).setPreferredWidth(width);
	    }
	}

	wait(initial_state);
    }


    public void sortOrderChanged(TableModelSorterEvent event) {
    }

    private void wait(boolean waiting) {
	if(parent_frame != null) {
	    parent_frame.wait(waiting);
	}
    }
}
