package org.bouncycastle.openpgp;

import java.io.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

import org.bouncycastle.bcpg.BCPGOutputStream;

/**
 * Often a PGP key ring file is made up of a succession of master/sub-key key rings.
 * If you want to read an entire secret key file in one hit this is the class for you.
 */
public class PGPSecretKeyRingCollection 
{
	private HashMap	secretRings = new HashMap();
	private ArrayList	order = new ArrayList();
	
	public PGPSecretKeyRingCollection(
		byte[]	encoding)
		throws IOException, PGPException
	{
		this(new ByteArrayInputStream(encoding));
	}
	
	public PGPSecretKeyRingCollection(
		InputStream	in)
		throws IOException, PGPException
	{
		PGPObjectFactory	pgpFact = new PGPObjectFactory(in);
		PGPSecretKeyRing	pgpSecret = null;
		
		while ((pgpSecret = (PGPSecretKeyRing)pgpFact.nextObject()) != null)
		{
			Long						key = new Long(pgpSecret.getPublicKey().getKeyID());
			
			secretRings.put(key, pgpSecret);
			order.add(key);
		}
	}
	
	public PGPSecretKeyRingCollection(
		Collection	collection)
		throws IOException, PGPException
	{
		Iterator					it = collection.iterator();
		
		while (it.hasNext())
		{
			PGPSecretKeyRing	pgpSecret = (PGPSecretKeyRing)it.next();
			Long						key = new Long(pgpSecret.getPublicKey().getKeyID());
			
			secretRings.put(key, pgpSecret);
			order.add(key);
		}
	}
	
	/**
	 * return the secret key rings making up this collection.
	 */
	public Iterator getKeyRings()
	{
		return secretRings.values().iterator();
	}
	
	/**
	 * Return the PGP secret key associated with the given key id.
	 * 
	 * @param keyID
	 * @return the secret key
	 * @throws PGPException
	 */
	public PGPSecretKey getSecretKey(
		long		keyID) 
		throws PGPException
	{	
		Iterator	it = this.getKeyRings();
		
		while (it.hasNext())
		{
			PGPSecretKeyRing	secRing = (PGPSecretKeyRing)it.next();
			PGPSecretKey			sec =secRing.getSecretKey(keyID);
			
			if (sec != null)
			{
				return sec;
			}
		}
	
		return null;
	}
	
	/**
	 * Return the secret key ring which contains the key referred to by keyID.
	 * 
	 * @param keyID
	 * @return the secret key ring
	 * @throws PGPException
	 */
	public PGPSecretKeyRing getSecretKeyRing(
		long	keyID) 
		throws PGPException
	{
		Long	id = new Long(keyID);
		
		if (secretRings.containsKey(id))
		{
			return (PGPSecretKeyRing)secretRings.get(id);
		}
		
		Iterator	it = this.getKeyRings();
		
		while (it.hasNext())
		{
			PGPSecretKeyRing	secretRing = (PGPSecretKeyRing)it.next();
			PGPSecretKey			secret = secretRing.getSecretKey(keyID);
			
			if (secret != null)
			{
				return secretRing;
			}
		}
	
		return null;
	}
	
	public byte[] getEncoded() 
		throws IOException
	{
		ByteArrayOutputStream	bOut = new ByteArrayOutputStream();
		
		this.encode(bOut);
		
		return bOut.toByteArray();
	}
	
	public void encode(
		OutputStream	outStream) 
		throws IOException
	{
		BCPGOutputStream	out;
		
		if (outStream instanceof BCPGOutputStream)
		{
			out = (BCPGOutputStream)outStream;
		}
		else
		{
			out = new BCPGOutputStream(outStream);
		}

		Iterator	it = order.iterator();
		while (it.hasNext())
		{
			PGPSecretKeyRing	sr = (PGPSecretKeyRing)secretRings.get(it.next());
			
			sr.encode(out);
		}
	}
}
