/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2005/10/04, 13:19
!  AUTHOR(S): KOGA, Junichiro
!  File : TableModelForInputInterface.java
!  
!  Contact address :  Phase System Consortium
!                     E-mail: phase_system@nims.go.jp URL https://azuma.nims.go.jp
!
!
!   Since 2002, this program set had been intensively developed as a part of the following 
!  national projects supported by the Ministry of Education, Culture, Sports, Science and
!  Technology (MEXT) of Japan; "Frontier Simulation Software for Industrial Science
!  (FSIS)" from 2002 to 2005, "Revolutionary Simulation Software (RSS21)" from 2006 to
!  2008. "Research and Development of Innovative Simulation Software (RISS)" from 2008
!  to 2013. These projects is lead by the Center for Research on Innovative Simulation 
!  Software (CISS), the Institute of Industrial Science (IIS), the University of Tokyo.
!   Since 2013, this program set has been further developed centering on PHASE System
!  Consortium. 
!   The activity of development of this program set has been supervised by Takahisa Ohno.
!
!=======================================================================
 */

package ciss.phase_viewer.primitiveguis.tableforinputinterface;

import java.util.EventListener;
import java.util.Vector;

import javax.swing.JTable;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;

import org.apache.log4j.Logger;

import ciss.phase_viewer.atomcoord.AtomCoords;
import ciss.phase_viewer.common.Command;
import ciss.phase_viewer.inputinterface.InputInterface;
import ciss.phase_viewer.inputinterface.InputInterfaceEntryChangeListener;
import ciss.phase_viewer.inputinterface.inputinterfacetable.InputInterfaceTableColumns;
import ciss.phase_viewer.inputinterface.inputinterfacetable.InputInterfaceTableSpec;
import ciss.phase_viewer.inputinterface.inputinterfacetable.InputInterfaceTableSpecManager;

/**
 * InputInterfaceオブジェクトと相互作用するテーブルモデルのベースクラス.
 * 
 * @author
 */
abstract public class TableModelForInputInterface extends DefaultTableModel
        implements Command, InputInterfaceEntryChangeListener {
    private Logger logger = Logger.getLogger(TableModelForInputInterface.class
            .getName());

    protected String[] inputSpecifications;
    protected InputInterface input;
    protected Vector tableData = new Vector();
    protected String[] idents;

    protected InputInterfaceTableSpecManager manager;
    protected InputInterfaceTableColumns[] columns;
    protected InputInterfaceTableSpec spec;

    protected int[] mapSpecCol;
    protected EventListener el;

    protected boolean updateInputInterface = true;
    private JTable parentTable;

    private int columnIndex;

    private boolean batchUpdate = false;

    public TableModelForInputInterface(String[] inputSpecifications,
            InputInterface input, int[] mapSpecCol, EventListener el) {
        super();
        this.inputSpecifications = inputSpecifications;
        this.input = input;
        this.input.addInputInterfaceEntryChangeListener(this);
        this.el = el;
        this.mapSpecCol = mapSpecCol;
        this.manager = input.getInputInterfaceTableSpecManager();
        this.columnIndex = 0;
    }

    public TableModelForInputInterface(String[] inputSpecifications,
            InputInterface input, int[] mapSpecCol, EventListener el,
            int columnIndex) {
        super();
        this.inputSpecifications = inputSpecifications;
        this.input = input;
        this.input.addInputInterfaceEntryChangeListener(this);
        this.el = el;
        this.mapSpecCol = mapSpecCol;
        this.manager = input.getInputInterfaceTableSpecManager();
        this.columnIndex = columnIndex;
    }

    public TableModelForInputInterface(String[] inputSpecifications,
            InputInterfaceTableSpecManager manager, int[] mapSpecCol,
            EventListener el) {
        super();
        this.inputSpecifications = inputSpecifications;
        this.el = el;
        this.mapSpecCol = mapSpecCol;
        this.manager = manager;
        this.spec = manager.getTableSpec(inputSpecifications[0]);
        this.columns = spec.getTableColumns();
    }

    protected void init() {
        if (manager != null && inputSpecifications != null) {
            spec = manager.getTableSpec(inputSpecifications[0], columnIndex);
            columns = spec.getTableColumns();
            createTableColumns();
        }

        super.addTableModelListener((TableModelListener) el);

        if (input != null && inputSpecifications != null) {
            extractInputFile();
        }

    }

    public TableModelForInputInterface(int rowCount, int columnCount) {
        super(rowCount, columnCount);
    }

    public TableModelForInputInterface(Object[][] data, Object[] columnNames) {
        super(data, columnNames);
    }

    public TableModelForInputInterface(Object[] columnNames, int rowCount) {
        super(columnNames, rowCount);
    }

    public TableModelForInputInterface(Vector columnNames, int rowCount) {
        super(columnNames, rowCount);
    }

    public TableModelForInputInterface(Vector data, Vector columnNames) {
        super(data, columnNames);
    }

    public static TableModelForInputInterface getInstance(
            String[] inputSpecifications, InputInterface input,
            int[] mapSpecCol, EventListener el, boolean non_tabular) {
        if (!non_tabular) {
            return new TableModelForTabularData(inputSpecifications, input,
                    mapSpecCol, el);
        } else {
            return new TableModelForNonTabularData(inputSpecifications, input,
                    mapSpecCol, el);
        }
    }

    public static TableModelForInputInterface getInstance(
            String[] inputSpecifications, InputInterface input,
            int[] mapSpecCol, EventListener el, boolean non_tabular,
            int columnIndex) {
        if (!non_tabular) {
            return new TableModelForTabularData(inputSpecifications, input,
                    mapSpecCol, el, columnIndex);
        } else {
            return new TableModelForNonTabularData(inputSpecifications, input,
                    mapSpecCol, el, columnIndex);
        }
    }

    public static TableModelForInputInterface getInstance(AtomCoords coords,
            String[] inputSpecifications,
            InputInterfaceTableSpecManager manager, int[] mapSpecCol,
            EventListener el, JTable table) {
        return new TableModelForAtomCoords(coords, inputSpecifications,
                manager, mapSpecCol, el, table);
    }

    protected void restoreListeners(TableModelListener[] listeners) {
        for (int i = 0; i < listeners.length; i++) {
            this.addTableModelListener(listeners[i]);
        }
    }

    protected void setParentTable(JTable table) {
        this.parentTable = table;
    }

    protected JTable getParentTable() {
        return this.parentTable;
    }

    protected void batchUpdate(boolean batchUpdate) {
        this.batchUpdate = batchUpdate;
        fireTableDataChanged();
    }

    public boolean batchUpdate() {
        return batchUpdate;
    }

    protected abstract void createTableColumns();

    protected abstract void extractInputFile();

    protected abstract void setInputToModel();

    public void inputInterfaceInitialized() {

    }

    protected boolean callListener = true;

    /**
     * InputInterfaceEntryChangeListenerにInputInterfaceEntryChangeEventを呼ぶべきかどうかを通知すべきか否かをセット
     * . たとえば, 原子配置を一気にインポートする時などはいちいち通知するのは明らかに無駄なのでこれにfalseをセットしておく.
     * 
     * @param callListener
     *            trueの時通知される
     */
    public void notifyInputInterfaceChangeListeners(boolean callListener) {
        this.callListener = callListener;
        // if ( this.callListener ) {
        // fireTableDataChanged();
        // }
    }

}
