using System;
using System.Collections;

using Org.BouncyCastle.Asn1;

namespace Org.BouncyCastle.Asn1.X509
{
    /**
     * Implementation of <code>IetfAttrSyntax</code> as specified by RFC3281.
     */
    public class IetfAttrSyntax
        : Asn1Encodable
    {
        public const int ValueOctets	= 1;
        public const int ValueOid		= 2;
        public const int ValueUtf8		= 3;

		internal readonly GeneralNames	policyAuthority;
        internal readonly Asn1EncodableVector values = new Asn1EncodableVector();

		internal int valueChoice = -1;

		/**
         *
         */
        public IetfAttrSyntax(
			Asn1Sequence seq)
        {
            int i = 0;

            if (seq[0] is Asn1TaggedObject)
            {
                policyAuthority = GeneralNames.GetInstance(((Asn1TaggedObject)seq[0]), false);
                i++;
            }
            else if (seq.Count == 2)
            { // VOMS fix
                policyAuthority = GeneralNames.GetInstance(seq[0]);
                i++;
            }

			if (!(seq[i] is Asn1Sequence))
            {
                throw new ArgumentException("Non-IetfAttrSyntax encoding");
            }

			seq = (Asn1Sequence) seq[i];

			foreach (Asn1Object obj in seq)
			{
                int type;

                if (obj is DerObjectIdentifier)
                {
                    type = ValueOid;
                }
                else if (obj is DerUtf8String)
                {
                    type = ValueUtf8;
                }
                else if (obj is DerOctetString)
                {
                    type = ValueOctets;
                }
                else
                {
                    throw new ArgumentException("Bad value type encoding IetfAttrSyntax");
                }

				if (valueChoice < 0)
                {
                    valueChoice = type;
                }

				if (type != valueChoice)
                {
                    throw new ArgumentException("Mix of value types in IetfAttrSyntax");
                }

				values.Add(obj);
            }
        }

		public GeneralNames PolicyAuthority
		{
			get { return policyAuthority; }
		}

		public int ValueType
		{
			get { return valueChoice; }
		}

		public object[] GetValues()
        {
            if (this.ValueType == ValueOctets)
            {
                Asn1OctetString[] tmp = new Asn1OctetString[values.Count];

				for (int i = 0; i != tmp.Length; i++)
                {
                    tmp[i] = (Asn1OctetString) values[i];
                }

				return tmp;
            }

			if (this.ValueType == ValueOid)
            {
                DerObjectIdentifier[] tmp = new DerObjectIdentifier[values.Count];

                for (int i = 0; i != tmp.Length; i++)
                {
                    tmp[i] = (DerObjectIdentifier) values[i];
                }

				return tmp;
            }

			{
				DerUtf8String[] tmp = new DerUtf8String[values.Count];

				for (int i = 0; i != tmp.Length; i++)
				{
					tmp[i] = (DerUtf8String) values[i];
				}

				return tmp;
			}
        }

		/**
         *
         * <pre>
         *
         *  IetfAttrSyntax ::= Sequence {
         *    policyAuthority [0] GeneralNames OPTIONAL,
         *    values Sequence OF CHOICE {
         *      octets OCTET STRING,
         *      oid OBJECT IDENTIFIER,
         *      string UTF8String
         *    }
         *  }
         *
         * </pre>
         */
        public override Asn1Object ToAsn1Object()
        {
            Asn1EncodableVector v = new Asn1EncodableVector();

			if (policyAuthority != null)
            {
                v.Add(new DerTaggedObject(0, policyAuthority));
            }

			v.Add(new DerSequence(values));

			return new DerSequence(v);
        }
    }
}
