/*
 * jNPad v0.3 - jNPad's an Simple Text Editor written in Java
 *
 * Copyright (C) 2014-2017  rgs
 *
 * Require JDK 1.6 (or later)
 *
 * 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 *
 * Info, Questions, Suggestions & Bugs Report to rgsevero@gmail.com
 */

package jnpad.ui.table;

import java.awt.Color;
import java.awt.Component;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;

import jnpad.ui.ColorUtilities;
import jnpad.ui.plaf.LAFUtils;
import jnpad.util.Utilities;

/**
 * The Class TableUtilities.
 *
 * @version 0.3
 * @since   jNPad v0.1
 */
public final class TableUtilities {
  /**
   * no instances.
   */
  private TableUtilities() {
    super();
  }

  /**
   * Sets the colors.
   *
   * @param comp JComponent
   * @param table JTable
   * @param isSelected boolean
   * @param row int
   * @param alternateRowColorEnabled boolean
   * @param alternateRowColor Color
   */
  public static void setColors(JComponent comp, JTable table, boolean isSelected, int row, boolean alternateRowColorEnabled, Color alternateRowColor) {
    if (isSelected && table.isEnabled()) {
      comp.setForeground(table.getSelectionForeground());
      comp.setBackground(table.getSelectionBackground());
    }
    else if (!table.isEnabled()) {
      comp.setForeground(LAFUtils.getTextFieldInactiveForeground());
      comp.setBackground(LAFUtils.getTextFieldInactiveBackground());
    }
    else {
      Color bg;
      Color fg;
      if (alternateRowColorEnabled && (row % 2 == 0)) {
        if (alternateRowColor != null) {
          bg = alternateRowColor;
          fg = ColorUtilities.computeForeground(bg);
        }
        else {
          Color alternateColor = UIManager.getColor("Table.alternateRowColor"); //$NON-NLS-1$
          if (alternateColor != null) {
            bg = alternateColor;
          }
          else {
            bg = table.getBackground();
            if (LAFUtils.isNimbusLAF() && bg instanceof javax.swing.plaf.UIResource) // 4Nimbus
              bg = ColorUtilities.createPureColor(bg);
          }
          fg = table.getForeground();
        }
      }
      else {
        bg = table.getBackground();
        if (LAFUtils.isNimbusLAF() && bg instanceof javax.swing.plaf.UIResource) // 4Nimbus
          bg = ColorUtilities.createPureColor(bg);
        fg = table.getForeground();
      }
      comp.setForeground(fg);
      comp.setBackground(bg);
    }
  }

  /**
   * Sets the border.
   *
   * @param comp JComponent
   * @param table JTable
   * @param isSelected boolean
   * @param hasFocus boolean
   * @param row int
   * @param column int
   * @param noFocusBorder Border
   */
  public static void setBorder(JComponent comp, JTable table, boolean isSelected, boolean hasFocus, int row, int column, Border noFocusBorder) {
    if (hasFocus) {
      Border border = null;
      if (isSelected) {
        border = UIManager.getBorder("Table.focusSelectedCellHighlightBorder"); //$NON-NLS-1$
      }
      if (border == null) {
        border = LAFUtils.getTableFocusCellHighlightBorder();
      }
      comp.setBorder(border);
      if (!isSelected && table.isCellEditable(row, column)) {
        comp.setForeground(LAFUtils.getTableFocusCellForeground());
        comp.setBackground(LAFUtils.getTableFocusCellBackground());
      }
    }
    else {
      comp.setBorder(noFocusBorder);
    }
  }

  /**
   * Sets the value.
   *
   * @param label JLabel
   * @param value Object
   * @param tooltipEnabled boolean
   */
  public static void setValue(JLabel label, Object value, boolean tooltipEnabled) {
    if (!tooltipEnabled) {
      label.setText(Utilities.toString(value));
      return;
    }

    if (value != null) {
      String s = value.toString();
      if (s.length() > 0) {
        label.setText(s);
        label.setToolTipText(s);
      }
      else {
        label.setText(Utilities.EMPTY_STRING);
        label.setToolTipText(null);
      }
    }
    else {
      label.setText(Utilities.EMPTY_STRING);
      label.setToolTipText(null);
    }
  }

  /**
   * Pack table columns.
   *
   * @param table JTable
   * @param margin int
   */
  public static void packTableColumns(JTable table, int margin) {
    for (int c = 0; c < table.getColumnCount(); c++)
      packTableColumn(table, c, margin);
  }

  /**
   * Sets the preferred width of the visible column specified by vColIndex. The column
   * will be just wide enough to show the column head and the widest cell in the column.
   * margin pixels are added to the left and right
   * (resulting in an additional width of 2*margin pixels).
   *
   * @param table JTable
   * @param colIndex int
   * @param margin int
   */
  public static void packTableColumn(JTable table, int colIndex, int margin) {
    DefaultTableColumnModel colModel = (DefaultTableColumnModel) table.getColumnModel();
    TableColumn col = colModel.getColumn(colIndex);
    int width;

    // Get width of column header
    TableCellRenderer renderer = col.getHeaderRenderer();
    if (renderer == null) {
      renderer = table.getTableHeader().getDefaultRenderer();
    }
    Component comp = renderer.getTableCellRendererComponent(table, col.getHeaderValue(), false, false, 0, 0);
    width = comp.getPreferredSize().width;

    // Get maximum width of column data
    for (int r = 0; r < table.getRowCount(); r++) {
      renderer = table.getCellRenderer(r, colIndex);
      comp = renderer.getTableCellRendererComponent(table, table.getValueAt(r, colIndex), false, false, r, colIndex);
      width = Math.max(width, comp.getPreferredSize().width);
    }

    // Add margin
    width += 2 * margin;

    // Set the width
    col.setPreferredWidth(width);
  }

  /**
   * The height of each row is set to the preferred height of the tallest cell
   * in that row.
   *
   * @param table JTable
   * @param margin int
   */
  public static void packTableRows(JTable table, int margin) {
    for (int r = 0; r < table.getRowCount(); r++) {
      // Get the preferred height
      int h = getTablePreferredRowHeight(table, r, margin);

      // Now set the row height using the preferred height
      if (table.getRowHeight(r) != h) {
        table.setRowHeight(r, h);
      }
    }
  }

  /**
   * Returns the preferred height of a row. The result is equal to the tallest
   * cell in the row.
   *
   * @param table JTable
   * @param rowIndex int
   * @param margin int
   * @return int
   */
  public static int getTablePreferredRowHeight(JTable table, int rowIndex, int margin) {
    // Get the current default height for all rows
    int height = table.getRowHeight();

    // Determine highest cell in the row
    for (int c = 0; c < table.getColumnCount(); c++) {
      TableCellRenderer renderer = table.getCellRenderer(rowIndex, c);
      Component comp = table.prepareRenderer(renderer, rowIndex, c);
      int h = comp.getPreferredSize().height + 2 * margin;
      height = Math.max(height, h);
    }
    return height;
  }

  /**
   * Free.
   *
   * @param table JTable
   */
  public static void free(JTable table) {
    TableModel tm = table.getModel();
    if (tm != null) {
      table.setModel(new EmptyTableModel());
    }
  }

  //////////////////////////////////////////////////////////////////////////////
  /**
   * The Class EmptyTableModel.
   */
  static class EmptyTableModel implements TableModel {
    /**
     * Gets the row count.
     *
     * @return the row count
     * @see javax.swing.table.TableModel#getRowCount()
     */
    @Override
    public int getRowCount() {return 0;}
    
    /**
     * Gets the column count.
     *
     * @return the column count
     * @see javax.swing.table.TableModel#getColumnCount()
     */
    @Override
    public int getColumnCount() {return 0;}
    
    /**
     * Gets the column name.
     *
     * @param columnIndex the column index
     * @return the column name
     * @see javax.swing.table.TableModel#getColumnName(int)
     */
    @Override
    public String getColumnName(int columnIndex) {return Utilities.EMPTY_STRING;}
    
    /**
     * Gets the column class.
     *
     * @param columnIndex the column index
     * @return the column class
     * @see javax.swing.table.TableModel#getColumnClass(int)
     */
    @Override
    public Class<?> getColumnClass(int columnIndex) {return String.class;}
    
    /**
     * Checks if is cell editable.
     *
     * @param rowIndex the row index
     * @param columnIndex the column index
     * @return true, if is cell editable
     * @see javax.swing.table.TableModel#isCellEditable(int, int)
     */
    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {return false; }
    
    /**
     * Gets the value at.
     *
     * @param rowIndex the row index
     * @param columnIndex the column index
     * @return the value at
     * @see javax.swing.table.TableModel#getValueAt(int, int)
     */
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {return Utilities.EMPTY_STRING;}
    
    /**
     * Sets the value at.
     *
     * @param aValue the a value
     * @param rowIndex the row index
     * @param columnIndex the column index
     * @see javax.swing.table.TableModel#setValueAt(java.lang.Object, int, int)
     */
    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {/*empty*/}
    
    /**
     * Adds the table model listener.
     *
     * @param l the l
     * @see javax.swing.table.TableModel#addTableModelListener(javax.swing.event.TableModelListener)
     */
    @Override
    public void addTableModelListener(TableModelListener l) {/*empty*/}
    
    /**
     * Removes the table model listener.
     *
     * @param l the l
     * @see javax.swing.table.TableModel#removeTableModelListener(javax.swing.event.TableModelListener)
     */
    @Override
    public void removeTableModelListener(TableModelListener l) {/*empty*/}
  }
  //////////////////////////////////////////////////////////////////////////////

}
