// Copyright 1997 The Open Group Research Institute.  All rights reserved.

package krb5.lib;

import krb5.lib.asn1.*;
import java.util.Vector;

/**
 * Encrypted AP response part
 */
public class EncAPRepPart {

	/**
	 * Time
	 */
	public KerberosTime ctime;

	/**
	 * CU sec
	 */
	public int cusec;

	/**
	 * Subject key
	 */
	public EncryptionKey subKey; //optional

	/**
	 * Sequence number
	 */
	public Integer seqNumber; //optional

	/**
	 * Class constructor
	 *
	 * @param new_ctime is of type KerberosTime
	 * @param new_cusec is of type int
	 * @param new_subKey is of type EncryptionKey
	 * @param new_seqNumber is of type Integer
	 * @see krb5.lib.KerberosTime
	 * @see krb5.lib.EncryptionKey
	 */
	public EncAPRepPart(
		KerberosTime new_ctime,
		int new_cusec,
		EncryptionKey new_subKey,
		Integer new_seqNumber
	) {
		ctime = new_ctime;
		cusec = new_cusec;
		subKey = new_subKey;
		seqNumber = new_seqNumber;
	}

	/**
	 * Class constructor
	 *
	 * @param data is of type byte[]
	 * @exception Asn1Exception an exception
	 * @exception BitStringException an exception
	 * @exception RealmException an exception
	 * @exception KrbApErrException an exception
	 * @see krb5.lib.Asn1Exception
	 * @see krb5.lib.BitStringException
	 * @see krb5.lib.RealmException
	 * @see krb5.lib.KrbApErrException
	 */
	public EncAPRepPart(byte[] data)
		throws Asn1Exception, BitStringException, RealmException,
		KrbApErrException {
		this(new EncodeRef(data));
	}

	/**
	 * Class constructor
	 *
	 * @param ref is of type EncodeRef
	 * @exception Asn1Exception an exception
	 * @exception BitStringException an exception
	 * @exception RealmException an exception
	 * @exception KrbApErrException an exception
	 * @see krb5.lib.asn1.EncodeRef
	 * @see krb5.lib.Asn1Exception
	 * @see krb5.lib.BitStringException
	 * @see krb5.lib.RealmException
	 * @see krb5.lib.KrbApErrException
	 */
	public EncAPRepPart(EncodeRef ref)
		throws Asn1Exception, BitStringException, RealmException,
		KrbApErrException {
		if (decode.TagApp(ref) != Krb5.KRB_ENC_AP_REP_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) {
			ctime = new KerberosTime(subRef.startOfData());
			subRef.next();
		}
		else
			throw new Asn1Exception(Krb5.ASN1_BAD_ID);

		if (decode.Tag(subRef) == 1) {
			cusec = decode.Integer(subRef.startOfData());
			subRef.next();
		}
		else
			throw new Asn1Exception(Krb5.ASN1_BAD_ID);

		if (subRef.isMoreInSequence() && decode.Tag(subRef) == 2) {
			subKey = new EncryptionKey(subRef.startOfData());
			subRef.next();
		}

		if (subRef.isMoreInSequence() && decode.Tag(subRef) == 3) {
			seqNumber = new Integer(decode.Integer(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 tempEncAPRepPart = new Vector();

		tempEncAPRepPart.addElement(
			encode.prependExplicitTag(0, ctime.asn1Encode()));
		tempEncAPRepPart.addElement(
			encode.prependExplicitTag(1, encode.Integer(cusec)));

		if (subKey != null)
			tempEncAPRepPart.addElement(
				encode.prependExplicitTag(2, subKey.asn1Encode()));

		if (seqNumber != null)
			tempEncAPRepPart.addElement(
				encode.prependExplicitTag(3, encode.Integer(seqNumber.intValue())));

		byte[][] enc_ap_rep_part = new byte[tempEncAPRepPart.size()][];
		for (int i = 0; i < tempEncAPRepPart.size(); i++)
			enc_ap_rep_part[i] = (byte[])(tempEncAPRepPart.elementAt(i));

		return encode.prependExplicitTag(asn1Class.APPLICATION,
			Krb5.KRB_ENC_AP_REP_PART, encode.Sequence(enc_ap_rep_part));
	}

}