/*******************************************************************************
 * 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.labo.utils;

import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import java.util.regex.Pattern;

import lu.tudor.santec.ftp.FTPClient;
import lu.tudor.santec.ftp.FTPClientException;
import lu.tudor.santec.ftp.FTPFileDescriptor;
import lu.tudor.santec.gecamed.core.utils.Logger;
import lu.tudor.santec.gecamed.labo.ejb.entity.beans.Certifier;
import lu.tudor.santec.gecamed.labo.ejb.entity.beans.Connection;
import lu.tudor.santec.gecamed.labo.ejb.session.interfaces.ImportInterface;
import lu.tudor.santec.gecamed.labo.ejb.session.interfaces.LaboratoryInterface;

import org.apache.log4j.Level;

public class ResultDownloader
	{
	private static Logger		m_Logger = new Logger (ResultDownloader.class);
	
	private FTPClient			m_FtpClient;
	
//---------------------------------------------------------------------------
//***************************************************************************
//* Constants	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------

    private static final Pattern	c_FilenamePattern = Pattern.compile ("^(\\d{6}-\\d{2}[A-Z]?)(\\d{6}-\\d{2}[A-Z]?)(\\d{10})\\.xml$",Pattern.CASE_INSENSITIVE);

//---------------------------------------------------------------------------
//***************************************************************************
//* Constructor	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------

public ResultDownloader ()
	{
	m_FtpClient 	= new FTPClient ();	
	}

//---------------------------------------------------------------------------
//***************************************************************************
//* Primitives	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
//***************************************************************************
//* Class Body	                                                            *
//***************************************************************************
//---------------------------------------------------------------------------

public boolean isConnected ()
	{
	return m_FtpClient.isConnected();
	}

//---------------------------------------------------------------------------

public boolean openConnection (Connection p_Connection, LaboratoryInterface laboManager)
	{
	if (p_Connection == null) return false;
	
	if (m_FtpClient.isConnected()) m_FtpClient.disconnectFromServer();
	
	m_FtpClient.setPassiveMode(p_Connection.getPassiveMode());
	if (p_Connection.getPort() != null) m_FtpClient.setPort(p_Connection.getPort());
	
	try	{
		m_FtpClient.connectToServer(p_Connection.getServer(),
								    p_Connection.getUsername(),
								    p_Connection.getPassword());
		
		downloadCertifiers(p_Connection.getServer(), laboManager);
		}
	catch (FTPClientException p_Exception)
		{
		m_Logger.log (Level.ERROR,"Error while opening connection to server " + p_Connection.getServer() + "!", p_Exception);	
		}
		
	return m_FtpClient.isConnected();
	}

//---------------------------------------------------------------------------

public Collection <String> getListOfAvailableResults ()
	{
	Collection <String>	l_AvailableResults	= null;
	FTPFileDescriptor	l_Descriptor		= null;
	String				l_Filename			= null;
	
	if (!m_FtpClient.isConnected()) return null;
	
	try	{
	    m_FtpClient.buildFileList("./");
 	    m_FtpClient.setFileMatchPattern (c_FilenamePattern.pattern());

        l_AvailableResults = new Vector <String> ();
        
        do  {
            l_Descriptor = m_FtpClient.getNextFileDescriptor (FTPFileDescriptor.c_File);
 
            if (l_Descriptor != null) 
                {    
                l_Filename = l_Descriptor.getFileName();
                l_AvailableResults.add(l_Filename);
                }
        	}
        while (l_Descriptor != null);
		}
	catch (FTPClientException p_Exception)
		{
		m_Logger.log (Level.FATAL,"Error while retrieving list of available results !", p_Exception);			
		}
	
	return l_AvailableResults;
	}

//---------------------------------------------------------------------------

public byte[] downloadResult (String p_ResultFilename)
	{
	byte[] l_ResultData = null;
	
	if (!m_FtpClient.isConnected()) return null;
		
	m_Logger.log (Level.INFO,"Downloading Result file " + p_ResultFilename + " !");			

	try {
		l_ResultData = m_FtpClient.fetchData (p_ResultFilename, FTPClient.c_ASCII);
//		m_FtpClient.renameFile (p_ResultFilename,"old/" + p_ResultFilename);
		}
	catch (FTPClientException p_Exception)
		{
		m_Logger.log (Level.FATAL,"Error while downloading file " + p_ResultFilename + " !", p_Exception);			
		}
	
	return l_ResultData;
	}

//---------------------------------------------------------------------------

public void renameFile (String p_OldFileName, String p_NewFileName) throws DecryptException
	{
	byte[] check = null;
	try {
		m_FtpClient.renameFile (p_OldFileName, p_NewFileName);
		
		check = m_FtpClient.fetchData(p_NewFileName, FTPClient.c_ASCII);
		}
	catch (Exception p_Exception)
		{
		throw new DecryptException(ImportInterface.COULD_NOT_MOVE_FILE);
		}
	if (check == null)
		throw new DecryptException(ImportInterface.COULD_NOT_MOVE_FILE);
	}

//---------------------------------------------------------------------------

public void closeConnection ()
	{
	if (m_FtpClient.isConnected()) m_FtpClient.disconnectFromServer();	
	}

//---------------------------------------------------------------------------

private void downloadCertifiers (String serverName, LaboratoryInterface laboManager)
{
	downloadCertifiers(serverName, m_FtpClient, laboManager);
}


public static void downloadCertifiers (String serverName, FTPClient ftpClient, LaboratoryInterface laboManager)
{
	FTPFileDescriptor	descriptor;
	Date				fileDate;
	String				fileName;
	Certifier			certifier;
	List<Certifier>		filesToDownload	= new LinkedList<Certifier>();
	byte[]				data;
	
	
	try
	{
		ftpClient.setFileMatchPattern(".*chain.*\\.crt");
		ftpClient.buildFileList(CertificateSynchronizer.c_CertificateFolder);
		
		while ((descriptor = ftpClient.getNextFileDescriptor(FTPFileDescriptor.c_File)) != null)
		{
			fileDate	= descriptor.getFileDate();
			fileName	= descriptor.getFileName();
			
			certifier	= laboManager.getOutdatedCertifier(
					Certifier.generateLabel(serverName, CertificateSynchronizer.c_CertificateFolder, fileName), 
					fileDate);
			
			if (certifier != null)
			{
				certifier.setFtpFileName(fileName);
				certifier.setFtpFolderName(CertificateSynchronizer.c_CertificateFolder);
				certifier.setFtpServerName(serverName);
				filesToDownload.add(certifier);
			}
		}
		
		if (!filesToDownload.isEmpty())
		{
			try
			{
				ftpClient.changeDirectory(CertificateSynchronizer.c_CertificateFolder);
				
				for (Certifier c : filesToDownload)
				{
					data	= ftpClient.fetchData(c.getFtpFileName(), FTPClient.c_ASCII);
					c.setCertificate(new String(data));
					laboManager.saveCertifier(c);
				}
			}
			catch (FTPClientException e)
			{
				m_Logger.log(Level.ERROR, "Error while loading certifier files from server.", e);
			}
		}
	}
	catch (FTPClientException e)
	{
		m_Logger.log(Level.ERROR, "Error while checking certifier files from server.", e);
	}
	finally
	{
		try
		{
			ftpClient.changeDirectory("~");
		}
		catch (FTPClientException e)
		{
			m_Logger.log(Level.ERROR, "Couldn't switch back to home folder.", e);
		}
	}
}

//---------------------------------------------------------------------------
//***************************************************************************
//* End of Class                                                            *
//***************************************************************************
//---------------------------------------------------------------------------
	}