package org.bouncycastle.openpgp;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;

import org.bouncycastle.bcpg.*;

/**
 * Holder for a collection of PGP secret keys.
 */
public class PGPSecretKeyRing
{	
	ArrayList			keys = new ArrayList();
	
	public PGPSecretKeyRing(
		byte[]	encoding)
		throws IOException, PGPException
	{
		this(new ByteArrayInputStream(encoding));
	}
	
	public PGPSecretKeyRing(
		InputStream	in)
		throws IOException, PGPException
	{
		BCPGInputStream	pIn;
		
		if (in instanceof BCPGInputStream)
		{
			pIn = (BCPGInputStream)in;
		}
		else
		{
			pIn = new BCPGInputStream(in);
		}
		
		SecretKeyPacket	secret = (SecretKeyPacket)pIn.readPacket();
		ArrayList			ids = new ArrayList();
		ArrayList			idSigs = new ArrayList();
		MessageDigest 	sha;
		
		try
		{
			sha = MessageDigest.getInstance("SHA1");
		}
		catch (NoSuchAlgorithmException e)
		{
			throw new IOException("can't find SHA1 digest");
		}
		
		while (pIn.nextPacketTag() == PacketTags.USER_ID)
		{
			UserIDPacket	id = (UserIDPacket)pIn.readPacket();
			ArrayList				sigList = new ArrayList();
			
			ids.add(id.getID());
			idSigs.add(sigList);
			
			while (pIn.nextPacketTag() == PacketTags.SIGNATURE)
			{
				sigList.add(new PGPSignature((SignaturePacket)pIn.readPacket()));
			}
		}
		
		keys.add(new PGPSecretKey(secret, sha, ids, idSigs));
		
		while (pIn.nextPacketTag() == PacketTags.SECRET_SUBKEY)
		{
			SecretSubkeyPacket	sub = (SecretSubkeyPacket)pIn.readPacket();
			ArrayList					subIds = new ArrayList();
			ArrayList					subIdSigs = new ArrayList();
			
			while (pIn.nextPacketTag() == PacketTags.USER_ID)
			{
				UserIDPacket	id = (UserIDPacket)pIn.readPacket();
				ArrayList				sigList = new ArrayList();
				
				ids.add(id.getID());
				idSigs.add(sigList);
				
				while (pIn.nextPacketTag() == PacketTags.SIGNATURE)
				{
					sigList.add(new PGPSignature((SignaturePacket)pIn.readPacket()));
				}
			}
			
			keys.add(new PGPSecretKey(sub, sha, subIds, subIdSigs));
		}
	}
	

	/**
	 * Return the public key for the master key.
	 * 
	 * @return PGPPublicKey
	 */
	public PGPPublicKey getPublicKey()
	{
		return ((PGPSecretKey)keys.get(0)).getPublicKey();
	}

	/**
	 * Return the master private key.
	 * 
	 * @return PGPSecretKey
	 */
	public PGPSecretKey getSecretKey()
	{
		return ((PGPSecretKey)keys.get(0));
	}
	
	public PGPSecretKey getSecretKey(
		long		keyId)
	{	
		for (int i = 0; i != keys.size(); i++)
		{
			PGPSecretKey	k = (PGPSecretKey)keys.get(i);
			
			if (keyId == k.getKeyID())
			{
				return k;
			}
		}
	
		return null;
	}
	
	public byte[] getEncoded() 
		throws IOException
	{
		ByteArrayOutputStream	bOut = new ByteArrayOutputStream();
		
		this.encode(bOut);
		
		return bOut.toByteArray();
	}
	
	public void encode(
		OutputStream	outStream) 
		throws IOException
	{
		for (int i = 0; i != keys.size(); i++)
		{
			PGPSecretKey	k = (PGPSecretKey)keys.get(i);
			
			k.encode(outStream);
		}
	}
}
