package com.sun.identity.saml2.protocol.impl;

import com.sun.identity.saml2.assertion.AssertionFactory;
import com.sun.identity.saml2.common.SAML2Exception;
import com.sun.identity.saml2.common.SAML2SDKUtils;
import com.sun.identity.saml2.protocol.ArtifactResponse;
import com.sun.identity.saml2.protocol.ProtocolFactory;
import com.sun.identity.shared.DateUtils;
import com.sun.identity.shared.xml.XMLUtils;
import java.text.ParseException;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class ArtifactResponseImpl extends StatusResponseImpl implements ArtifactResponse {
   private String anyString;

   private void parseElement(Element element) throws SAML2Exception {
      if (element == null) {
         if (SAML2SDKUtils.DEBUG.messageEnabled()) {
            SAML2SDKUtils.DEBUG.message("ArtifactResponseImpl.parseElement: element input is null.");
         }

         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("nullInput"));
      } else {
         String tag = element.getLocalName();
         if (tag != null && tag.equals("ArtifactResponse")) {
            NamedNodeMap atts = element.getAttributes();
            if (atts != null) {
               int length = atts.getLength();

               for (int i = 0; i < length; i++) {
                  Attr attr = (Attr)atts.item(i);
                  String attrName = attr.getName();
                  String attrValue = attr.getValue().trim();
                  if (attrName.equals("ID")) {
                     this.responseId = attrValue;
                  } else if (attrName.equals("InResponseTo")) {
                     this.inResponseTo = attrValue;
                  } else if (attrName.equals("Version")) {
                     this.version = attrValue;
                  } else if (attrName.equals("IssueInstant")) {
                     try {
                        this.issueInstant = DateUtils.stringToDate(attrValue);
                     } catch (ParseException pe) {
                        throw new SAML2Exception(pe.getMessage());
                     }
                  } else if (attrName.equals("Destination")) {
                     this.destination = attrValue;
                  } else if (attrName.equals("Consent")) {
                     this.consent = attrValue;
                  }
               }
            }

            NodeList nl = element.getChildNodes();
            int length = nl.getLength();

            for (int i = 0; i < length; i++) {
               Node child = nl.item(i);
               String childName;
               if ((childName = child.getLocalName()) != null) {
                  if (childName.equals("Issuer")) {
                     if (this.issuer != null) {
                        if (SAML2SDKUtils.DEBUG.messageEnabled()) {
                           SAML2SDKUtils.DEBUG.message("ArtifactResponseImpl.parseElement: included more than one Issuer.");
                        }

                        throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("moreElement"));
                     }

                     if (this.signatureString != null || this.extensions != null || this.status != null || this.anyString != null) {
                        if (SAML2SDKUtils.DEBUG.messageEnabled()) {
                           SAML2SDKUtils.DEBUG.message("ArtifactResponseImpl.parseElement:wrong sequence.");
                        }

                        throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("schemaViolation"));
                     }

                     this.issuer = AssertionFactory.getInstance().createIssuer((Element)child);
                  } else if (childName.equals("Signature")) {
                     if (this.signatureString != null) {
                        if (SAML2SDKUtils.DEBUG.messageEnabled()) {
                           SAML2SDKUtils.DEBUG.message("ArtifactResponseImpl.parseElement:included more than one Signature.");
                        }

                        throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("moreElement"));
                     }

                     if (this.extensions != null || this.status != null || this.anyString != null) {
                        if (SAML2SDKUtils.DEBUG.messageEnabled()) {
                           SAML2SDKUtils.DEBUG.message("ArtifactResponseImpl.parseElement:wrong sequence.");
                        }

                        throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("schemaViolation"));
                     }

                     this.signatureString = XMLUtils.print(child);
                     this.isSigned = true;
                  } else if (childName.equals("Extensions")) {
                     if (this.extensions != null) {
                        if (SAML2SDKUtils.DEBUG.messageEnabled()) {
                           SAML2SDKUtils.DEBUG.message("ArtifactResponseImpl.parseElement:included more than one Extensions.");
                        }

                        throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("moreElement"));
                     }

                     if (this.status != null || this.anyString != null) {
                        if (SAML2SDKUtils.DEBUG.messageEnabled()) {
                           SAML2SDKUtils.DEBUG.message("ArtifactResponseImpl.parseElement:wrong sequence.");
                        }

                        throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("schemaViolation"));
                     }

                     this.extensions = ProtocolFactory.getInstance().createExtensions((Element)child);
                  } else if (childName.equals("Status")) {
                     if (this.status != null) {
                        if (SAML2SDKUtils.DEBUG.messageEnabled()) {
                           SAML2SDKUtils.DEBUG.message("ArtifactResponseImpl.parseElement: included more than one Status.");
                        }

                        throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("moreElement"));
                     }

                     if (this.anyString != null) {
                        if (SAML2SDKUtils.DEBUG.messageEnabled()) {
                           SAML2SDKUtils.DEBUG.message("ResponseImpl.parseElement:wrong sequence.");
                        }

                        throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("schemaViolation"));
                     }

                     this.status = ProtocolFactory.getInstance().createStatus((Element)child);
                  } else {
                     if (this.anyString != null) {
                        if (SAML2SDKUtils.DEBUG.messageEnabled()) {
                           SAML2SDKUtils.DEBUG.message("ArtifactResponseImpl.parseElement: included more than one any element.");
                        }

                        throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("moreElement"));
                     }

                     this.anyString = XMLUtils.print(child);
                  }
               }
            }

            super.validateData();
            this.isMutable = false;
         } else {
            if (SAML2SDKUtils.DEBUG.messageEnabled()) {
               SAML2SDKUtils.DEBUG.message("ArtifactResponseImpl.parseElement: not ArtifactResponse.");
            }

            throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("wrongInput"));
         }
      }
   }

   public ArtifactResponseImpl() {
      this.isMutable = true;
   }

   public ArtifactResponseImpl(Element element) throws SAML2Exception {
      this.parseElement(element);
      if (this.isSigned) {
         this.signedXMLString = XMLUtils.print(element);
      }
   }

   @Override
   public String getAny() {
      return this.anyString;
   }

   @Override
   public void setAny(String value) throws SAML2Exception {
      if (this.isMutable) {
         this.anyString = value;
      } else {
         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("objectImmutable"));
      }
   }

   @Override
   public String toXMLString() throws SAML2Exception {
      return this.toXMLString(true, false);
   }

   @Override
   public String toXMLString(boolean includeNSPrefix, boolean declareNS) throws SAML2Exception {
      if (this.isSigned && this.signedXMLString != null) {
         return this.signedXMLString;
      }

      this.validateData();
      StringBuilder result = new StringBuilder(1000);
      String prefix = "";
      String uri = "";
      if (includeNSPrefix) {
         prefix = "samlp:";
      }

      if (declareNS) {
         uri = " xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"";
      }

      result.append("<").append(prefix).append("ArtifactResponse").append(uri).append(" ID=\"").append(this.responseId).append("\"");
      if (this.inResponseTo != null && !this.inResponseTo.trim().isEmpty()) {
         result.append(" InResponseTo=\"").append(this.inResponseTo).append("\"");
      }

      result.append(" Version=\"")
         .append(this.version)
         .append("\"")
         .append(" IssueInstant=\"")
         .append(DateUtils.toUTCDateFormat(this.issueInstant))
         .append("\"");
      if (this.destination != null && !this.destination.trim().isEmpty()) {
         result.append(" Destination=\"").append(this.destination).append("\"");
      }

      if (this.consent != null && !this.consent.trim().isEmpty()) {
         result.append(" Consent=\"").append(this.consent).append("\"");
      }

      result.append(">");
      if (this.issuer != null) {
         result.append(this.issuer.toXMLString(includeNSPrefix, declareNS));
      }

      if (this.signatureString != null) {
         result.append(this.signatureString);
      }

      if (this.extensions != null) {
         result.append(this.extensions.toXMLString(includeNSPrefix, declareNS));
      }

      result.append(this.status.toXMLString(includeNSPrefix, declareNS));
      if (this.anyString != null && !this.anyString.trim().isEmpty()) {
         result.append(this.anyString);
      }

      result.append("</").append(prefix).append("ArtifactResponse>");
      return result.toString();
   }
}
