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

import com.sun.identity.saml2.assertion.AssertionFactory;
import com.sun.identity.saml2.assertion.EncryptedID;
import com.sun.identity.saml2.assertion.NameID;
import com.sun.identity.saml2.common.SAML2Exception;
import com.sun.identity.saml2.common.SAML2SDKUtils;
import com.sun.identity.saml2.xmlenc.EncManager;
import com.sun.identity.shared.xml.XMLUtils;
import java.io.Serializable;
import java.security.Key;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class NameIDImpl extends NameIDTypeImpl implements NameID, Serializable {
   private static final String NAME_ID_ELEMENT = "NameID";

   public NameIDImpl() {
   }

   public NameIDImpl(String xml) throws SAML2Exception {
      Document document = XMLUtils.toDOMDocument(xml, SAML2SDKUtils.DEBUG);
      if (document != null) {
         Element rootElement = document.getDocumentElement();
         this.processElement(rootElement);
         this.makeImmutable();
      } else {
         SAML2SDKUtils.DEBUG.error("NameIDImpl.processElement(): invalid XML input");
         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("errorObtainingElement"));
      }
   }

   public NameIDImpl(Element element) throws SAML2Exception {
      this.processElement(element);
      this.makeImmutable();
   }

   private void processElement(Element element) throws SAML2Exception {
      if (element == null) {
         SAML2SDKUtils.DEBUG.error("NameIDImpl.processElement(): invalid root element");
         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("invalid_element"));
      }

      String elemName = element.getLocalName();
      if (elemName == null) {
         SAML2SDKUtils.DEBUG.error("NameIDImpl.processElement(): local name missing");
         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("missing_local_name"));
      }

      if (!elemName.equals("NameID")) {
         SAML2SDKUtils.DEBUG.error("NameIDImpl.processElement(): invalid local name " + elemName);
         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("invalid_local_name"));
      }

      this.getValueAndAttributes(element);
   }

   @Override
   public EncryptedID encrypt(Key recipientPublicKey, String dataEncAlgorithm, int dataEncStrength, String recipientEntityID) throws SAML2Exception {
      Element el = EncManager.getEncInstance()
         .encrypt(this.toXMLString(true, true), recipientPublicKey, dataEncAlgorithm, dataEncStrength, recipientEntityID, "EncryptedID");
      return AssertionFactory.getInstance().createEncryptedID(el);
   }

   @Override
   public String toXMLString(boolean includeNSPrefix, boolean declareNS) throws SAML2Exception {
      StringBuilder sb = new StringBuilder(2000);
      String ns = "";
      String appendNS = "";
      if (declareNS) {
         ns = " xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\"";
      }

      if (includeNSPrefix) {
         appendNS = "saml:";
      }

      sb.append("<").append(appendNS).append("NameID").append(ns);
      String nameQualifier = this.getNameQualifier();
      if (nameQualifier != null && !nameQualifier.trim().isEmpty()) {
         sb.append(" ").append("NameQualifier").append("=\"").append(nameQualifier).append("\"");
      }

      String spNameQualifier = this.getSPNameQualifier();
      if (spNameQualifier != null && !spNameQualifier.trim().isEmpty()) {
         sb.append(" ").append("SPNameQualifier").append("=\"").append(spNameQualifier).append("\"");
      }

      String format = this.getFormat();
      if (format != null && !format.trim().isEmpty()) {
         sb.append(" ").append("Format").append("=\"").append(format).append("\"");
      }

      String spProvidedID = this.getSPProvidedID();
      if (spProvidedID != null && !spProvidedID.trim().isEmpty()) {
         sb.append(" ").append("SPProvidedID").append("=\"").append(XMLUtils.escapeSpecialCharacters(spProvidedID)).append("\"");
      }

      sb.append(">");
      String value = this.getValue();
      if (value != null && !value.trim().isEmpty()) {
         sb.append(XMLUtils.escapeSpecialCharacters(value));
         sb.append("</").append(appendNS).append("NameID").append(">");
         return sb.toString();
      } else {
         SAML2SDKUtils.DEBUG.error("NameIDImpl.processElement(): name identifier is missing");
         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("missing_name_identifier"));
      }
   }

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