/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2005/09/08, 15:23
!  AUTHOR(S): KOGA, Junichiro
!  File : InputInterfaceTableSpec.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.inputinterface.inputinterfacetable;

import java.io.Serializable;
import java.util.List;
import java.util.Vector;

import org.apache.log4j.Logger;
import org.jdom.Element;

/**
 * InputInterfaceTableをいかに生成すべきか, という情報を持つクラス.
 * 
 * @author KOGA, Junichiro
 */
public class InputInterfaceTableSpec implements Serializable {
    private static Logger logger = Logger
            .getLogger(InputInterfaceTableSpec.class.getName());
    private String ID;

    private InputInterfaceTableColumns[] columns;
    private int num_rows = -1;
    private boolean undo_each_column = true;

    private InputInterfaceTableSpecManager parent;

    private boolean non_tabular = false;
    private boolean row_oriented = false;
    private String[] non_tabular_cols;
    private String cell_editor;

    /**
     * Creates a new instance of InputInterfaceTableSpec
     * 
     * @param element
     *            the Element object from which the InputInterfaceTableSpec
     *            object is created.
     * @param parent
     *            the InputInterfaceTableSpecManager to which this class
     *            belongs.
     */
    protected InputInterfaceTableSpec(Element element,
            InputInterfaceTableSpecManager parent) {
        this.ID = element.getName();
        this.parent = parent;
        num_rows = parseGetNumRows(element);
        undo_each_column = parseUndoEachColumns(element);
        non_tabular = parseNonTabular(element);
        if (non_tabular) {
            parseNonTabularBlock(element);
        }
        parseRightClickItems(element);

        createTableColumns(element);
    }

    /**
     * returns the number of rows this table has. if that value depends on the
     * input file, than this method will return -1.
     * 
     * @return the number of rows this table should have.
     */
    public int getNumRows() {
        return this.num_rows;
    }

    /**
     * returns whether to operate on each column when performing undo/redo
     * operations.
     * 
     * @return true if undo/redo operations should be performed for each column.
     */
    public boolean undoEachColumns() {
        return this.undo_each_column;
    }

    /**
     * returns the InputInterfaceTableSpecManager object to which this class is
     * associated.
     * 
     * @return InputInterfaceTableSpecManager object associated with this clas.
     */
    public InputInterfaceTableSpecManager getInputInterfaceTableSpecManager() {
        return this.parent;
    }

    /**
     * returns the ID of this object.
     * 
     * @return ID for this object (example: structure.atom_list.atoms)
     */
    public String getID() {
        return this.ID;
    }

    /**
     * returns an array of the InputInterfaceTableColumns object encapsulated in
     * this class.
     * 
     * @return an array of InputInterfaceTableColumns object.
     */
    public InputInterfaceTableColumns[] getTableColumns() {
        return columns;
    }

    /**
     * returns an InputInterfaceTableColumns object specified by its name.
     * 
     * @param name
     *            the name of the desired InputInterfaceTableColumns object.
     * @return the desired InputInterfaceTableColumns object.
     */
    public InputInterfaceTableColumns getTableColumn(String name) {
        if (columns == null) {
            return null;
        }

        for (int i = 0; i < columns.length; i++) {
            if (columns[i].getName().equalsIgnoreCase(name)) {
                return columns[i];
            }
        }
        return null;
    }

    /**
     * specifies whether this "table specification" is inteded for non-tabular
     * data
     * 
     * @return true if such is the case.
     */
    public boolean nonTabular() {
        return non_tabular;
    }

    /**
     * specifies whether the table is "row-oriented".
     * 
     * @return true if such is the case.
     */
    public boolean isRowOriented() {
        return row_oriented;
    }

    /**
     * retrieves column names when row_oriented == true.
     * 
     * @return column names. returns null if row_oriented is false.
     */
    public String[] getColumnNamesForNonTabularData() {
        return non_tabular_cols;
    }

    /**
     * get an array of "RightClickItems", which specifies the behavior of the
     * pop-up menu on right-click of the table.
     * 
     * @return an array of RightClickItems (may return null)
     */
    public RightClickItems[] getRightClickItems() {
        return ritems;
    }

    private int parseGetNumRows(Element element) {
        String srow = element.getChildTextTrim("num_rows");
        if (srow == null || srow.length() == 0) {
            return -1;
        }

        int ret = -1;
        try {
            ret = Integer.parseInt(srow);
        } catch (NumberFormatException nfe) {
            return -1;
        }
        return ret;
    }

    private RightClickItems[] ritems;

    private boolean parseRightClickItems(Element element) {
        Element rightclick = element.getChild("right_click_items");
        if (rightclick == null) {
            return false;
        }

        List list = rightclick.getChildren("item");
        if (list == null || list.size() == 0) {
            return false;
        }

        Vector rightclickitems = new Vector();
        for (int i = 0; i < list.size(); i++) {
            Element item = (Element) list.get(i);
            String name = item.getChildTextTrim("name");
            String text = item.getChildTextTrim("text");
            String tool = item.getChildTextTrim("tooltiptext");
            RightClickItems items = new RightClickItems(name, text, tool);
            logger.debug(items);
            rightclickitems.addElement(items);
        }

        if (rightclickitems.size() == 0) {
            return false;
        }

        ritems = new RightClickItems[rightclickitems.size()];
        rightclickitems.copyInto(ritems);
        return true;
    }

    private boolean parseUndoEachColumns(Element element) {
        String eachcol = element.getChildTextTrim("undo_each_column");
        if (eachcol == null || eachcol.length() == 0) {
            // the default value is true...
            return true;
        }
        return new Boolean(eachcol).booleanValue();
    }

    private boolean parseNonTabular(Element element) {
        Element nontabular = element.getChild("non_tabular_data");
        return nontabular != null;
    }

    private void parseNonTabularBlock(Element element) {
        Element nontabular = element.getChild("non_tabular_data");
        String srow_oriented = nontabular.getChildTextTrim("row_oriented");
        row_oriented = srow_oriented != null
                && new Boolean(srow_oriented).booleanValue();

        String scols = nontabular.getChildTextTrim("columns");
        if (scols != null) {
            non_tabular_cols = scols.split(",");
        }
        Element celleditor = nontabular.getChild("cell_editor");
        cell_editor = celleditor.getChildTextTrim("type");
    }

    private void createTableColumns(Element element) {
        List column = element.getChildren("column");
        if (column == null) {
            return;
        }

        columns = new InputInterfaceTableColumns[column.size()];
        for (int i = 0; i < column.size(); i++) {
            columns[i] = new InputInterfaceTableColumns(
                    (Element) column.get(i), this);
            if (cell_editor != null && cell_editor.trim().length() != 0) {
                columns[i].setCellEditor(cell_editor);
            }
        }
    }

}
