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

import com.sun.identity.saml2.common.SAML2Exception;
import com.sun.identity.saml2.common.SAML2SDKUtils;
import com.sun.identity.saml2.ecp.ECPRelayState;
import com.sun.identity.shared.xml.XMLUtils;
import org.w3c.dom.Element;

public class ECPRelayStateImpl implements ECPRelayState {
   private String value;
   private Boolean mustUnderstand;
   private String actor;
   private boolean isMutable;

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

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

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

   @Override
   public void setMustUnderstand(Boolean mustUnderstand) throws SAML2Exception {
      if (!this.isMutable) {
         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("objectImmutable"));
      }

      this.mustUnderstand = mustUnderstand;
   }

   @Override
   public String getActor() {
      return this.actor;
   }

   @Override
   public void setActor(String actor) throws SAML2Exception {
      if (!this.isMutable) {
         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("objectImmutable"));
      }

      this.actor = actor;
   }

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

   @Override
   public String toXMLString(boolean includeNSPrefix, boolean declareNS) throws SAML2Exception {
      this.validateData();
      StringBuffer xml = new StringBuffer(300);
      xml.append("<");
      if (includeNSPrefix) {
         xml.append("ecp:");
      }

      xml.append("RelayState");
      if (declareNS) {
         xml.append(" ")
            .append("xmlns:ecp=\"urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp\"")
            .append(" ")
            .append("xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\"");
      }

      xml.append(" ")
         .append("soap-env:")
         .append("mustUnderstand")
         .append("=")
         .append("\"")
         .append(this.mustUnderstand.toString())
         .append("\"")
         .append(" ")
         .append("soap-env:")
         .append("actor")
         .append("=")
         .append("\"")
         .append(this.actor)
         .append("\"")
         .append(">")
         .append(this.value)
         .append("</ecp:")
         .append("RelayState")
         .append(">");
      return xml.toString();
   }

   @Override
   public void makeImmutable() {
      if (this.isMutable) {
         this.isMutable = false;
      }
   }

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

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

         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("nullInput"));
      } else {
         String localName = element.getLocalName();
         if (!"RelayState".equals(localName)) {
            if (SAML2SDKUtils.DEBUG.messageEnabled()) {
               SAML2SDKUtils.DEBUG.message("ECPRelayStateImpl.parseElement: element local name should be RelayState");
            }

            throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("invalidECPRelayState"));
         } else {
            String namespaceURI = element.getNamespaceURI();
            if (!"urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp".equals(namespaceURI)) {
               if (SAML2SDKUtils.DEBUG.messageEnabled()) {
                  SAML2SDKUtils.DEBUG.message("ECPRelayStateImpl.parseElement: element namespace should be urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp");
               }

               throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("invalidECPNamesapce"));
            } else {
               String str = XMLUtils.getNodeAttributeValueNS(element, "http://schemas.xmlsoap.org/soap/envelope/", "mustUnderstand");
               this.mustUnderstand = SAML2SDKUtils.stringToBoolean(str);
               this.actor = XMLUtils.getNodeAttributeValueNS(element, "http://schemas.xmlsoap.org/soap/envelope/", "actor");
               this.value = XMLUtils.getElementValue(element);
               this.validateData();
            }
         }
      }
   }

   protected void validateData() throws SAML2Exception {
      if (this.value == null) {
         if (SAML2SDKUtils.DEBUG.messageEnabled()) {
            SAML2SDKUtils.DEBUG.message("ECPRelayStateImpl.validateData: value is missing in the ecp:RelayState");
         }

         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("missingECPRelayState"));
      } else if (this.mustUnderstand == null) {
         if (SAML2SDKUtils.DEBUG.messageEnabled()) {
            SAML2SDKUtils.DEBUG.message("ECPRelayStateImpl.validateData: mustUnderstand is missing in the ecp:RelayState");
         }

         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("missingMustUnderstandECPRelayState"));
      } else if (this.actor == null) {
         if (SAML2SDKUtils.DEBUG.messageEnabled()) {
            SAML2SDKUtils.DEBUG.message("ECPRelayStateImpl.validateData: actor is missing in the ecp:RelayState");
         }

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