/*
 * This file is part of the Poliqarp suite.
 * 
 * Copyright (C) 2004-2009 by Instytut Podstaw Informatyki Polskiej
 * Akademii Nauk (IPI PAN; Institute of Computer Science, Polish
 * Academy of Sciences; cf. www.ipipan.waw.pl).  All rights reserved.
 * 
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file gpl.txt included in the packaging
 * of this file.  (See http://www.gnu.org/licenses/translations.html for
 * unofficial translations.)
 * 
 * A commercial license is available from IPI PAN (contact
 * Michal.Ciesiolka@ipipan.waw.pl or ipi@ipipan.waw.pl for more
 * information).  Licensees holding a valid commercial license from IPI
 * PAN may use this file in accordance with that license.
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

package ipipan.poliqarp.gui;

import java.awt.Color;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;

import ipipan.poliqarp.logic.MatchList;

/**
 * A table holding the query results.
 */
public class ResultTable extends JTable implements MultilingualEntity,
   ResultEventListener, TableModelListener
{
   private ResultModel model;
   private MultiColorCellRenderer mcRenderer, lsRenderer;
   private TableCellSizeAdjustor tcsa;
   private boolean contentChanging;
   private Application app;

   /**
    * Constructs a new, empty <code>ResultTable</code>.
    */
   public ResultTable(Application app)
   {
      this.app = app;
      model = new ResultModel(app);
      setModel(model);
      tcsa = TableCellSizeAdjustor.adjustorForTable(this, 
         TableCellSizeAdjustor.ADJUST_WIDTH);
      ToolTipManager.sharedInstance().unregisterComponent(this);
      ToolTipManager.sharedInstance().unregisterComponent(getTableHeader());
      Color[] colors = { new Color(192,255,192), new Color(255,255,255) };
      mcRenderer = new MultiColorCellRenderer(colors);
      lsRenderer = new LeftSideCellRenderer(colors); 
      lsRenderer.setHorizontalAlignment(LeftSideCellRenderer.RIGHT);
      setCellSelectionEnabled(false);
      setRowSelectionAllowed(true);
      setColumnSelectionAllowed(false);
      setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
      model.addResultEventListener(this);
/*    FIXME
      model.addTableModelListener(new TableModelListener() {
         public void tableChanged(TableModelEvent e)
         {
            ListSelectionModel lsm = getSelectionModel();
            int index = lsm.getMinSelectionIndex();
            if (index == -1 && model != null && model.getRowCount() > 0) 
               lsm.setSelectionInterval(0, 0);
         }
      });
*/
      setContentChangingEnabled(true);
   }

   public void setContentChangingEnabled(boolean contentChanging)
   {
      this.contentChanging = contentChanging;
   }

   /**
    * Creates and adds a selection listener that updates contents
    * of a context area and metadata table as needed 
    * to this table's selection model.
    */
   public void addContextSelectionListener(ContextArea anArea,
      MetaDataTable aTable)
   {
      final ContextArea area = anArea;
      final MetaDataTable table = aTable;
      final ResultModel m = model;
      getSelectionModel().addListSelectionListener(
         new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent lse)
            {
               ListSelectionModel lsm = (ListSelectionModel)lse.getSource();
               int index = lsm.getMinSelectionIndex();
               if (index != -1) {
                  StringBuilder s = new StringBuilder();
                  for (int i = 0; i < m.getColumnCount(); i++)
                     s.append(m.getValueAt(index, i));
                  StringSelection sel = new StringSelection(s.toString());
                  Toolkit.getDefaultToolkit().getSystemClipboard().
                     setContents(sel, sel);
               }                    
               if (!contentChanging) 
                  return;
               if (index == -1) {
                  area.wipe();
                  table.getModel().setSource(app.getCorpus(), null);
               } else 
                  model.setAreaContent(area, table, index);
            }
         });
   }

   private void updateRenderer()
   {
      TableColumnModel cm = getColumnModel();
      int columnCount = cm.getColumnCount();

      for (int j = 0; j < columnCount; j++)
      {
         TableColumn col = cm.getColumn(j);
         if(model.isStatistical() && j > 1 || !model.isStatistical() &&
            j < columnCount - 2)  
            col.setCellRenderer(lsRenderer);
         else
            col.setCellRenderer(mcRenderer);
      }
   }     

   /**
    * Updates the language of this table, using the given configuration as 
    * source of the column names.
    */
   public void updateLanguage(Configuration config)
   {
      tcsa.setEnabled(false); // Don't change column widths on language change
      model.setColumnNames(config);
      updateRenderer();
      tcsa.setEnabled(true);
   }

   /**
    * Returns the model of this table as a <code>ResultModel</code>.
    */
   public ResultModel getModel()
   {
      return model;
   }

   /**
    * Notifies this table that its model has changed. If the change involved
    * modification of the table structure, this event triggers renaming of
    * the columns.
    * 
    * @param e the result change event
    */
   public void resultChanged(ResultEvent e)
   {
      if (e.tableChanged())
         updateLanguage(e.getConfig());
   }
}
