text: ﻿using System;
  
  namespace Raksha.Asn1.Cmp
  {
      public class PkiMessage
          : Asn1Encodable
      {
          private readonly PkiHeader header;
          private readonly PkiBody body;
          private readonly DerBitString protection;
          private readonly Asn1Sequence extraCerts;
  
          private PkiMessage(Asn1Sequence seq)
          {
              header = PkiHeader.GetInstance(seq[0]);
              body = PkiBody.GetInstance(seq[1]);
  
              for (int pos = 2; pos < seq.Count; ++pos)
              {
                  Asn1TaggedObject tObj = (Asn1TaggedObject)seq[pos].ToAsn1Object();
  
                  if (tObj.TagNo == 0)
                  {
                      protection = DerBitString.GetInstance(tObj, true);
                  }
                  else
                  {
                      extraCerts = Asn1Sequence.GetInstance(tObj, true);
                  }
              }
          }
  
          public static PkiMessage GetInstance(object obj)
          {
              if (obj is PkiMessage)
                  return (PkiMessage)obj;
  
              if (obj != null)
                  return new PkiMessage(Asn1Sequence.GetInstance(obj));
  
              return null;
          }
  
          /**
           * Creates a new PkiMessage.
           *
           * @param header message header
           * @param body message body
           * @param protection message protection (may be null)
           * @param extraCerts extra certificates (may be null)
           */
          public PkiMessage(
              PkiHeader header,
              PkiBody body,
              DerBitString protection,
              CmpCertificate[] extraCerts)
          {
              this.header = header;
              this.body = body;
              this.protection = protection;
              if (extraCerts != null)
              {
                  this.extraCerts = new DerSequence(extraCerts);
              }
          }
  
          public PkiMessage(
              PkiHeader header,
              PkiBody body,
              DerBitString protection)
              : this(header, body, protection, null)
          {
          }
  
          public PkiMessage(
              PkiHeader header,
              PkiBody body)
              : this(header, body, null, null)
          {
          }
  
          public virtual PkiHeader Header
          {
              get { return header; }
          }
  
          public virtual PkiBody Body
          {
              get { return body; }
          }
  
          public virtual DerBitString Protection
          {
              get { return protection; }
          }
  
          public virtual CmpCertificate[] GetExtraCerts()
          {
              if (extraCerts == null)
                  return null;
  
              CmpCertificate[] results = new CmpCertificate[extraCerts.Count];
              for (int i = 0; i < results.Length; ++i)
              {
                  results[i] = CmpCertificate.GetInstance(extraCerts[i]);
              }
              return results;
          }
  
          /**
           * <pre>
           * PkiMessage ::= SEQUENCE {
           *                  header           PKIHeader,
           *                  body             PKIBody,
           *                  protection   [0] PKIProtection OPTIONAL,
           *                  extraCerts   [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
           *                                                                     OPTIONAL
           * }
           * </pre>
           * @return a basic ASN.1 object representation.
           */
          public override Asn1Object ToAsn1Object()
          {
              Asn1EncodableVector v = new Asn1EncodableVector(header, body);
  
              AddOptional(v, 0, protection);
              AddOptional(v, 1, extraCerts);
  
              return new DerSequence(v);
          }
  
          private static void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
          {
              if (obj != null)
              {
                  v.Add(new DerTaggedObject(true, tagNo, obj));
              }
          }
      }
  }
  