
package jp.riken.brain.ni.samuraigraph.application;

import java.awt.Window;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import jp.riken.brain.ni.samuraigraph.base.SGIConstants;
import jp.riken.brain.ni.samuraigraph.base.SGUtility;

import org.w3c.dom.DOMImplementation;

/**
 * 
 * This class provides static methods for the application.
 */
public class SGApplicationUtility implements SGIApplicationTextConstants
{

	/**
	 * Delete all files recursively.
	 * @param f The abstract pathname to be deleted.
	 */
	public static void deleteRecursively( final File f )
	{
		if( f.isDirectory() )
		{
			String dir = f.getAbsolutePath();
			String fs = SGIConstants.FILE_SEPARATOR;
			String[] fList = f.list();
			for( int ii=0; ii<fList.length; ii++ )
			{
				File f_ = new File( f + fs + fList[ii] );
				deleteRecursively( f_ );
			}
		}

		f.delete();
	}
	

	/**
	 * Delete all files recursively when the virtual machine terminates.
	 * @param f The abstract pathname to be deleted.
	 */
	public static void deleteOnExitRecursively( final File f )
	{
		if( f.isDirectory() )
		{
			String dir = f.getAbsolutePath();
			String fs = SGIConstants.FILE_SEPARATOR;
			String[] fList = f.list();
			for( int ii=0; ii<fList.length; ii++ )
			{
				File f_ = new File( f + fs + fList[ii] );
				deleteOnExitRecursively( f_ );
			}
		}

		f.deleteOnExit();
	}



	/**
	 * Copy file from f1 to f2.
	 * @param f1
	 * @param f2
	 * @return true:success, false:failure
	 */
	public static boolean copyBinaryFile(
		final File f1, final File f2 )
		throws IOException
	{
		if( f1==null | f2==null )
		{
			return false;
		}

		FileInputStream in = null;
		FileOutputStream out = null;
		try
		{
			in = new FileInputStream(f1);
			out = new FileOutputStream(f2);
		}
		catch( FileNotFoundException ex )
		{
			if( in!=null )
			{
				in.close();
			}
			if( out!=null )
			{
				out.close();
			}
			return false;
		}

		BufferedInputStream bis = new BufferedInputStream(in);
		BufferedOutputStream bos = new BufferedOutputStream(out);

		final int bufferLength = 1024;
		byte[] buffer = new byte[bufferLength];
		int len;
		while( (len=bis.read(buffer,0,bufferLength))!=-1 )
		{
			bos.write( buffer, 0, len );
		}


		// close I/O streams
		bis.close();
		bos.close();		
		
		return true;	
	}



	/**
	 * Copy file from f1 to f2.
	 * @param f1
	 * @param f2
	 * @return true:success, false:failure
	 */
	public static boolean copyBinaryFile( final String f1, final String f2 )
		throws IOException
	{
		if( f1==null || f2==null )
		{
			return false;
		}
		return copyBinaryFile( new File(f1), new File(f2) );
	}



	/**
	 * Returns a DOMImplementation instance.
	 * @return
	 */
	public static DOMImplementation getDOMImplementation()
	{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = null;
		try
		{
			builder = factory.newDocumentBuilder();
		}
		catch( ParserConfigurationException ex )
		{
			return null;
		}
		DOMImplementation domImpl = builder.getDOMImplementation();

		return domImpl;
	}



	/**
	 * Find files with the given name.
	 * @param baseDir - base directory to start to search
	 * @param name - the file name to search
	 * @param list - a list to add the found files
	 */
	public static void findFiles(
		final File baseDir, final String name, final ArrayList list )
	{
		if( baseDir.isDirectory() == false )
		{
			return;
		}

		File[] fArray = baseDir.listFiles();
		for( int ii=0; ii<fArray.length; ii++ )
		{
			if( fArray[ii].isDirectory() )
			{
				findFiles( fArray[ii], name, list );
			}
			else
			{
				String name_ = fArray[ii].getName();
				if( name_.equals(name) )
				{
					list.add( fArray[ii].getAbsolutePath() );
				}
			}
		}
		
	}

	/**
	 * Check whether one version is released later than the other version.
	 * @param m1
	 * @param m2
	 * @param m3
	 * @param n1
	 * @param n2
	 * @param n3
	 * @return	whether the version n is released later than version m
	 */
	public static boolean compareVersionNumber(
		final int m1, final int m2, final int m3,
		final int n1, final int n2, final int n3 )
	{
		boolean b;
		if( m1 < n1 )
		{
			b = true;
		}
		else if( m1 == n1 )
		{
			if( m2 < n2 )
			{
				b = true;
			}
			else if( m2 == n2 )
			{
				b = ( m3 < n3 );
			}
			else
			{
				b = false;
			}
		}
		else
		{
			b = false;
		}

		return b;
	}



	public static final void showDataFileInvalidMessageDialog( final Window owner )
	{
		SGUtility.showErrorMessageDialog(
			owner,
			MSG_DATA_FILE_INVALID,
			TITLE_ERROR
		);
	}

	public static final void showDataTypeInvalidMessageDialog( final Window owner )
	{
		SGUtility.showErrorMessageDialog(
			owner,
			MSG_DATA_TYPE_INVALID,
			TITLE_ERROR
		);
	}

}

