// Copyright 1997 The Open Group Research Institute.  All rights reserved.

package krb5.lib;

import krb5.lib.asn1.*;
import java.util.Vector;

/**
 * Encrypted KRC credential part
 */
public class EncKrbCredPart {

	/**
	 * Ticket informations
	 */
	public KrbCredInfo[] ticketInfo;

	/**
	 * Nounce
	 */
	public Integer nonce; //optional

	/**
	 * Timestamp
	 */
	public KerberosTime timestamp; //optional

	/**
	 * UseC
	 */
	public Integer usec; //optional

	/**
	 * Address
	 */
	public HostAddress sAddress; //optional

	/**
	 * Remote addresses
	 */
	public HostAddresses rAddress; //optional

	/**
	 * Class constructor
	 *
	 * @param new_ticketInfo is of type KrbCredInfo[]
	 * @param new_timestamp is of type KerberosTime
	 * @param new_usec is of type Integer
	 * @param new_nonce is of type Integer
	 * @param new_sAddress is of type HostAddress
	 * @param new_rAddress is of type HostAddresses
	 * @see krb5.lib.KrbCredInfo
	 * @see krb5.lib.KerberosTime
	 * @see krb5.lib.HostAddress
	 * @see krb5.lib.HostAddresses
	 */
	public EncKrbCredPart(
		KrbCredInfo[] new_ticketInfo,
		KerberosTime new_timestamp,
		Integer new_usec,
		Integer new_nonce,
		HostAddress new_sAddress,
		HostAddresses new_rAddress
	) {
		ticketInfo = new_ticketInfo;
		nonce = new_nonce;
		timestamp = new_timestamp;
		usec = new_usec;
		sAddress = new_sAddress;
		rAddress = new_rAddress;
	}

	/**
	 * Class constructor
	 *
	 * @param data is of type byte[]
	 * @exception Asn1Exception an exception
	 * @exception BitStringException an exception
	 * @exception RealmException an exception
	 * @see krb5.lib.Asn1Exception
	 * @see krb5.lib.BitStringException
	 * @see krb5.lib.RealmException
	 */
	public EncKrbCredPart(byte[] data) throws Asn1Exception,
		BitStringException, RealmException {
		this(new EncodeRef(data));
	}

	/**
	 * Class constructor
	 *
	 * @param ref is of type EncodeRef
	 * @exception Asn1Exception an exception
	 * @exception BitStringException an exception
	 * @exception RealmException an exception
	 * @see krb5.lib.asn1.EncodeRef
	 * @see krb5.lib.Asn1Exception
	 * @see krb5.lib.BitStringException
	 * @see krb5.lib.RealmException
	 */
	public EncKrbCredPart(EncodeRef ref) throws Asn1Exception,
		BitStringException, RealmException {
		if (decode.TagApp(ref) != Krb5.KRB_ENC_KRB_CRED_PART)
			//XXX may not be the correct error code for a tag
			//mismatch on an encrypted structure
			throw new Asn1Exception(Krb5.ASN1_BAD_ID);
		EncodeRef subRef = decode.Sequence(ref.startOfData());

		if (decode.Tag(subRef) == 0) {
			Vector tempKrbCredInfo = new Vector();
			EncodeRef subSubRef = decode.Sequence(subRef);
			while (subSubRef.isMoreInSequence()) {
				tempKrbCredInfo.addElement(new KrbCredInfo(subSubRef));
				subSubRef.next();
			}
			if (tempKrbCredInfo.size() > 0) {
				ticketInfo = new KrbCredInfo[tempKrbCredInfo.size()];
				tempKrbCredInfo.copyInto(ticketInfo);
			}
			subRef.next();
		}
		else
			throw new Asn1Exception(Krb5.ASN1_BAD_ID);

		if (subRef.isMoreInSequence() && decode.Tag(subRef) == 1) {
			nonce = new Integer(decode.Integer(subRef.startOfData()));
			subRef.next();
		}

		if (subRef.isMoreInSequence() && decode.Tag(subRef) == 2) {
			timestamp = new KerberosTime(subRef.startOfData());
			subRef.next();
		}

		if (subRef.isMoreInSequence() && decode.Tag(subRef) == 3) {
			usec = new Integer(decode.Integer(subRef.startOfData()));
			subRef.next();
		}

		if (subRef.isMoreInSequence() && decode.Tag(subRef) == 4) {
			sAddress = new HostAddress(subRef.startOfData());
			subRef.next();
		}

		if (subRef.isMoreInSequence() && decode.Tag(subRef) == 5) {
			rAddress = new HostAddresses(subRef.startOfData());
			subRef.next();
		}

		if (subRef.isMoreInSequence())
			throw new Asn1Exception(Krb5.ASN1_BAD_ID);
	}

	/**
	 * Encodes the object in asn1
	 *
	 * @return byte[] is a result
	 * @exception Asn1Exception an exception
	 * @exception BitStringException an exception
	 * @see krb5.lib.Asn1Exception
	 * @see krb5.lib.BitStringException
	 */
	public byte[] asn1Encode() throws Asn1Exception,
		BitStringException {
		Vector tempEncKrbCredPart = new Vector();

		byte[][] ticket_info = new byte[ticketInfo.length][];
		for (int i = 0; i < ticketInfo.length; i++)
			ticket_info[i] = ticketInfo[i].asn1Encode();
		tempEncKrbCredPart.addElement(
			encode.prependExplicitTag(0,
				encode.Sequence(ticket_info)));

		if (nonce != null)
			tempEncKrbCredPart.addElement(
				encode.prependExplicitTag(1,
					encode.Integer(nonce.intValue())));
		if (timestamp != null)
			tempEncKrbCredPart.addElement(
				encode.prependExplicitTag(2,
					timestamp.asn1Encode()));
		if (usec != null)
			tempEncKrbCredPart.addElement(
				encode.prependExplicitTag(3,
					encode.Integer(usec.intValue())));
		
		if (sAddress != null)
			tempEncKrbCredPart.addElement(
				encode.prependExplicitTag(4, sAddress.asn1Encode()));
			
		if (rAddress != null)
			tempEncKrbCredPart.addElement(
				encode.prependExplicitTag(5, rAddress.asn1Encode()));

		byte[][] enc_krb_cred_part = new byte[tempEncKrbCredPart.size()][];
		for (int i = 0; i < tempEncKrbCredPart.size(); i++)
			enc_krb_cred_part[i] = (byte[])(tempEncKrbCredPart.elementAt(i));

		return encode.prependExplicitTag(asn1Class.APPLICATION,
			Krb5.KRB_ENC_KRB_CRED_PART, encode.Sequence(enc_krb_cred_part));
	}

}