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

import com.sun.identity.saml2.common.SAML2Exception;
import com.sun.identity.saml2.common.SAML2SDKUtils;
import com.sun.identity.saml2.protocol.ProtocolFactory;
import com.sun.identity.saml2.protocol.StatusCode;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class StatusCodeImpl implements StatusCode {
   private boolean isMutable;
   private StatusCode statusCode;
   private String statusCodeValue;

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

   public StatusCodeImpl(Element element) throws SAML2Exception {
      this.parseElement(element);
   }

   @Override
   public StatusCode getStatusCode() {
      return this.statusCode;
   }

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

   @Override
   public String getValue() {
      return this.statusCodeValue;
   }

   @Override
   public void setValue(String value) throws SAML2Exception {
      if (this.isMutable) {
         this.statusCodeValue = 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 {
      String xmlStr = null;
      if (this.statusCodeValue != null && !this.statusCodeValue.isEmpty()) {
         StringBuilder xmlString = new StringBuilder(500);
         xmlString.append("<");
         if (includeNSPrefix) {
            xmlString.append("samlp:");
         }

         xmlString.append("StatusCode").append(" ");
         if (declareNS) {
            xmlString.append(" xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"").append("\n");
         }

         xmlString.append("Value").append("=").append("\"").append(this.statusCodeValue).append("\"");
         xmlString.append(">");
         if (this.statusCode != null) {
            xmlString.append("\n").append(this.statusCode.toXMLString(includeNSPrefix, declareNS));
         }

         xmlString.append("\n").append("</samlp:").append("StatusCode").append(">");
         xmlStr = xmlString.toString();
      }

      return xmlStr;
   }

   @Override
   public void makeImmutable() {
      if (this.isMutable) {
         if (this.statusCode != null && this.statusCode.isMutable()) {
            this.statusCode.makeImmutable();
         }

         this.isMutable = false;
      }
   }

   @Override
   public boolean isMutable() {
      return this.isMutable;
   }

   private void parseElement(Element element) throws SAML2Exception {
      ProtocolFactory protoFactory = ProtocolFactory.getInstance();
      this.statusCodeValue = element.getAttribute("Value");
      this.validateStatusCodeValue(this.statusCodeValue);
      NodeList nList = element.getChildNodes();
      if (nList != null && nList.getLength() > 0) {
         for (int i = 0; i < nList.getLength(); i++) {
            Node childNode = nList.item(i);
            String cName = childNode.getLocalName();
            if (cName != null && cName.equals("StatusCode")) {
               this.statusCode = protoFactory.createStatusCode((Element)childNode);
            }
         }
      }
   }

   private void validateStatusCodeValue(String statusCodeValue) throws SAML2Exception {
      if (statusCodeValue == null || statusCodeValue.isEmpty()) {
         SAML2SDKUtils.DEBUG.message("statusCodeValue is required");
         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("missingStatusCodeValue"));
      }
   }
}
