/*******************************************************************************
 * This file is part of GECAMed.
 * 
 * GECAMed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (L-GPL) as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GECAMed 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License (L-GPL)
 * along with GECAMed.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * GECAMed is Copyrighted by the Centre de Recherche Public Henri Tudor (http://www.tudor.lu)
 * (c) CRP Henri Tudor, Luxembourg, 2008
 *******************************************************************************/
package lu.tudor.santec.gecamed.patient.gui.fileimport;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import lu.tudor.santec.gecamed.core.gui.LoginScreen;
import lu.tudor.santec.gecamed.core.gui.MainFrame;
import lu.tudor.santec.gecamed.core.gui.widgets.GECAMedBaseDialog;
import lu.tudor.santec.gecamed.core.utils.GECAMedUtils;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Logger;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

/**
 * @author Thorsten Roth thorsten.roth(at)tudor.lu
 *
 * @version
 * <br>$Log: ScannerDialog.java,v $
 * <br>Revision 1.11  2014-01-23 15:00:15  ferring
 * <br>OS and Java checking moved from MainFrame (where only client components can access) to GECAMedUtils (where also server can access it)
 * <br>
 * <br>Revision 1.10  2013-12-27 18:09:25  donak
 * <br>Cleanup of imports
 * <br>
 * <br>Revision 1.9  2013-10-28 16:52:57  ferring
 * <br>os notification changed and shortcut key modifier added
 * <br>
 * <br>Revision 1.8  2013-07-15 06:18:36  ferring
 * <br>logging changed
 * <br>
 * <br>Revision 1.7  2013-01-17 14:46:12  troth
 * <br>Code clearup.
 * <br>
 * <br>Revision 1.6  2013-01-17 14:09:41  troth
 * <br>Fix some Bugs in Scanner Dialog.
 * <br>
 * <br>Revision 1.5  2013-01-17 12:52:54  troth
 * <br>Fix some bugs in the scanner dialog.
 * <br>
 * <br>Revision 1.4  2013-01-17 10:35:44  troth
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.3  2013-01-17 10:14:42  troth
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.2  2013-01-17 09:50:52  troth
 * <br>Scanner control version 1.
 * <br>
 * <br>Revision 1.1  2013-01-16 16:42:50  troth
 * <br>add new Scanner dialog.
 * <br>
 */
public class ScannerDialog extends GECAMedBaseDialog implements ActionListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private int dialogSizeX = 550;
	
	private int dialogSizeY = 560;
	
	private CellConstraints cc;
	
	private boolean pathScan = true;
	
	private JPanel scannerStartPanel;
	
	private JLabel scannerSoftwareFileLabel;
	
	private JTextField scannerSoftwareFileName;
	
	private JButton scannerSoftwareFileChooseButton;
	
	private JLabel scannerImagePathLabel;
	
	private JTextField scannerImagePathName;

	private JButton scannerImagePathChooseButton;
	
	private JButton startScanButton;
	
	private JLabel scannedFilesLabel;
	
	private JScrollPane scrollPaneScannedFiles;
	
	private JTextArea scannedFilesTextArea;
	
	private JButton setPathToDefaultButton;
	
	private String scannerSoftwarePath;
	
	private String scannerImagePath;
	
	public static final String SCANNER_SOFTWARE_PATH_DEFAULT = "/Applications/Image Capture.app";
	
	public static final String SCANNER_IMAGE_PATH_DEFAULT = "/Users/" + System.getProperty("user.name") + "/Pictures";
	
	private ArrayList<File> saveFiles = new ArrayList<File>();
	
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(ScannerDialog.class.getName());
	
	
	/**
	 * Constructor
	 */
	public ScannerDialog()
	{
		super(Translatrix.getTranslationString("scanner.dialog.title"), true);
		// set the scanner software and the scanner image path
		this.scannerSoftwarePath = MainFrame.getMachineSetting(LoginScreen.SCANNER_SOFTWARE_PATH);
		this.scannerImagePath = MainFrame.getMachineSetting(LoginScreen.SCANNER_IMAGE_PATH);
		if(this.scannerSoftwarePath == null)
			this.scannerSoftwarePath = SCANNER_SOFTWARE_PATH_DEFAULT;
		if(this.scannerImagePath == null)
			this.scannerImagePath = SCANNER_IMAGE_PATH_DEFAULT;
		// init dialog components
		initPanel();
		initActions();
	}


	/**
	 * show and center the scanner dialog over the main frame.
	 * @return
	 */
	public ArrayList<File> showDialog()
	{
		this.setSize(dialogSizeX, dialogSizeY);
		MainFrame.showDialogCentered(this);
		return this.saveFiles;
	}

	
	/**
	 * init all button actions.
	 */
	private void initActions()
	{
		this.okButton.addActionListener(this);
		this.cancelButton.addActionListener(this);
		this.setPathToDefaultButton.addActionListener(this);
		this.startScanButton.addActionListener(this);
		this.scannerSoftwareFileChooseButton.addActionListener(this);
		this.scannerImagePathChooseButton.addActionListener(this);
	}

	
	/**
	 * init the main dialg panel.
	 */
	private void initPanel()
	{	
		this.cc = new CellConstraints();
		
		this.scannerStartPanel = new JPanel();
		this.scannerStartPanel.setLayout(new FormLayout("3dlu ,pref, 3dlu, default:grow, 3dlu", 
				"3dlu, " +
				"pref, " +			//2 Software path chooser
				"3dlu, " +
				"pref, " +			//4 Image path chooser
				"3dlu, " +
				"pref, " +			//6 set paths to default button
				"20dlu, " +
				"pref, " +			//8 start scan button
				"20dlu, " +
				"pref, " +			//10 text label for scanned files field
				"3dlu, " +
				"top:pref:grow, " +	//12 scanned files field
				"3dlu"));
		this.scannerStartPanel.setOpaque(false);
		
		// Software path chooser
		this.scannerSoftwareFileLabel = new JLabel(Translatrix.getTranslationString("scanner.dialog.softwarePath"));
		this.scannerStartPanel.add(this.scannerSoftwareFileLabel, cc.xy(2,2));
		final JFileChooser scannerSoftwareFileChooser = new JFileChooser();
		scannerSoftwareFileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); //JFileChooser.DIRECTORIES_ONLY
		JPanel scannerSoftwarePanel = new JPanel(new BorderLayout());
		this.scannerSoftwareFileName = new JTextField(scannerSoftwarePath);
		//this.scannerSoftwareFileName.setEditable(false);
		scannerSoftwarePanel.add(this.scannerSoftwareFileName, BorderLayout.CENTER);
		this.scannerSoftwareFileChooseButton = new JButton("...");
		this.scannerSoftwareFileChooseButton.addActionListener(new ActionListener() {
			
			public void actionPerformed(ActionEvent e) 
			{
				int returnVal = scannerSoftwareFileChooser.showOpenDialog(scannerStartPanel);

		        if (returnVal == JFileChooser.APPROVE_OPTION) {
		            File file = scannerSoftwareFileChooser.getSelectedFile();
		            scannerSoftwareFileName.setText(file.getAbsolutePath());
		        }
			}
		});
		scannerSoftwarePanel.add(this.scannerSoftwareFileChooseButton, BorderLayout.EAST);
		this.scannerStartPanel.add(scannerSoftwarePanel, cc.xy(4,2));
		
		// Image path chooser
		this.scannerImagePathLabel = new JLabel(Translatrix.getTranslationString("scanner.dialog.imagePath"));
		this.scannerStartPanel.add(this.scannerImagePathLabel, cc.xy(2,4));
		final JFileChooser scannerImagePathChooser = new JFileChooser();
		scannerImagePathChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); //JFileChooser.DIRECTORIES_ONLY
		JPanel scannerImagePathPanel = new JPanel(new BorderLayout());
		this.scannerImagePathName = new JTextField(scannerImagePath);
		//this.scannerImagePathName.setEditable(false);
		scannerImagePathPanel.add(this.scannerImagePathName, BorderLayout.CENTER);
		scannerImagePathChooseButton = new JButton("...");
		this.scannerImagePathChooseButton.addActionListener(new ActionListener() {
			
			public void actionPerformed(ActionEvent e) 
			{
				int returnVal = scannerImagePathChooser.showOpenDialog(scannerStartPanel);

		        if (returnVal == JFileChooser.APPROVE_OPTION) {
		            File file = scannerImagePathChooser.getSelectedFile();
		            scannerImagePathName.setText(file.getAbsolutePath());
		        }
			}
		});
		scannerImagePathPanel.add(this.scannerImagePathChooseButton, BorderLayout.EAST);
		this.scannerStartPanel.add(scannerImagePathPanel, cc.xy(4,4));
		
		// set paths to default button
		this.setPathToDefaultButton = new JButton(Translatrix.getTranslationString("scanner.dialog.defaultButton"));
		this.scannerStartPanel.add(setPathToDefaultButton, cc.xyw(2, 6, 3, CellConstraints.RIGHT, CellConstraints.CENTER));
		
		// start scan button
		this.startScanButton = new JButton(Translatrix.getTranslationString("scanner.dialog.startScanButton"));
		this.scannerStartPanel.add(startScanButton, cc.xyw(2, 8, 3, CellConstraints.CENTER, CellConstraints.CENTER));
		
		// text label for scanned files field
		this.scannedFilesLabel = new JLabel(Translatrix.getTranslationString("scanner.dialog.scannedFilesLabel"));
		this.scannerStartPanel.add(scannedFilesLabel, cc.xyw(2, 10, 3));
		// scanned files field
		this.scannedFilesTextArea = new JTextArea(Translatrix.getTranslationString("scanner.dialog.noFiles"));
		this.scrollPaneScannedFiles = new JScrollPane(scannedFilesTextArea);
		this.scrollPaneScannedFiles.setPreferredSize(new Dimension(getPreferredSize().width,200));//(getPreferredSize());
		this.scannerStartPanel.add(scrollPaneScannedFiles, cc.xyw(2, 12, 3));
		// add Main Panel to Dialog
		this.addMainPanel(this.scannerStartPanel);
	}

	
	/* (non-Javadoc)
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent e) 
	{	
		// set path of scanner software and scanned images to default path
		if(this.setPathToDefaultButton.equals(e.getSource()))
		{
			setPathToDefault();
		}
		
		// start the scanner software
		if(this.startScanButton.equals(e.getSource()))
		{
			this.scannerSoftwarePath = this.scannerSoftwareFileName.getText();
			this.scannerImagePath = this.scannerImagePathName.getText();
			startScanSoftware();
		}
		
		// return new scanned files and close dialog
		if(this.okButton.equals(e.getSource()))
		{
			pathScan = false;
			this.setVisible(false);
			MainFrame.setMachineSetting(LoginScreen.SCANNER_SOFTWARE_PATH, this.scannerSoftwareFileName.getText());
			MainFrame.setMachineSetting(LoginScreen.SCANNER_IMAGE_PATH, this.scannerImagePathName.getText());
		}
		
		// do nothing and close dialog
		if (cancelButton.equals(e.getSource()))
		{
			pathScan = false;
			this.setVisible(false);			
		}
	}


	/**
	 * set defult path of the scanner software and the scanner image folder.
	 */
	private void setPathToDefault()
	{
		this.scannerSoftwarePath = SCANNER_SOFTWARE_PATH_DEFAULT;
		this.scannerImagePath = SCANNER_IMAGE_PATH_DEFAULT;
		this.scannerSoftwareFileName.setText(this.scannerSoftwarePath);
		this.scannerImagePathName.setText(this.scannerImagePath);
	}
	
	
	/**
	 * Disable the two filechoosers, the reset button and the start scanner button
	 */
	private void disableUpperComponents()
	{
		this.scannerSoftwareFileChooseButton.setEnabled(false);
		this.scannerImagePathChooseButton.setEnabled(false);
		this.setPathToDefaultButton.setEnabled(false);
		this.startScanButton.setEnabled(false);
	}

	/**
	 * Enable the two filechoosers, the reset button and the start scanner button
	 */
	private void enableUpperComponents()
	{
		this.scannerSoftwareFileChooseButton.setEnabled(true);
		this.scannerImagePathChooseButton.setEnabled(true);
		this.setPathToDefaultButton.setEnabled(true);
		this.startScanButton.setEnabled(true);
	}
	
	/**
	 * call scanner software given from the user settings.
	 */
	private void startScanSoftware()
	{
		// try to start scanner software
		Process startImageCaptureProcess = null;
		
		try {
			if(GECAMedUtils.getOS() == GECAMedUtils.OS_MAC) startImageCaptureProcess = Runtime.getRuntime().exec(new String[]{"open", scannerSoftwarePath});
			else if(GECAMedUtils.getOS() == GECAMedUtils.OS_WINDOWS) startImageCaptureProcess = Runtime.getRuntime().exec(scannerSoftwarePath);
		} catch (IOException e) {
			logger.warn("Can't start Image Capture !!!\n" + e.getStackTrace());
			JOptionPane.showMessageDialog(this, "Die Scanner Software im Pfad x konnte nicht gestartet werden, bitte prüfen Sie ob der Pfad richtig angegeben ist und ob die Sannersoftware richtig installiert ist.", "info", JOptionPane.INFORMATION_MESSAGE);
			enableUpperComponents();
			return;
		}
		// the function waitFor() works not fine under windows
//		System.out.println("wait for exit value ...");
//		try {
//			System.out.println("ExitValue: " + startImageCaptureProcess.waitFor());
//			if(startImageCaptureProcess.exitValue() != 0)
//			{
//				JOptionPane.showMessageDialog(this, "Die Scanner Software im Pfad x konnte nicht gestartet werden, bitte prüfen Sie ob der Pfad richtig angegeben ist und ob die Sannersoftware richtig installiert ist.", "info", JOptionPane.INFORMATION_MESSAGE);
//				return;
//			}else System.out.println("Image Capture starts ...!!!");
//		} catch (InterruptedException e) {
//			e.printStackTrace();
//			
//			enableUpperComponents();
//			return;
//		}
		
		// start watching the scanner image path in a thread
		// if new file found build new file list to import
		final File imageDir = new File(scannerImagePath);
		final long startTime = new Date().getTime();
		this.pathScan = true;
		Thread pathScanThread = new Thread()
		{
			public void run() 
			{
				disableUpperComponents();
				while(pathScan)
				{
					File[] fileList = imageDir.listFiles();
					ArrayList<File> files = new ArrayList<File>();
					for (int i = 0; i < fileList.length; i++)
					{
						if (fileList[i].isFile())
						{
							if(fileList[i].lastModified() > startTime)
							{
								files.add(fileList[i]);
							}
						}
					}
					
					String fileListString = "";
					for (File file : files)
					{
						fileListString += file.getName() + "\n";
					}
					scannedFilesTextArea.setText(fileListString);
					saveFiles = files;
					try {
						Thread.sleep(3000);
					} catch (InterruptedException e) {
						logger.warn("GECAMed PathScan Thread can't sleep.\n" + e.getStackTrace());
						e.printStackTrace();
					}
				}
			}
		};
		
		pathScanThread.start();
	}
	
	// Close the dialog aktion
	@Override
	public void closeActionCalled()
	{
		pathScan = false;
		this.setVisible(false);
	}
}
