package j3deditor.bin.util;

import java.awt.Dimension;

import java.awt.Toolkit;

import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;

import java.awt.event.WindowListener;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;

/**
 * Shows a progress bar in a popup window, which
 * indicates that something is processed.
 * 
 * @author Risto Seene
 */
public class ProgressIndicator extends JProgressBar implements WindowFocusListener, PropertyChangeListener, ProgressChangeListener, WindowListener{
	
	/** dialog of this progress indicator */
	private JDialog parent;
	
	/** info label */
	private JLabel info;
	
	/** determines if the shown <code>JProgressBar</code> is determinate or indeterminate */
	private boolean percentage = false;
	
	/** a task user can cancel by closing this dialog */
	private CancellableTask task = null;


	/**
	 * Creates an instance of <code>ProgressIndicator</code>.
	 */
	public ProgressIndicator(){
		this.info = new JLabel();
	          this.setIndeterminate(true);
	}
	
	
	/**
	 * Creates an instance of <code>ProgressIndicator</code>
	 * that shows the given info.
	 * 
	 * @param info
	 * 	info that will be shown
	 */
	public ProgressIndicator(String info){
		this();
		this.info.setText(info);
	}
	
	
	/**
	 * Associates a task with this progress indicator
	 * that user can cancel by closing this dialog.
	 * 
	 * @param task
	 * 	a task that can be cancelled
	 */
	public void setCancellableTask(CancellableTask task){
		this.task = task;
	}
	
	
	/**
	 * Makes this progress indicator visible.
	 */
	public void open(){
		if(this.parent == null){
			parent = new JDialog();
			parent.setIconImage(Utilities.image.getImage("icons/gear.png"));
			parent.setTitle(Utilities.translator.translate(this.getClass(), "processing"));
			parent.addWindowFocusListener(this);
			parent.addWindowListener(this);
			
			JPanel panel = new JPanel(null);
			info.setBounds(20, 10, 250, (int)(info.getPreferredSize().getHeight()));
			panel.add(info);
			this.setBounds(20, 30, 250, 20);

			panel.add(this);
			parent.add(panel);
			
			Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
			parent.setSize(300, 100);
			parent.setLocation((int)(size.getWidth()/2-150), (int)(size.getHeight()/2-50));
			parent.setVisible(true);
		}
	}
	
	
	/**
	 * Disposes this progress indicator.
	 */
	public void close(){
		try{
			this.parent.dispose();
			this.parent = null;
		} catch(Throwable t){}
	}


	/**
	 * Opens or closes this progress indicator according to the
	 * event sent by <code>SwingWorker</code>.
	 * 
	 * @param e
	 * 	event sent by <code>SwingWorker</code>
	 */
	public void propertyChange(PropertyChangeEvent e){
	          if(e.getNewValue() == SwingWorker.StateValue.STARTED){
	                    this.open();
	          }
		else if(e.getNewValue() == SwingWorker.StateValue.DONE){
			this.close();
		}
	}


	/**
	 * Sets the new percentage shown by this progress bar.
	 * 
	 * @param newPercentage
	 * 	new value
	 */
	public void percentageChanged(float newPercentage){
		if(!percentage){
			this.percentage = true;
			this.setIndeterminate(false);
			this.setMinimum(0);
			this.setMaximum(1000);
		          this.setStringPainted(true);
		}
		
		this.setValue((int)(10 * newPercentage));
	}


	/**
	 * Not in use.
	 * @param windowEvent
	 * 	doesn't do anything
	 */
	public void windowGainedFocus(WindowEvent windowEvent){
	}


	/**
	 * Brings this window to front if focus is lost.
	 * 
	 * @param windowEvent
	 * 	window event
	 */
	public void windowLostFocus(WindowEvent windowEvent){
		if(parent != null){
			try{
				this.parent.toFront();
			} catch(Throwable t){}
		}
	}


	/**
	 * Not in use.
	 * @param windowEvent
	 * 	doesn't do anything
	 */
	public void windowOpened(WindowEvent windowEvent){
	}


	/**
	 * Not in use.
	 * @param windowEvent
	 * 	doesn't do anything
	 */
	public void windowClosing(WindowEvent windowEvent){
		if(this.task != null){
			this.task.cancel(this);
		}
	}


	/**
	 * Not in use.
	 * @param windowEvent
	 * 	doesn't do anything
	 */
	public void windowClosed(WindowEvent windowEvent){
	}


	/**
	 * Not in use.
	 * @param windowEvent
	 * 	doesn't do anything
	 */
	public void windowIconified(WindowEvent windowEvent){
	}


	/**
	 * Not in use.
	 * @param windowEvent
	 * 	doesn't do anything
	 */
	public void windowDeiconified(WindowEvent windowEvent){
	}


	/**
	 * Not in use.
	 * @param windowEvent
	 * 	doesn't do anything
	 */
	public void windowActivated(WindowEvent windowEvent){
	}


	/**
	 * Not in use.
	 * @param windowEvent
	 * 	doesn't do anything
	 */
	public void windowDeactivated(WindowEvent windowEvent){
	}
	
}
