/*
 * File:     TierTableModel.java
 * Project:  MPI Linguistic Application
 * Date:     03 April 2006
 *
 * Copyright (C) 2001-2006  Max Planck Institute for Psycholinguistics
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package mpi.eudico.client.annotator.tier;

import mpi.eudico.client.annotator.ElanLocale;

import mpi.eudico.server.corpora.clomimpl.abstr.TierImpl;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import javax.swing.table.AbstractTableModel;


/**
 * A table model for tier objects.
 *
 * @author Han Sloetjes
 * @version 1.0
  */
public class TierTableModel extends AbstractTableModel {
    /** table column and label identifiers */
    public static final String LABEL_PREF = "EditTierDialog.Label.";

    /** name column */
    public static final String NAME = "TierName";

    /** parent column */
    public static final String PARENT = "Parent";

    /** participant */
    public static final String PARTICIPANT = "Participant";

    /** linguistic type column */
    public static final String TYPE = "LinguisticType";

    /** language */
    public static final String LANGUAGE = "Language";

    /** empty or not applicable value */
    public static final String N_A = "-";
    private ArrayList tierList;
    private List columnIds;
    private List tableData;
    private List classes;

    /**
     * No-arg constructor
     */
    public TierTableModel() {
        this(null);
    }

    /**
     * Constructor.
     *
     * @param tiers a vector containing tier objects
     */
    public TierTableModel(Vector tiers) {
        this(tiers, null);
    }

    /**
     * Constructor.
     *
     * @param tiers a vector containing tier objects
     * @param columns an array of column names that should be visible in the
     *        table
     */
    public TierTableModel(Vector tiers, String[] columns) {
        if (tiers == null) {
            tierList = new ArrayList(0);
        } else {
            tierList = new ArrayList(tiers);
        }

        columnIds = new ArrayList();
        classes = new ArrayList();

        if (columns != null) {
            for (int i = 0; i < columns.length; i++) {
                if (columns[i].equals(NAME)) {
                    columnIds.add(NAME);
                    classes.add(String.class);
                } else if (columns[i].equals(PARENT)) {
                    columnIds.add(PARENT);
                    classes.add(String.class);
                } else if (columns[i].equals(TYPE)) {
                    columnIds.add(TYPE);
                    classes.add(String.class);
                } else if (columns[i].equals(PARTICIPANT)) {
                    columnIds.add(PARTICIPANT);
                    classes.add(String.class);
                } else if (columns[i].equals(LANGUAGE)) {
                    columnIds.add(LANGUAGE);
                    classes.add(String.class);
                }
            }
        } else {
            columnIds.add(NAME);
            columnIds.add(PARENT);
            columnIds.add(TYPE);
            columnIds.add(PARTICIPANT);
            columnIds.add(LANGUAGE);
            classes.add(String.class);
            classes.add(String.class);
            classes.add(String.class);
            classes.add(String.class);
            classes.add(String.class);
        }

        initData();
    }

    private void initData() {
        tableData = new ArrayList(tierList.size());

        TierImpl tier;

        for (int i = 0; i < tierList.size(); i++) {
            tier = (TierImpl) tierList.get(i);
            addRowData(tier);
        }

        fireTableDataChanged();
    }

    private void addRowData(TierImpl tier) {
        if (tier == null) {
            return;
        }

        ArrayList rowData = new ArrayList(5);

        int index = columnIds.indexOf(NAME);

        if (index > -1) {
            rowData.add(index, tier.getName());
        }

        index = columnIds.indexOf(PARENT);

        if (index > -1) {
            if (tier.getParentTier() == null) {
                rowData.add(index, N_A);
            } else {
                rowData.add(index, tier.getParentTier().getName());
            }
        }

        index = columnIds.indexOf(TYPE);

        if (index > -1) {
            rowData.add(index, tier.getLinguisticType().getLinguisticTypeName());
        }

        index = columnIds.indexOf(PARTICIPANT);

        if (index > -1) {
            rowData.add(index, tier.getParticipant());
        }

        index = columnIds.indexOf(LANGUAGE);

        if (index > -1) {
            rowData.add(index, tier.getDefaultLocale().getDisplayName());
        }

        tableData.add(rowData);
    }

    /**
     * The number of rows = size of table data list
     *
     * @see javax.swing.table.TableModel#getRowCount()
     */
    public int getRowCount() {
        return tableData.size();
    }

    /**
     * the number of columns = the size of column ids list
     *
     * @see javax.swing.table.TableModel#getColumnCount()
     */
    public int getColumnCount() {
        return columnIds.size();
    }

    /**
     * Finds the ArrayList of the specified row and returns the value at the
     * column index.
     *
     * @see javax.swing.table.TableModel#getValueAt(int, int)
     */
    public Object getValueAt(int rowIndex, int columnIndex) {
        if ((rowIndex < 0) || (rowIndex >= tableData.size()) ||
                (columnIndex < 0) || (columnIndex >= columnIds.size())) {
            return null;
        }

        ArrayList row = (ArrayList) tableData.get(rowIndex);

        return row.get(columnIndex);
    }

    /**
     * Returns false regardless of parameter values. The values are not  to be
     * edited directly in the table.
     *
     * @param row the row
     * @param column the column
     *
     * @return false
     */
    public boolean isCellEditable(int row, int column) {
        return false;
    }

    /**
     * Finds the column index for the specified identifier.
     *
     * @param columnName the name/identifier of the column
     *
     * @return the index, or -1 if not found
     */
    public int findColumn(String columnName) {
        return columnIds.indexOf(columnName);
    }

    /**
     * Returns the class of the data in the specified column. Note: returns
     * null instead of throwing an ArrayIndexOutOfBoundsException
     *
     * @param columnIndex the column
     *
     * @return the <code>class</code> of the objects in column
     *         <code>columnIndex</code>
     */
    public Class getColumnClass(int columnIndex) {
        if ((columnIndex < 0) || (columnIndex >= classes.size())) {
            return null;
        }

        return (Class) classes.get(columnIndex);
    }

    /**
     * Returns the identifier of the column. Note: returns empty String when
     * the column cannot be found
     *
     * @param columnIndex the column
     *
     * @return the id of the column or empty stringl
     */
    public String getColumnName(int columnIndex) {
        if ((columnIndex < 0) || (columnIndex >= columnIds.size())) {
            return "";
        }

        //return (String) columnIds.get(columnIndex);
        return ElanLocale.getString(LABEL_PREF +
            (String) columnIds.get(columnIndex));
    }

    /**
     * Note: silently returns instead of throwing an
     * ArrayIndexOutOfBoundsException
     *
     * @param rowIndex the row to remove
     */
    public void removeRow(int rowIndex) {
        if ((rowIndex >= 0) && (rowIndex < tableData.size())) {
            tableData.remove(rowIndex);
            tierList.remove(rowIndex);
            fireTableDataChanged();
        }
    }

    /**
     * Removes all rows from the table.
     */
    public void removeAllRows() {
        tableData.clear();
        tierList.clear();
        fireTableDataChanged();
    }

    /**
     * Adds a row with the data from the tier.
     *
     * @param tier the tier to add to the model
     */
    public void addRow(TierImpl tier) {
        if ((tier == null) || tierList.contains(tier)) {
            return;
        }

        tierList.add(tier);
        addRowData(tier);
        fireTableDataChanged();
    }

    /**
     * Adds a row with the data from the tier
     *
     * @param tier the tier to add to the model
     */
    public void addTier(TierImpl tier) {
        addRow(tier);
    }

    /**
     * Notification that the data in some Tier has been changed so
     * the row value list should be updated.
     */
    public void rowDataChanged() {
        initData();
        fireTableDataChanged();
    }
}
