/*
 *  Draco Econometrics
 *  Copyright (C) 2006-2007 Approximatrix, LLC
 *  http://www.approximatrix.com
 *  
 *  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 3 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, see <http://www.gnu.org/licenses/>.
 */

package com.approximatrix.draco.io.ui;

import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JDialog;
import javax.swing.BoxLayout;
import javax.swing.JProgressBar;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

import com.sun.java.SwingWorker;

public class IOFileWorkerDialog extends JDialog {

	private JPanel jContentPane = null;
	private IOWorker ioworker = null;
	private JPanel jPanel = null;
	private JProgressBar jProgressBar = null;
	private JPanel jPanel1 = null;
	private JLabel statuslabel = null;
	
	private SwingWorker workerthread = null;
	
	/**
	 * This is the default constructor
	 */
	public IOFileWorkerDialog(IOWorker worker) {
		super(worker.getParentWindow(),true);
		ioworker = worker;
		initialize();
		this.setLocationRelativeTo(worker.getParentWindow());
		build_worker();
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(300, 87);
		this.setPreferredSize(new java.awt.Dimension(300, 150));
		this.setResizable(false);
		this.setContentPane(getJContentPane());
		this.setTitle(ioworker.getWorkerTitle());
		this.getJProgressBar().setMaximum(ioworker.getTotalSteps());
		this.getJProgressBar().setMinimum(0);
		this.addWindowListener(new java.awt.event.WindowAdapter() {
			public void windowClosing(java.awt.event.WindowEvent e) {
				if(workerthread != null)
					workerthread.interrupt();
				IOFileWorkerDialog.this.setVisible(false);
				dispose();
			}
		});
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BoxLayout(getJContentPane(), BoxLayout.Y_AXIS));
			jContentPane.add(getJPanel(), null);
			jContentPane.add(getJPanel1(), null);
		}
		return jContentPane;
	}

	/**
	 * This method initializes jPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJPanel() {
		if (jPanel == null) {
			jPanel = new JPanel();
			jPanel.add(getJProgressBar(), null);
		}
		return jPanel;
	}

	/**
	 * This method initializes jProgressBar	
	 * 	
	 * @return javax.swing.JProgressBar	
	 */
	private JProgressBar getJProgressBar() {
		if (jProgressBar == null) {
			jProgressBar = new JProgressBar();
			jProgressBar.setPreferredSize(new java.awt.Dimension(275,14));
		}
		return jProgressBar;
	}

	/**
	 * This method initializes jPanel1	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJPanel1() {
		if (jPanel1 == null) {
			statuslabel = new JLabel();
			statuslabel.setText("JLabel");
			jPanel1 = new JPanel();
			jPanel1.add(statuslabel, null);
		}
		return jPanel1;
	}
	
	/** Updates the Swing components safely from the SwingWorker thread
	 * 
	 * @param iteration the current iteration
	 * @param status the message to display
	 */
	private void updateStatus(final int iteration, final String status) {
		Runnable doSetProgress = new Runnable() {
            public void run() {
            	jProgressBar.setValue(iteration-1);
            	statuslabel.setText(status);
            }
        };
        SwingUtilities.invokeLater(doSetProgress);
	}

	/** This routine represents the meat of the SwingWorker thread that performs
	 * all iteration control
	 * 
	 * @return for now, a String
	 */
	private Object doIterations() {
		try {
			
			int step = 0;
			while(step<ioworker.getTotalSteps()) {
				step = ioworker.getStepNumber();
				updateStatus(step,ioworker.getStatus());
				ioworker.doStep();
				
				if(!ioworker.stepSuccess()) {
					updateStatus(ioworker.getTotalSteps(),"Failure");
					break;
				}
				
				// Check interuptions
				if (Thread.interrupted()) {
					throw new InterruptedException();
				}
			}
			
		} catch (InterruptedException e) {
			updateStatus(ioworker.getTotalSteps(),"Failure");
			return "Interrupted";  
		}
		
		return "All Done"; 
	}
	
	/** Constructs the worker thread and starts it on its way
	 * 
	 */
	private void build_worker() {
		/* Invoking start() on the SwingWorker causes a new Thread
		 * to be created that will call construct(), and then
		 * finished().  Note that finished() is called even if
		 * the worker is interrupted because we catch the
		 * InterruptedException in doWork().
		 */
		workerthread = new SwingWorker() {
			public Object construct() {
				return doIterations();
			}
			public void finished() {
				Runnable doSetProgress = new Runnable() {
		            public void run() {
		            	IOFileWorkerDialog.this.dispose();
		            }
		        };
		        SwingUtilities.invokeLater(doSetProgress);
			}
		};
		workerthread.start();
	}
	
}  //  @jve:decl-index=0:visual-constraint="10,10"
