/**
 *############################################################################
 * A component of the Greenstone Librarian Interface, part of the Greenstone
 * digital library suite from the New Zealand Digital Library Project at the
 * University of Waikato, New Zealand.
 *
 * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
 *
 * Copyright (C) 2004 New Zealand Digital Library Project
 *
 * 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; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *############################################################################
 */

package org.greenstone.gatherer.metadata;


import java.awt.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
import org.greenstone.gatherer.Configuration;
import org.greenstone.gatherer.Dictionary;
import org.greenstone.gatherer.collection.CollectionTreeNode;


public class MetadataAuditTableModel
    extends AbstractTableModel
{
    /** It is not expected that this class will ever be serialized */
    private static final long serialVersionUID = 0L;

    /** The CollectionTreeNodes this model is built for */
    private CollectionTreeNode[] file_nodes = null;
    /** The list of MetadataElements in the table (columns) */
    private ArrayList metadata_elements = new ArrayList();
    /** The list of MetadataAuditTableEntries in the table (rows) */
    private ArrayList metadata_audit_table_entries = new ArrayList();


    /** Returns the number of columns in this table. */
    public int getColumnCount()
    {
	return 1 + metadata_elements.size();
    }


    /** Returns the name of the specified column. */
    public String getColumnName(int col)
    {
	// First column: filename
	if (col == 0) {
	    return Dictionary.get("AuditTable.File");
	}

	int metadata_element_index = col - 1;
	return metadata_elements.get(metadata_element_index).toString();
    }


    /** Returns the values in a particular column. */
    public ArrayList getColumnValues(int col)
    {
	// First column: filename
	if (col == 0) {
	    ArrayList column_values = new ArrayList();
	    for (int i = 0; i < metadata_audit_table_entries.size(); i++) {
		MetadataAuditTableEntry metadata_audit_table_entry = (MetadataAuditTableEntry) metadata_audit_table_entries.get(i);
		column_values.add(metadata_audit_table_entry.getFilename());
	    }

	    return column_values;
	}

	// Check values are reasonable
	int metadata_element_index = col - 1;
	if (metadata_element_index < 0 || metadata_element_index >= metadata_elements.size()) {
	    return null;
	}

	ArrayList column_values = new ArrayList();
	for (int i = 0; i < metadata_audit_table_entries.size(); i++) {
	    MetadataAuditTableEntry metadata_audit_table_entry = (MetadataAuditTableEntry) metadata_audit_table_entries.get(i);
	    MetadataValueTreeNode[] metadata_value_tree_nodes = metadata_audit_table_entry.getMetadataValueTreeNodes(metadata_element_index);
	    if (metadata_value_tree_nodes != null) {
		for (int j = 0; j < metadata_value_tree_nodes.length; j++) {
		    column_values.add(metadata_value_tree_nodes[j].toString());
		}
	    }
	}

	return column_values;
    }


    /** Returns the number of rows in this table. */
    public int getRowCount()
    {
	return metadata_audit_table_entries.size();
    }


    /** Returns the cell value at a given row and column as an Object. */
    public Object getValueAt(int row, int col)
    {
	// Check values are reasonable
	if (row < 0 || row >= metadata_audit_table_entries.size()) {
	    return null;
	}

	// First column: filename
	if (col == 0) {
	    ArrayList cell_values = new ArrayList();
	    cell_values.add(((MetadataAuditTableEntry) metadata_audit_table_entries.get(row)).getFilename());
	    return cell_values;
	}

	// Check values are reasonable
	int metadata_element_index = col - 1;
	if (metadata_element_index < 0 || metadata_element_index >= metadata_elements.size()) {
	    return null;
	}

	ArrayList cell_values = new ArrayList();
	MetadataAuditTableEntry metadata_audit_table_entry = (MetadataAuditTableEntry) metadata_audit_table_entries.get(row);
	MetadataValueTreeNode[] metadata_value_tree_nodes = metadata_audit_table_entry.getMetadataValueTreeNodes(metadata_element_index);
	if (metadata_value_tree_nodes != null) {
	    for (int j = 0; j < metadata_value_tree_nodes.length; j++) {
		cell_values.add(metadata_value_tree_nodes[j].toString());
	    }
	}

	return cell_values;
    }


    public void rebuild(CollectionTreeNode[] file_nodes)
    {
	metadata_elements = MetadataSetManager.getEveryMetadataSetElement();
	metadata_audit_table_entries.clear();

	this.file_nodes = file_nodes;
	if (file_nodes != null && file_nodes.length > 0) {
	    // Create model builder
	    MetadataAuditTableModelBuilder builder = new MetadataAuditTableModelBuilder();
	    builder.run();
	}
    }


    private class MetadataAuditTableModelBuilder
    {
	// Build a list of MetadataAuditTableEntries that represent the metadata asssigned to the selected files
	public void run()
	{
	    // Process each of the selected files in turn
	    for (int i = 0; i < file_nodes.length; i++) {
		File current_file = file_nodes[i].getFile();

		// Get the metadata assigned to this file
		ArrayList current_file_metadata = MetadataXMLFileManager.getMetadataAssignedToFile(current_file);

		// Get the extracted metadata for this file, if desired
		if (Configuration.get("general.view_extracted_metadata", Configuration.COLLECTION_SPECIFIC) == true) {
		    current_file_metadata.addAll(DocXMLFileManager.getMetadataExtractedFromFile(current_file));
		}

		MetadataAuditTableEntry metadata_audit_table_entry = new MetadataAuditTableEntry(current_file, current_file_metadata);
		metadata_audit_table_entries.add(metadata_audit_table_entry);
	    }
	}
    }


    /** This class represents one (file, metadata) pair */
    private class MetadataAuditTableEntry
    {
	private File file = null;
	private ArrayList[] metadata_values = null;


	public MetadataAuditTableEntry(File file, ArrayList metadata_values_list)
	{
	    this.file = file;

	    metadata_values = new ArrayList[metadata_elements.size()];
	    for (int i = 0; i < metadata_values.length; i++) {
		metadata_values[i] = new ArrayList();
	    }

	    for (int i = 0; i < metadata_values_list.size(); i++) {
		MetadataValue metadata_value = (MetadataValue) metadata_values_list.get(i);
		MetadataElement metadata_element = metadata_value.getMetadataElement();

		// Find the right column to put the value in
		for (int j = 0; j < metadata_elements.size(); j++) {
		    if (metadata_element.equals(metadata_elements.get(j))) {
			metadata_values[j].add(metadata_value);
			break;
		    }
		}
	    }
	}


	public String getFilename()
	{
	    return file.getName();
	}


 	public MetadataValueTreeNode[] getMetadataValueTreeNodes(int metadata_element_index)
 	{
	    ArrayList metadata_values_list = metadata_values[metadata_element_index];
 	    if (metadata_values_list == null) {
 		return null;
 	    }

	    MetadataValueTreeNode[] metadata_value_tree_nodes = new MetadataValueTreeNode[metadata_values_list.size()];
	    for (int i = 0; i < metadata_values_list.size(); i++) {
		metadata_value_tree_nodes[i] = ((MetadataValue) metadata_values_list.get(i)).getMetadataValueTreeNode();
	    }

 	    return metadata_value_tree_nodes;
 	}
    }
}
