/*
 * 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.event.*;
import javax.swing.*;
import com.jgoodies.forms.layout.*;
import ipipan.poliqarp.logic.Job;

import ipipan.poliqarp.logic.ServerJob;

/**
 * A <code>StatusPanel</code> is the bottom-most part of the GUI window.
 * It consists of: <ul>
 *   <li>a status line, which displays information about the GUI's current
 *       status;</li>
 *   <li>a progress bar (visible only when a time-consuming operation is
 *       in progress);</li>
 *   <li>three buttons: one used to switch between wide context and metadata
 *       and two to advance to the next/previous parts of the result table.
 *   </li>
 * </ul>
 * It also is a compound <code>MultilingualEntity</code>, performing 
 * language changes on its components as requested.
 */
public class StatusPanel extends JPanel implements MultilingualEntity, 
   ResultEventListener
{   
   private Application app;
   private StatusLine statusLine;
   private JProgressBar progressBar;
   private MultifunctionButton toggleButton;
   private JButton upButton, downButton;
   private Timer timer;
   private ResultModel res;
   private boolean upLast, downLast;

   private class ButtonActionListener implements ActionListener 
   {
      public void actionPerformed(ActionEvent e) 
      {
         if (e.getSource() == upButton)
            res.scrollUp();
         else if (e.getSource() == downButton)
            res.scrollDown();
         else if (e.getSource() == toggleButton) {
            toggleButton.nextFunction();
            app.toggleContextVisible();
         }
      }
   }

   private final class ProgressBarListener implements ActionListener
   {
      private Job job;
      private JProgressBar bar;

      public ProgressBarListener(Job job, JProgressBar bar)
      {
         this.job = job;
         this.bar = bar;
      }
      
      public void actionPerformed(ActionEvent e)
      {
         bar.setValue(job.getProgress());
      }
   }

   /**
    * Constructs a default status panel.
    */
   public StatusPanel(Application app)
   {
      super();
      this.app = app;
      timer = null;
      setLayout(new FormLayout("0:grow(0.65), 2dlu, 0:grow(0.35), 2dlu, default, 2dlu, default, 2dlu, default", "default"));

      statusLine = new StatusLine();
      add(statusLine, new CellConstraints(1, 1));

      progressBar = new JProgressBar(0, 100);
      progressBar.setStringPainted(true);
      progressBar.setValue(0);
      progressBar.setVisible(false);
      add(progressBar, new CellConstraints(3, 1));

      ButtonActionListener bal = new ButtonActionListener();
      toggleButton = new MultifunctionButton("TOGGLE", 2);
      toggleButton.addActionListener(bal);
      add(toggleButton, new CellConstraints(5, 1));
      upButton = new JButton(PoliqarpIconFactory.loadIcon("arr_u"));
      upButton.setEnabled(false);
      upButton.addActionListener(bal);
      add(upButton, new CellConstraints(7, 1));
      downButton = new JButton(PoliqarpIconFactory.loadIcon("arr_d"));
      downButton.setEnabled(false);
      downButton.addActionListener(bal);
      add(downButton, new CellConstraints(9, 1));
   }

   /**
    * Updates the language of this panel.
    */
   public void updateLanguage(Configuration config)
   {
      statusLine.updateLanguage(config);
      toggleButton.updateLanguage(config);
   }

   /**
    * Shows the progress bar, sets its position to zero and launches
    * a timer that updates its content every 1/10th of a second. The
    * progress bar will reflect progress of the given job.
    */
   public void enableProgress(Job job)
   {
      progressBar.setValue(0);
      progressBar.setVisible(true);
      timer = new Timer(100, new ProgressBarListener(job, progressBar));
      timer.start();
   }

   /**
    * Hides the progress bar, disabling the timer.
    */
   public void disableProgress()
   {
      timer.stop();
      timer = null;
      progressBar.setVisible(false);
   }

   /**
    * Returns the status line component of this panel.
    */
   public StatusLine getStatusLine()
   {
      return statusLine;
   }

   /**
    * Sets state and updates the status line basing on the state and
    * language.
    */
   public void setState(StatusLine.State state, 
                        String param1, String param2, 
                        Configuration c)
   {
      statusLine.setState(state, param1, param2);
      statusLine.updateLanguage(c);
   }

   /**
    * Notifies this status panel that the results displayed by the result 
    * table have been altered. This can involve altering the status line
    * and enabling/disabling the "up" and "down" buttons.
    */
   public void resultChanged(ResultEvent e)
   {
      res = e.getSource();
      upButton.setEnabled(res.getStartPosition() > 0);
      downButton.setEnabled(res.getEndPosition() < res.getTotal());
      statusLine.resultChanged(e);
   }

   /**
    * Enables or disables the 'Previous' and 'Next' buttons
    * of this panel.
    */
   public void setButtonsEnabled(boolean enabled)
   {
      if (enabled) {
         upButton.setEnabled(upLast);
         downButton.setEnabled(downLast);
      } else {
         upLast = upButton.isEnabled();
         downLast = downButton.isEnabled();
         upButton.setEnabled(false);
         downButton.setEnabled(false);
      }
   }
}
