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.Status;
import com.sun.identity.saml2.protocol.StatusCode;
import com.sun.identity.saml2.protocol.StatusDetail;
import com.sun.identity.saml2.protocol.StatusMessage;
import com.sun.identity.shared.xml.XMLUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class StatusImpl implements Status {
   private boolean isMutable;
   private StatusCode statusCode;
   private String statusMessage;
   private StatusDetail statusDetail;

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

   public StatusImpl(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 getStatusMessage() {
      return this.statusMessage;
   }

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

   @Override
   public StatusDetail getStatusDetail() {
      return this.statusDetail;
   }

   @Override
   public void setStatusDetail(StatusDetail value) throws SAML2Exception {
      if (this.isMutable) {
         this.statusDetail = 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.statusCode != null) {
         StringBuilder xmlString = new StringBuilder(500);
         xmlString.append("<");
         if (includeNSPrefix) {
            xmlString.append("samlp:");
         }

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

         xmlString.append(">");
         xmlString.append("\n").append(this.statusCode.toXMLString(includeNSPrefix, declareNS));
         if (this.statusMessage != null && !this.statusMessage.isEmpty()) {
            ProtocolFactory protoFactory = ProtocolFactory.getInstance();
            StatusMessage sMessage = protoFactory.createStatusMessage(this.statusMessage);
            xmlString.append("\n").append(sMessage.toXMLString(includeNSPrefix, declareNS));
         }

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

         xmlString.append("\n").append("</samlp:").append("Status").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();
      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) {
               if (cName.equals("StatusCode")) {
                  this.statusCode = protoFactory.createStatusCode((Element)childNode);
                  this.validateStatusCode(this.statusCode);
               } else if (cName.equals("StatusMessage")) {
                  this.statusMessage = XMLUtils.getElementString((Element)childNode);
               } else if (cName.equals("StatusDetail")) {
                  this.statusDetail = protoFactory.createStatusDetail((Element)childNode);
               }
            }
         }
      }
   }

   private void validateStatusCode(StatusCode statusCode) throws SAML2Exception {
      if (statusCode == null) {
         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("missingStatusCode"));
      }
   }
}
