/***********************************************************
Copyright (C) 2020 VeriSign, Inc.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

http://www.verisign.com/nds/naming/namestore/techdocs.html
 ***********************************************************/
package com.verisign.epp.codec.unhandlednamespaces.v1_0;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.verisign.epp.codec.gen.EPPExtValue;
import com.verisign.epp.codec.gen.EPPResponse;


/**
 * Class used to hold the unhandled namespace information, which includes the
 * namespace URI and the response XML of the unhandled namespace.
 */
public class EPPUnhandledNamespace {

  /**
   * Category for logging
   */
      private static Logger cat = LoggerFactory.getLogger(EPPUnhandledNamespace.class);
        

  /**
   * Regular Expression (RegEx) pattern used for identifying an unhandled
   * namespace extValue element.
   */
  private static Pattern unhandledNamespacesPattern = Pattern.compile("^(.+) not in login services$");

  /**
   * Namespace URI of the unhandled namespace.
   */
  private String namespaceUri;

  /**
   * Response XML associated with the unhandled namespace.
   */
  private String xml;

  /**
   * Default constructor for {@code UnhandledNamespace}.
   */
  public EPPUnhandledNamespace() {
  }

  /**
   * Constructor for {@code UnhandledNamespace} that takes to two attributes of
   * the namespace URI and the response XML.
   *
   * @param aNamespaceUri
   *           Namespace URI of the unhandled namespace
   * @param aXml
   *           Response XML of the unhandled namespace
   */
  public EPPUnhandledNamespace(String aNamespaceUri, String aXml) {
    this.namespaceUri = aNamespaceUri;
    this.xml = aXml;
  }

  /**
   * Gets the namespace URI of the unhandled namespace.
   *
   * @return the namespaceUri namespace URI of the unhandled namespace if set;
   *         {@code null} otherwise.
   */
  public String getNamespaceUri() {
    return this.namespaceUri;
  }

  /**
   * Sets the namespace URI of the unhandled namespace.
   *
   * @param aNamespaceUri
   *           tnamespace URI of the unhandled namespace
   */
  public void setNamespaceUri(String aNamespaceUri) {
    this.namespaceUri = aNamespaceUri;
  }

  /**
   * Gets the response XML of the unhandled namespace.
   *
   * @return Response XML of unhandled namespace if set; {@code null}
   *         otherwise.
   */
  public String getXml() {
    return this.xml;
  }

  /**
   * Sets the response XML of the unhandled namespace.
   *
   * @param aXml
   *           Response XML of the unhandled namespace.
   */
  public void setXml(String aXml) {
    this.xml = aXml;
  }

  /**
   * Method to set the unhandled namespace attribute from an
   * {@link EPPExtValue} of an {@link EPPResponse}.
   *
   * @param aExtValue
   *           {@link EPPExtValue} containing the unhandled namespaces
   *           information and content.
   *
   * @return {@code true} if the {@code aExtValue} does represent an unhandled
   *         namespace; {@code false} otherwise.
   */
  public boolean fromEppExtValue(EPPExtValue aExtValue) {
    if (aExtValue == null) {
      return false;
    }

    Matcher theMatcher = unhandledNamespacesPattern.matcher(aExtValue.getReason());

    if (theMatcher.matches()) {
      this.namespaceUri = theMatcher.group(1);
      this.xml = aExtValue.getValueStr();
      return true;
    }
    else {
      return false;
    }

  }

  /**
   * Create a list of {@code UnhandledNamespace} instances from the passed in
   * {@link EPPResponse}
   *
   * @param aResponse
   *           Response to get the list of {@code UnhandledNamespace}
   *           instances.
   *
   * @return List of {@code UnhandledNamespace} instances if at least one
   *         unhandled namespace was found; {@code null} otherwise.
   */
  public static List<EPPUnhandledNamespace> fromResponse(EPPResponse aResponse) {

    // No extValues elements?
    if (aResponse.getResult().getExtValues() == null) {
      return null;
    }

    List<EPPUnhandledNamespace> theUnhandledNamespaces = new ArrayList<>();

    for (EPPExtValue extValue : (Vector<EPPExtValue>) aResponse.getResult().getExtValues()) {

      EPPUnhandledNamespace theUnhandledNamespace = new EPPUnhandledNamespace();

      if (theUnhandledNamespace.fromEppExtValue(extValue)) {
        theUnhandledNamespaces.add(theUnhandledNamespace);
      }
    }

    if (theUnhandledNamespaces.size() != 0) {
      return theUnhandledNamespaces;
    }
    else {
      return null;
    }

  }

  /**
   * Creates a {@link String} of the {@code EPPUnhandledNamespace} attributes.
   *
   * @return Encoded {@link String} of the object attributes.
   */
  @Override
  public String toString() {
    return "URI = " + this.namespaceUri + ", XML = [" + this.xml + "]";
  }

  /**
   * Utility method to print the list of {@code EPPUnhandledNamespace}
   * instances.
   *
   * @param aUnhandledNamespaces
   *           List of {@code EPPUnhandledNamespace} instances.
   */
  public static void printUnhandledNamespaces(List<EPPUnhandledNamespace> aUnhandledNamespaces) {
    if (aUnhandledNamespaces == null || aUnhandledNamespaces.size() == 0) {
      System.out.println("printUnhandledNamespaces: There are no unhandled namespaces");
    }

    for (EPPUnhandledNamespace theUnhandledNamespace : aUnhandledNamespaces) {
      System.out.println(theUnhandledNamespace.toString());
    }
  }

  /**
   * Utility method to log the list of {@code EPPUnhandledNamespace} instances.
   *
   * @param aUnhandledNamespaces
   *           List of {@code EPPUnhandledNamespace} instances.
   */
  public static void logUnhandledNamespaces(List<EPPUnhandledNamespace> aUnhandledNamespaces) {
    if (aUnhandledNamespaces == null || aUnhandledNamespaces.size() == 0) {
      cat.debug("There are no unhandled namespaces");
    }

    for (EPPUnhandledNamespace theUnhandledNamespace : aUnhandledNamespaces) {
      cat.debug(theUnhandledNamespace.toString());
    }

  }

}
