// Copyright 1997 The Open Group Research Institute.  All rights reserved.

package krb5.lib;

import krb5.lib.asn1.*;
import java.util.Vector;

/**
 * Encrypted Kerberos private part
 */
public class EncKrbPrivPart {

	/**
	 * User data
	 */
	public byte[] userData;

	/**
	 * Timestamp
	 */
	public KerberosTime timestamp; //optional

	/**
	 * U sec
	 */
	public Integer usec; //optional

	/**
	 * Sequence number
	 */
	public Integer seqNumber; //optional

	/**
	 * Address
	 */
	public HostAddress sAddress; //optional

	/**
	 * Remote address
	 */
	public HostAddress rAddress; //optional

	/**
	 * Class constructor
	 *
	 * @param new_userData is of type byte[]
	 * @param new_timestamp is of type KerberosTime
	 * @param new_usec is of type Integer
	 * @param new_seqNumber is of type Integer
	 * @param new_sAddress is of type HostAddress
	 * @param new_rAddress is of type HostAddress
	 * @see krb5.lib.KerberosTime
	 * @see krb5.lib.HostAddress
	 */
	public EncKrbPrivPart(
		byte[] new_userData,
		KerberosTime new_timestamp,
		Integer new_usec,
		Integer new_seqNumber,
		HostAddress new_sAddress,
		HostAddress new_rAddress
	) {
		userData = new_userData;
		timestamp = new_timestamp;
		usec = new_usec;
		seqNumber = new_seqNumber;
		sAddress = new_sAddress;
		rAddress = new_rAddress;
	}

	/**
	 * Class constructor
	 *
	 * @param data is of type byte[]
	 * @exception Asn1Exception an exception
	 * @see krb5.lib.Asn1Exception
	 */
	public EncKrbPrivPart(byte[] data) throws Asn1Exception {
		this(new EncodeRef(data));
	}

	/**
	 * Class constructor
	 *
	 * @param ref is of type EncodeRef
	 * @exception Asn1Exception an exception
	 * @see krb5.lib.asn1.EncodeRef
	 * @see krb5.lib.Asn1Exception
	 */
	public EncKrbPrivPart(EncodeRef ref) throws Asn1Exception {
		if (decode.TagApp(ref) != Krb5.KRB_ENC_KRB_PRIV_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) {
			userData = decode.OctetString(subRef.startOfData());
			subRef.next();
		}
		else
			throw new Asn1Exception(Krb5.ASN1_BAD_ID);

		if (subRef.isMoreInSequence() && decode.Tag(subRef) == 1) {
			timestamp = new KerberosTime(subRef.startOfData());
			subRef.next();
		}

		if (subRef.isMoreInSequence() && decode.Tag(subRef) == 2) {
			usec = new Integer(decode.Integer(subRef.startOfData()));
			subRef.next();
		}

		if (subRef.isMoreInSequence() && decode.Tag(subRef) == 3) {
			seqNumber = 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 HostAddress(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
	 * @see krb5.lib.Asn1Exception
	 */
	public byte[] asn1Encode() throws Asn1Exception {
		Vector tempEncKrbPrivPart = new Vector();

		tempEncKrbPrivPart.addElement(
			encode.prependExplicitTag(0,
				encode.OctetString(userData)));

		if (timestamp != null)
			tempEncKrbPrivPart.addElement(
				encode.prependExplicitTag(1,
					timestamp.asn1Encode()));
		if (usec != null)
			tempEncKrbPrivPart.addElement(
				encode.prependExplicitTag(2,
					encode.Integer(usec.intValue())));
		if (seqNumber != null)
			tempEncKrbPrivPart.addElement(
				encode.prependExplicitTag(3,
					encode.Integer(seqNumber.intValue())));
		
		if (sAddress != null)
			tempEncKrbPrivPart.addElement(
				encode.prependExplicitTag(4, sAddress.asn1Encode()));
		
		if (rAddress != null)
			tempEncKrbPrivPart.addElement(
				encode.prependExplicitTag(5, rAddress.asn1Encode()));

		byte[][] enc_krb_priv_part = new byte[tempEncKrbPrivPart.size()][];
		for (int i = 0; i < tempEncKrbPrivPart.size(); i++)
			enc_krb_priv_part[i] = (byte[])(tempEncKrbPrivPart.elementAt(i));

		return encode.prependExplicitTag(asn1Class.APPLICATION,
			Krb5.KRB_ENC_KRB_PRIV_PART, encode.Sequence(enc_krb_priv_part));
	}

}