/**
 * 
 */
package at.gv.egiz.pdfas.impl.input;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import at.gv.egiz.pdfas.framework.input.PdfDataSource;
import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper;

/**
 * @author wprinz
 * 
 */
public class FileBasedPdfDataSourceImpl implements PdfDataSource, FileBased
{
  /**
   * The log.
   */
  private static final Log log = LogFactory.getLog(FileBasedPdfDataSourceImpl.class);

  /**
   * The underlying file.
   */
  protected File inputFile = null;

  protected int length = -1;

  /**
   * Constructor that creates this PdfDataSource backed by a file in the file
   * system.
   * 
   * @param file
   *          The input File.
   * @param length
   *          The length of the InputStream. The is the maximum number of bytes
   *          that can be read from the stream.
   * @throws IOException
   *           Thrown if the file cannot be read properly.
   */
  public FileBasedPdfDataSourceImpl(File file, int length) throws IOException
  {

    if (!file.exists())
    {
      throw new FileNotFoundException("The file '" + file + "' does not exist.");
    }
    // for some reason the isFile is not always correct...
    // if (file.isFile())
    // {
    // throw new IOException("The file '" + file + "' is not a normal file.");
    // }
    if (!file.canRead())
    {
      throw new IOException("The file '" + file + "' cannot be read.");
    }

    this.inputFile = file;
    this.length = length;
  }

  /**
   * @see at.gv.egiz.pdfas.impl.input.FileBased#getFile()
   */
  public File getFile()
  {
    return this.inputFile;
  }

  /**
   * @see at.gv.egiz.pdfas.framework.input.PdfDataSource#createInputStream()
   */
  public InputStream createInputStream()
  {
    if (cache == null)
    {
      getAsByteArray();
    }
    return new ByteArrayInputStream(cache);
  }

  protected InputStream createFileInputStream()
  {
    try
    {
      FileInputStream fis = new FileInputStream(getFile());
      DelimitedInputStream dis = new DelimitedInputStream(fis, getLength());
      return dis;
    }
    catch (IOException e)
    {
      log.error("Couldn't create InputStream for file " + getFile() + ". Returning null.", e);

      return null;
    }
  }
  /**
   * @see at.gv.egiz.pdfas.framework.input.PdfDataSource#getLength()
   */
  public int getLength()
  {
    return this.length;
  }
  
  byte [] cache = null;
  
  /**
   * @see at.gv.egiz.pdfas.framework.input.DataSource#getAsByteArray()
   */
  public byte[] getAsByteArray()
  {
    if (cache != null)
    {
      return cache;
    }
    
    cache = DataSourceHelper.convertInputStreamToByteArray(createFileInputStream());
    
    return cache;
  }

}