/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.solr.core;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.IOException;
import java.io.InputStream;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;

import org.apache.commons.io.IOUtils;
import org.apache.solr.cloud.ZkSolrResourceLoader;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.XMLErrorLogger;
import org.apache.solr.util.DOMUtil;
import org.apache.solr.util.SystemIdResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * Wrapper around an XML DOM object to provide convenient accessors to it.  Intended for XML config files.
 */
public class XmlConfigFile { // formerly simply "Config"
  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
  private static final XMLErrorLogger xmllog = new XMLErrorLogger(log);

  static final XPathFactory xpathFactory = XPathFactory.newInstance();

  private final Document doc;
  private final Document origDoc; // with unsubstituted properties
  private final String prefix;
  private final String name;
  private final SolrResourceLoader loader;
  private final Properties substituteProperties;
  private int zkVersion = -1;

  /**
   * Builds a config from a resource name with no xpath prefix.  Does no property substitution.
   */
  public XmlConfigFile(SolrResourceLoader loader, String name) throws ParserConfigurationException, IOException, SAXException
  {
    this( loader, name, null, null );
  }

  /**
   * Builds a config.  Does no property substitution.
   */
  public XmlConfigFile(SolrResourceLoader loader, String name, InputSource is, String prefix) throws ParserConfigurationException, IOException, SAXException
  {
    this(loader, name, is, prefix, null);
  }

  /**
   * Builds a config:
   * <p>
   * Note that the 'name' parameter is used to obtain a valid input stream if no valid one is provided through 'is'.
   * If no valid stream is provided, a valid SolrResourceLoader instance should be provided through 'loader' so
   * the resource can be opened (@see SolrResourceLoader#openResource); if no SolrResourceLoader instance is provided, a default one
   * will be created.
   * </p>
   * <p>
   * Consider passing a non-null 'name' parameter in all use-cases since it is used for logging &amp; exception reporting.
   * </p>
   * @param loader the resource loader used to obtain an input stream if 'is' is null
   * @param name the resource name used if the input stream 'is' is null
   * @param is the resource as a SAX InputSource
   * @param prefix an optional prefix that will be prepended to all non-absolute xpath expressions
   * @param substituteProps optional property substitution
   */
  public XmlConfigFile(SolrResourceLoader loader, String name, InputSource is, String prefix, Properties substituteProps) throws ParserConfigurationException, IOException, SAXException
  {
    if (null == loader) throw new NullPointerException("loader");
    this.loader = loader;
    
    this.substituteProperties = substituteProps;
    this.name = name;
    this.prefix = (prefix != null && !prefix.endsWith("/"))? prefix + '/' : prefix;
    try {
      javax.xml.parsers.DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

      if (is == null) {
        InputStream in = loader.openResource(name);
        if (in instanceof ZkSolrResourceLoader.ZkByteArrayInputStream) {
          zkVersion = ((ZkSolrResourceLoader.ZkByteArrayInputStream) in).getStat().getVersion();
          log.debug("loaded config {} with version {} ",name,zkVersion);
        }
        is = new InputSource(in);
        is.setSystemId(SystemIdResolver.createSystemIdFromResourceName(name));
      }

      // only enable xinclude, if a SystemId is available
      if (is.getSystemId() != null) {
        try {
          dbf.setXIncludeAware(true);
          dbf.setNamespaceAware(true);
        } catch(UnsupportedOperationException e) {
          log.warn("{} XML parser doesn't support XInclude option", name);
        }
      }
      
      final DocumentBuilder db = dbf.newDocumentBuilder();
      db.setEntityResolver(new SystemIdResolver(loader));
      db.setErrorHandler(xmllog);
      try {
        doc = db.parse(is);
        origDoc = doc;
      } finally {
        // some XML parsers are broken and don't close the byte stream (but they should according to spec)
        IOUtils.closeQuietly(is.getByteStream());
      }
      if (substituteProps != null) {
        DOMUtil.substituteProperties(doc, getSubstituteProperties());
      }
    } catch (ParserConfigurationException | SAXException e)  {
      SolrException.log(log, "Exception during parsing file: " + name, e);
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
    }
  }

  /*
     * Assert that assertCondition is true.
     * If not, prints reason as log warning.
     * If failCondition is true, then throw exception instead of warning
     */
  public static void assertWarnOrFail(String reason, boolean assertCondition, boolean failCondition) {
    if (assertCondition) {
      return;
    } else if (failCondition) {
      throw new SolrException(SolrException.ErrorCode.FORBIDDEN, reason);
    } else {
      log.warn(reason);
    }
  }

  /** Returns non-null props to substitute.  Param is the base/default set, also non-null. */
  protected Properties getSubstituteProperties() {
    return this.substituteProperties;
  }


  /**
   * @since solr 1.3
   */
  public SolrResourceLoader getResourceLoader()
  {
    return loader;
  }

  /**
   * @since solr 1.3
   */
  public String getResourceName() {
    return name;
  }

  public String getName() {
    return name;
  }
  
  public Document getDocument() {
    return doc;
  }

  public XPath getXPath() {
    return xpathFactory.newXPath();
  }

  private String normalize(String path) {
    return (prefix==null || path.startsWith("/")) ? path : prefix+path;
  }
  
  public Object evaluate(String path, QName type) {
    XPath xpath = xpathFactory.newXPath();
    try {
      String xstr=normalize(path);

      // TODO: instead of prepending /prefix/, we could do the search rooted at /prefix...
      Object o = xpath.evaluate(xstr, doc, type);
      return o;

    } catch (XPathExpressionException e) {
      throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,"Error in xpath:" + path +" for " + name,e);
    }
  }

  public Node getNode(String path, boolean errifMissing) {
    return getNode(path, doc, errifMissing);
  }

  public Node getNode(String path, Document doc, boolean errIfMissing) {
    XPath xpath = xpathFactory.newXPath();
    String xstr = normalize(path);

    try {
      NodeList nodes = (NodeList)xpath.evaluate(xstr, doc, 
                                                XPathConstants.NODESET);
      if (nodes==null || 0 == nodes.getLength() ) {
        if (errIfMissing) {
          throw new RuntimeException(name + " missing "+path);
        } else {
          log.trace("{} missing optional {}", name, path);
          return null;
        }
      }
      if ( 1 < nodes.getLength() ) {
        throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,
                                 name + " contains more than one value for config path: " + path);
      }
      Node nd = nodes.item(0);
      log.trace("{}:{}={}", name, path, nd);
      return nd;

    } catch (XPathExpressionException e) {
      SolrException.log(log,"Error in xpath",e);
      throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,"Error in xpath:" + xstr + " for " + name,e);
    } catch (SolrException e) {
      throw(e);
    } catch (Exception e) {
      SolrException.log(log,"Error in xpath",e);
      throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,"Error in xpath:" + xstr+ " for " + name,e);
    }
  }

  public NodeList getNodeList(String path, boolean errIfMissing) {
    XPath xpath = xpathFactory.newXPath();
    String xstr = normalize(path);

    try {
      NodeList nodeList = (NodeList)xpath.evaluate(xstr, doc, XPathConstants.NODESET);

      if (null == nodeList) {
        if (errIfMissing) {
          throw new RuntimeException(name + " missing "+path);
        } else {
          log.trace("{} missing optional {}", name, path);
          return null;
        }
      }

      log.trace("{}:{}={}", name, path, nodeList);
      return nodeList;

    } catch (XPathExpressionException e) {
      SolrException.log(log,"Error in xpath",e);
      throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,"Error in xpath:" + xstr + " for " + name,e);
    } catch (SolrException e) {
      throw(e);
    } catch (Exception e) {
      SolrException.log(log,"Error in xpath",e);
      throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,"Error in xpath:" + xstr+ " for " + name,e);
    }
  }

  /**
   * Returns the set of attributes on the given element that are not among the given knownAttributes,
   * or null if all attributes are known.
   */
  public Set<String> getUnknownAttributes(Element element, String... knownAttributes) {
    Set<String> knownAttributeSet = new HashSet<>(Arrays.asList(knownAttributes));
    Set<String> unknownAttributeSet = null;
    NamedNodeMap attributes = element.getAttributes();
    for (int i = 0 ; i < attributes.getLength() ; ++i) {
      final String attributeName = attributes.item(i).getNodeName();
      if ( ! knownAttributeSet.contains(attributeName)) {
        if (null == unknownAttributeSet) {
          unknownAttributeSet = new HashSet<>();
        }
        unknownAttributeSet.add(attributeName);
      }
    }
    return unknownAttributeSet;
  }

  /**
   * Logs an error and throws an exception if any of the element(s) at the given elementXpath
   * contains an attribute name that is not among knownAttributes. 
   */
  public void complainAboutUnknownAttributes(String elementXpath, String... knownAttributes) {
    SortedMap<String,SortedSet<String>> problems = new TreeMap<>();
    NodeList nodeList = getNodeList(elementXpath, false);
    for (int i = 0 ; i < nodeList.getLength() ; ++i) {
      Element element = (Element)nodeList.item(i);
      Set<String> unknownAttributes = getUnknownAttributes(element, knownAttributes);
      if (null != unknownAttributes) {
        String elementName = element.getNodeName();
        SortedSet<String> allUnknownAttributes = problems.get(elementName);
        if (null == allUnknownAttributes) {
          allUnknownAttributes = new TreeSet<>();
          problems.put(elementName, allUnknownAttributes);
        }
        allUnknownAttributes.addAll(unknownAttributes);
      }
    }
    if (problems.size() > 0) {
      StringBuilder message = new StringBuilder();
      for (Map.Entry<String,SortedSet<String>> entry : problems.entrySet()) {
        if (message.length() > 0) {
          message.append(", ");
        }
        message.append('<');
        message.append(entry.getKey());
        for (String attributeName : entry.getValue()) {
          message.append(' ');
          message.append(attributeName);
          message.append("=\"...\"");
        }
        message.append('>');
      }
      message.insert(0, "Unknown attribute(s) on element(s): ");
      String msg = message.toString();
      SolrException.log(log, msg);
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, msg);
    }
  }

  public String getVal(String path, boolean errIfMissing) {
    Node nd = getNode(path,errIfMissing);
    if (nd==null) return null;

    String txt = DOMUtil.getText(nd);

    log.debug("{} {}={}", name, path, txt);
    return txt;
  }


  public String get(String path) {
    return getVal(path,true);
  }

  public String get(String path, String def) {
    String val = getVal(path, false);
    if (val == null || val.length() == 0) {
      return def;
    }
    return val;
  }

  public int getInt(String path) {
    return Integer.parseInt(getVal(path, true));
  }

  public int getInt(String path, int def) {
    String val = getVal(path, false);
    return val!=null ? Integer.parseInt(val) : def;
  }

  public boolean getBool(String path) {
    return Boolean.parseBoolean(getVal(path, true));
  }

  public boolean getBool(String path, boolean def) {
    String val = getVal(path, false);
    return val!=null ? Boolean.parseBoolean(val) : def;
  }

  public float getFloat(String path) {
    return Float.parseFloat(getVal(path, true));
  }

  public float getFloat(String path, float def) {
    String val = getVal(path, false);
    return val!=null ? Float.parseFloat(val) : def;
  }

  public double getDouble(String path){
     return Double.parseDouble(getVal(path, true));
   }

  public double getDouble(String path, double def) {
    String val = getVal(path, false);
    return val != null ? Double.parseDouble(val) : def;
  }

  /**If this config is loaded from zk the version is relevant other wise -1 is returned
   */
  public int getZnodeVersion(){
    return zkVersion;
  }

}
