package org.apache.taverna.biocatalogue.ui;
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.awt.BorderLayout;
//import java.awt.Dimension;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;

import org.apache.taverna.biocatalogue.model.ResourceManager;
import org.apache.taverna.workbench.MainWindow;

/**
 * Creates a modal non-resizable dialog window.
 * 
 * Intended to be used for operations that consume some
 * time, but the user must wait for them to complete before
 * proceeding.
 * 
 * Initially the dialog shows a specified string message or
 * component and a "loader" bar - dynamic GIF image that
 * displays "activity" going on. At this stage the window
 * cannot be closed.
 * 
 * When the operation completes, the caller notifies the dialog
 * that it has finished, provides a new message / component to
 * display and allows the dialog to be closed.
 * 
 * If the operation doesn't complete within the specified time,
 * a timeout occurs and the dialog windows lets to close itself.
 * 
 * @author Sergejs Aleksejevs
 */
@SuppressWarnings("serial")
public class JWaitDialog extends JDialog
{
  private static final int DEFAULT_TIMEOUT = 10000;
  private static final ImageIcon LOADER_ICON = ResourceManager.getImageIcon(ResourceManager.BAR_LOADER_ORANGE);
  
  private JPanel jpInformationPanel;
  private JLabel jlLoaderIcon;
  
  private JButton bOK;
  private JPanel jpOKButton;
  
  private Timer timeoutTimer;
  private boolean hasTimedOut;
  
  
  /**
   * Creates a new Wait Dialog with no parent and default timeout on
   * operation - <code>JWaitDialog.DEFAULT_TIMEOUT</code>.
   * 
   * @param dialogTitle Title to set for the dialog window.
   * @param waitMessage Text to be displayed in the body of this dialog while
   *                    the user waits.
   */
  public JWaitDialog(String dialogTitle, String waitMessage) {
    this(null, dialogTitle, new JLabel(waitMessage, JLabel.CENTER), DEFAULT_TIMEOUT);
  }
  
  
  /**
   * Creates a new Wait Dialog with specified parent and default timeout on
   * operation - <code>JWaitDialog.DEFAULT_TIMEOUT</code>.
   * 
   * @param owner Specified JFrame is set as an owner for this Wait Dialog.
   * @param dialogTitle Title to set for the dialog window.
   * @param waitMessage Text to be displayed in the body of this dialog while
   *                    the user waits.
   */
  public JWaitDialog(JFrame owner, String dialogTitle, String waitMessage) {
    this(owner, dialogTitle, new JLabel(waitMessage, JLabel.CENTER), DEFAULT_TIMEOUT);
  }
  
  
  /**
   * Creates a new Wait Dialog with specified parent and timeout on
   * operation.
   * 
   * @param owner Specified JFrame is set as an owner for this Wait Dialog.
   * @param dialogTitle Title to set for the dialog window.
   * @param waitMessage Text to be displayed in the body of this dialog while
   *                    the user waits.
   * @param timeoutMillis Duration of the timeout on the operation - after this
   *                      time has passed the window will notify of the timeout
   *                      and allow to close itself. Value of 0 indicates that the timeout will never occur.
   */
  public JWaitDialog(JFrame owner, String dialogTitle, String waitMessage, int timeoutMillis) {
    this(owner, dialogTitle, new JLabel(waitMessage, JLabel.CENTER), timeoutMillis);
  }
  
  
  /**
   * Creates a new Wait Dialog with parent JFrame.
   * 
   * @param owner Specified JFrame is set as an owner for this Wait Dialog.
   * @param dialogTitle Title to set for the dialog window.
   * @param waitInformationComponent Component to be shown in the body of this
   *                    dialog windows while the user waits for an operation to complete.
   * @param timeoutMillis Duration of the timeout on the operation - after this
   *                      time has passed the window will notify of the timeout
   *                      and allow to close itself. Value of 0 indicates that the timeout will never occur.
   */
  public JWaitDialog(JFrame owner, String dialogTitle, JComponent waitInformationComponent, int timeoutMillis)
  {
    super(owner);
    this.setModal(true);
    this.setTitle(dialogTitle);
    
    // this will show the wait message to the user
    jpInformationPanel = new JPanel(new GridLayout());
    jpInformationPanel.add(waitInformationComponent);
    jpInformationPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 10, 20));
    
    // some graphical indication that the loading activity is going on
    jlLoaderIcon = new JLabel(LOADER_ICON);
    jlLoaderIcon.setBorder(BorderFactory.createEmptyBorder(0, 20, 20, 20));
    
    // put components into the dialog box
    this.getContentPane().setLayout(new BorderLayout());
    this.getContentPane().add(jpInformationPanel, BorderLayout.CENTER);
    this.getContentPane().add(jlLoaderIcon, BorderLayout.SOUTH);

    this.pack();
    // Set the height of the dialog not to be more than 500; the message is in the scroll pane so that should be OK
    this.setSize(new Dimension(this.getPreferredSize().width, this.getPreferredSize().height > 500 ? 500 : this.getPreferredSize().height));
    //    this.setResizable(false);
    this.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
    
    // center this window within the main Taverna Workbench window
    this.setLocationRelativeTo(MainWindow.getMainWindow());
    
    
    // start the timer - on timeout it will produce the
    // timeout message and allow to close the window
    hasTimedOut = false;
    if (timeoutMillis > 0)
    {
      timeoutTimer = new Timer();
      timeoutTimer.schedule(
          new TimerTask() {
            public void run() {
              waitFinished(new JLabel("<html><center>The operation did not complete within the " +
              		                    "allocated time.</center></html>",
              		                    UIManager.getIcon("OptionPane.warningIcon"), JLabel.CENTER));
              hasTimedOut = true;
            }
          },
          timeoutMillis);
    }
  }
  
  
  public void waitFinished(String resultMessage) {
    waitFinished(new JLabel(resultMessage, JLabel.CENTER));
  }
  
  public void waitFinished(JComponent resultInformationComponent)
  {
    // this prevents the real response to be set after the
    // timeout message was already displayed
    if (!hasTimedOut)
    {
      // first of all stop the timeout timer: if this
      // method was called by the application explicitly, not on
      // timeout, we don't want the timeout message to appear after that
      if (timeoutTimer != null) { timeoutTimer.cancel(); }
      
      // change the information component
      jpInformationPanel.removeAll();
      jpInformationPanel.add(resultInformationComponent);
      
      // the OK button will allow closing the window
      bOK = new JButton("OK");
      //bOK.setPreferredSize(new Dimension(LOADER_ICON.getIconWidth(), (int) (1.5 * LOADER_ICON.getIconHeight())));
      bOK.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          // just remove the window
          dispose();
        }
      });
      bOK.addKeyListener(new KeyAdapter() {
        public void keyPressed(KeyEvent e) {
          if (e.getKeyCode() == KeyEvent.VK_ENTER) {
            // a fallback mechanism - default button doesn't work for some reason
            // when the button is added into the dialog not in the constructor
            bOK.doClick();
          }
        }
      });
      bOK.setDefaultCapable(true);
      this.getRootPane().setDefaultButton(bOK);
      
      // wrap OK button into a panel to add empty borders
      jpOKButton = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
      jpOKButton.add(bOK);
      jpOKButton.setBorder(BorderFactory.createEmptyBorder(0, 20, 20 - (bOK.getPreferredSize().height - LOADER_ICON.getIconHeight()), 20));
      
      
      // add OK button instead of the loader icon 
      this.getContentPane().remove(jlLoaderIcon);
      this.getContentPane().add(jpOKButton, BorderLayout.SOUTH);
      this.bOK.requestFocusInWindow();
      
      // re-enable (X) button in the title bar
      this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
      
      // update the size of this window - as the inner sizes of components have
      // been likely to change; then center the dialog box within its parent
      this.pack();
      // Set the height of the dialog not to be more than 500; the message is in the scroll pane so that should be OK
      this.setSize(new Dimension(this.getPreferredSize().width, this.getPreferredSize().height > 500 ? 500 : this.getPreferredSize().height));
      this.setLocationRelativeTo(MainWindow.getMainWindow());
    }
  }
  
  
}
