package org.bouncycastle.openpgp;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;

import org.bouncycastle.bcpg.BCPGOutputStream;
import org.bouncycastle.bcpg.PacketTags;

/**
 * Class for producing literal data packets.
 */
public class PGPLiteralDataGenerator 
{	
	public static final char	BINARY = PGPLiteralData.BINARY;
	public static final char	TEXT = PGPLiteralData.TEXT;
	
	/**
	 * The special name indicating a "for your eyes only" packet.
	 */
	public static final String	CONSOLE = PGPLiteralData.CONSOLE;
	
	/**
	 * The special time for a modification time of "now" or
	 * the present time.
	 */
	public static final Date		NOW = PGPLiteralData.NOW;
	
	private BCPGOutputStream			pkOut;
	private boolean							oldFormat = false;
	
	public PGPLiteralDataGenerator()
	{		
	}
	
	/**
	 * Generates literal data objects in the old format, this is
	 * important if you need compatability with  PGP 2.6.x.
	 * 
	 * @param oldFormat
	 */
	public PGPLiteralDataGenerator(
		boolean	oldFormat)
	{
		this.oldFormat = oldFormat;
	}
	
	/**
	 * Open a literal data packet, returning a stream to store the data inside
	 * the packet.
	 * 
	 * @param out the stream we want the packet in
	 * @param format the format we are using
	 * @param name the name of the "file"
	 * @param length the length of the data we will write
	 * @param modificationTime the time of last modification we want stored.
	 */
	public OutputStream open(
		OutputStream	out,
		char					format,
		String				name,
		long					length,
		Date					modificationTime)
		throws IOException
	{
		pkOut = new BCPGOutputStream(out, PacketTags.LITERAL_DATA, length + 2 + name.length() + 4, oldFormat);
		pkOut.write(format);
		pkOut.write((byte)name.length());

		for (int i = 0; i != name.length(); i++)
		{
			pkOut.write(name.charAt(i));
		}

		long	modDate = modificationTime.getTime() / 1000;

		pkOut.write((byte)(modDate >> 24));
		pkOut.write((byte)(modDate >> 16));
		pkOut.write((byte)(modDate >> 8));
		pkOut.write((byte)(modDate));

		return pkOut;
	}
	
	/**
	 * Open a literal data packet for the passed in File object, returning
	 * an output stream for saving the file contents.
	 * 
	 * @param out
	 * @param format
	 * @param file
	 * @return OutputStream
	 * @throws IOException
	 */
	public OutputStream open(
		OutputStream	out,
		char					format,
		File					file)
		throws IOException
	{
		String	name = file.getName();
		
		pkOut = new BCPGOutputStream(out, PacketTags.LITERAL_DATA, file.length() + 2 + name.length() + 4, oldFormat);
		pkOut.write(format);
		pkOut.write((byte)name.length());

		for (int i = 0; i != name.length(); i++)
		{
			pkOut.write(name.charAt(i));
		}

		long	modDate = file.lastModified() / 1000;

		pkOut.write((byte)(modDate >> 24));
		pkOut.write((byte)(modDate >> 16));
		pkOut.write((byte)(modDate >> 8));
		pkOut.write((byte)(modDate));

		return pkOut;
	}
	
	/**
	 * Close the literal data packet.
	 * 
	 * @throws IOException
	 */
	public void close()
		throws IOException
	{
		pkOut.flush();
	}
}
