package lu.tudor.santec.gecamed.core.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

import org.apache.log4j.Level;
import org.mozilla.universalchardet.UniversalDetector;

public class AutoEncodingFileReader
{
	/* ======================================== */
	// 		MEMBERS
	/* ======================================== */
	
	/** the logger Object for this class */
	private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(AutoEncodingFileReader.class.getName());
	
	private static String lastUsedFormat;
	
	
	private File 		file;
	
	private InputStream is;
	
	
	
	/* ======================================== */
	// 		CONSTRUCTORS
	/* ======================================== */
	
	public AutoEncodingFileReader (File file)
	{
		setFile(file);
	}
	
	
	
	/* ======================================== */
	// 		CLASS BODY
	/* ======================================== */
	
	public void setFile (File file)
	{
		this.file = file;
	}
	
	
	public File getFile ()
	{
		return file;
	}
	
	
	public InputStreamReader read (File file) throws IOException
	{
		setFile(file);
		return read();
	}
	
	
	public InputStreamReader read (File file, String encoding) throws IOException
	{
		setFile(file);
		return read(encoding);
	}
	
	
	public InputStreamReader read () throws IOException
	{
		InputStreamReader reader;
		
		if (lastUsedFormat == null)
			lastUsedFormat 	= detectCharset();
		
		try 
		{
			reader 			= read (lastUsedFormat);
		}
		catch (Exception e) 
		{
			lastUsedFormat 	= detectCharset();
			reader 			= read(lastUsedFormat);
		}
		
		return reader;
	}
	
	
	public InputStreamReader read (String encoding) throws IOException
	{
		InputStreamReader 	reader;
		
		try 
		{
			closeStream();
			is 		= new FileInputStream(file);
			reader 	= new InputStreamReader(is, Charset.forName(encoding));
		}
		catch (IOException e) 
		{
			throw e;
		}
		
		return reader;
	}
	
	
	public String detectCharset () throws IOException
	{
		InputStream 		is = null;
		UniversalDetector 	detector;
		int 				read;
		byte[] 				bytes = new byte[4096];
		String 				detectedCharset;
		
		try
		{
			is 				= new FileInputStream(file);
			detector 		= new UniversalDetector(null);
			
			while ((read = is.read(bytes)) > 0 && !detector.isDone())
			{
				detector.handleData(bytes, 0, read);
			}
			detector.dataEnd();
			
			detectedCharset = detector.getDetectedCharset();
			if (detectedCharset == null)
				 return "UTF8";
			else if (Charset.isSupported(detectedCharset))
				 return detectedCharset;
			else throw new IOException("The detected encoding \""+detectedCharset+"\" is NOT supported.");
		}
		catch (IOException e)
		{
			throw e;
		}
		finally 
		{
			if (is != null)
				is.close();
		}
	}
	
	
	public void closeStream ()
	{
		if (is != null)
		{
			try 
			{
				is.close();
			}
			catch (IOException e) 
			{
				logger.log(Level.WARN, "Unable to close stream.", e);
			}
		}
	}
}
