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.GetComplete;
import com.sun.identity.saml2.protocol.IDPEntry;
import com.sun.identity.saml2.protocol.IDPList;
import com.sun.identity.saml2.protocol.ProtocolFactory;
import com.sun.identity.shared.xml.XMLUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class IDPListImpl implements IDPList {
   private List<IDPEntry> idpEntryList;
   private GetComplete getComplete;
   private boolean isMutable;

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

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

   @Override
   public List<IDPEntry> getIDPEntries() {
      return this.idpEntryList;
   }

   @Override
   public void setIDPEntries(List<IDPEntry> idpEntryList) throws SAML2Exception {
      if (this.isMutable) {
         this.idpEntryList = idpEntryList;
      } else {
         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("objectImmutable"));
      }
   }

   @Override
   public GetComplete getGetComplete() {
      return this.getComplete;
   }

   @Override
   public void setGetComplete(GetComplete getComplete) throws SAML2Exception {
      if (this.isMutable) {
         this.getComplete = getComplete;
      } 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 {
      this.validateIDPEntryList(this.idpEntryList);
      StringBuilder xmlString = new StringBuilder(150);
      xmlString.append("<");
      if (includeNSPrefix) {
         xmlString.append("samlp:");
      }

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

      xmlString.append(">").append("\n");
      if (this.idpEntryList != null && !this.idpEntryList.isEmpty()) {
         for (IDPEntry idpEntry : this.idpEntryList) {
            if (idpEntry != null) {
               String idpEntryStr = idpEntry.toXMLString(includeNSPrefix, declareNS);
               xmlString.append(idpEntryStr).append("\n");
            }
         }

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

         xmlString.append("</samlp:").append("IDPList").append(">");
         return xmlString.toString();
      } else {
         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("noIDPEntry"));
      }
   }

   @Override
   public void makeImmutable() {
      if (this.isMutable) {
         if (this.idpEntryList != null && !this.idpEntryList.isEmpty()) {
            for (IDPEntry idpEntry : this.idpEntryList) {
               if (idpEntry != null && idpEntry.isMutable()) {
                  idpEntry.makeImmutable();
               }
            }
         }

         if (this.getComplete != null && this.getComplete.isMutable()) {
            this.getComplete.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) {
         if (this.idpEntryList == null) {
            this.idpEntryList = new ArrayList<>();
         }

         for (int i = 0; i < nList.getLength(); i++) {
            Node childNode = nList.item(i);
            String cName = childNode.getLocalName();
            if (cName != null) {
               if (cName.equals("IDPEntry")) {
                  this.validateIDPEntry();
                  this.idpEntryList.add(protoFactory.createIDPEntry(XMLUtils.print(childNode)));
               } else if (cName.equals("GetComplete")) {
                  this.validateGetComplete();
                  Element getCompleteElement = (Element)childNode;
                  this.getComplete = protoFactory.createGetComplete(getCompleteElement);
               }
            }
         }

         this.validateIDPEntryList(this.idpEntryList);
         this.idpEntryList = Collections.unmodifiableList(this.idpEntryList);
      } else {
         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("noIDPEntry"));
      }
   }

   private void validateIDPEntryList(List<IDPEntry> idpEntryList) throws SAML2Exception {
      if (idpEntryList == null || idpEntryList.isEmpty()) {
         SAML2SDKUtils.DEBUG.message("IDPEntry Object is required");
         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("noIDPEntry"));
      }
   }

   private void validateIDPEntry() throws SAML2Exception {
      if (this.getComplete != null) {
         if (SAML2SDKUtils.DEBUG.messageEnabled()) {
            SAML2SDKUtils.DEBUG.message("IDPList Element should be the first element");
         }

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

   private void validateGetComplete() throws SAML2Exception {
      if (this.getComplete != null) {
         SAML2SDKUtils.DEBUG.message("Too may GetComplete Elements");
         throw new SAML2Exception(SAML2SDKUtils.BUNDLE.getString("schemaViolation"));
      }
   }
}
