// Copyright 1997 The Open Group Research Institute.  All rights reserved.

package krb5.lib;

import krb5.lib.asn1.*;
import java.util.Vector;

/**
 * KRB safe body
 */
public class KRBSafeBody {

	/**
	 * User data
	 */
	public byte[] userData;

	/**
	 * Timestamp
	 */
	public KerberosTime timestamp; //optional

	/**
	 * Usec
	 */
	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 KRBSafeBody(
		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 ref is of type EncodeRef
	 * @exception Asn1Exception an exception
	 * @see krb5.lib.asn1.EncodeRef
	 * @see krb5.lib.Asn1Exception
	 */
	public KRBSafeBody(EncodeRef ref) throws Asn1Exception {
		EncodeRef subRef = decode.Sequence(ref);

		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 tempKRBSafeBody = new Vector();

		tempKRBSafeBody.addElement(
			encode.prependExplicitTag(0,
				encode.OctetString(userData)));

		if (timestamp != null)
			tempKRBSafeBody.addElement(
				encode.prependExplicitTag(1,
					timestamp.asn1Encode()));
		if (usec != null)
			tempKRBSafeBody.addElement(
				encode.prependExplicitTag(2,
					encode.Integer(usec.intValue())));
		if (seqNumber != null)
			tempKRBSafeBody.addElement(
				encode.prependExplicitTag(3,
					encode.Integer(seqNumber.intValue())));
		
		if (sAddress != null)
			tempKRBSafeBody.addElement(
				encode.prependExplicitTag(4, sAddress.asn1Encode()));
		
		if (rAddress != null)
			tempKRBSafeBody.addElement(
				encode.prependExplicitTag(5, rAddress.asn1Encode()));

		byte[][] krb_safe_body = new byte[tempKRBSafeBody.size()][];
		for (int i = 0; i < tempKRBSafeBody.size(); i++)
			krb_safe_body[i] = (byte[])(tempKRBSafeBody.elementAt(i));
		return encode.Sequence(krb_safe_body);
	}

}