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.Artifact;
import com.sun.identity.saml2.protocol.ArtifactResolve;
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 ArtifactResolveImpl extends RequestAbstractImpl implements ArtifactResolve {
   private Artifact artifact;

   @Override
   protected void validateData() throws SAML2Exception {
      super.validateData();
      if (this.artifact == null) {
         if (SAML2SDKUtils.DEBUG.messageEnabled()) {
            SAML2SDKUtils.DEBUG.message("ArtifactResolveImpl.validateData: missing Artifact.");
         }

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

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

         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("nullInput"));
      } else {
         String tag = element.getLocalName();
         if (tag != null && tag.equals("ArtifactResolve")) {
            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.requestId = 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.destinationURI = 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.nameID != null) {
                        if (SAML2SDKUtils.DEBUG.messageEnabled()) {
                           SAML2SDKUtils.DEBUG.message("ArtifactResolveImpl.parseElement: included more than one Issuer.");
                        }

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

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

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

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

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

                     if (this.extensions != null || this.artifact != null) {
                        if (SAML2SDKUtils.DEBUG.messageEnabled()) {
                           SAML2SDKUtils.DEBUG.message("ArtifactResolveImpl.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("ArtifactResolveImpl.parseElement:included more than one Extensions.");
                        }

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

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

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

                     this.extensions = ProtocolFactory.getInstance().createExtensions((Element)child);
                  } else {
                     if (!childName.equals("Artifact")) {
                        if (SAML2SDKUtils.DEBUG.messageEnabled()) {
                           SAML2SDKUtils.DEBUG.message("ArtifactResolveImpl.parseElement: Invalid element:" + childName);
                        }

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

                     if (this.artifact != null) {
                        if (SAML2SDKUtils.DEBUG.messageEnabled()) {
                           SAML2SDKUtils.DEBUG.message("ArtifactResolveImpl.parseElement: included more than one Artifact.");
                        }

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

                     this.artifact = ProtocolFactory.getInstance().createArtifact((Element)child);
                  }
               }
            }

            this.validateData();
         } else {
            if (SAML2SDKUtils.DEBUG.messageEnabled()) {
               SAML2SDKUtils.DEBUG.message("ArtifactResolveImpl.parseElement: not ArtifactResolve.");
            }

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

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

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

   @Override
   public Artifact getArtifact() {
      return this.artifact;
   }

   @Override
   public void setArtifact(Artifact value) throws SAML2Exception {
      if (!this.isMutable) {
         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("objectImmutable"));
      }

      this.artifact = value;
   }

   @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();
      StringBuffer result = new StringBuffer(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("ArtifactResolve")
         .append(uri)
         .append(" ID=\"")
         .append(this.requestId)
         .append("\"")
         .append(" Version=\"")
         .append(this.version)
         .append("\"")
         .append(" IssueInstant=\"")
         .append(DateUtils.toUTCDateFormat(this.issueInstant))
         .append("\"");
      if (this.destinationURI != null && !this.destinationURI.trim().isEmpty()) {
         result.append(" Destination=\"").append(this.destinationURI).append("\"");
      }

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

      result.append(">");
      if (this.nameID != null) {
         result.append(this.nameID.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.artifact.toXMLString(includeNSPrefix, declareNS));
      result.append("</").append(prefix).append("ArtifactResolve>");
      return result.toString();
   }
}
