/*
 * 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 org.apache.lucene.util.Version;
import org.apache.solr.common.SolrException;
import org.apache.solr.util.DOMUtil;
import org.apache.solr.util.SystemIdResolver;
import org.apache.solr.common.util.XMLErrorLogger;
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;
import org.apache.commons.io.IOUtils;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
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.text.ParseException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 *
 */
public class Config {
  public static final Logger log = LoggerFactory.getLogger(Config.class);
  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;

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

  public Config(SolrResourceLoader loader, String name, InputSource is, String prefix) throws ParserConfigurationException, IOException, SAXException 
  {
    this(loader, name, is, prefix, true);
  }
  /**
   * 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 & 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 preprended to all non-absolute xpath expressions
   */
  public Config(SolrResourceLoader loader, String name, InputSource is, String prefix, boolean subProps) throws ParserConfigurationException, IOException, SAXException 
  {
    if( loader == null ) {
      loader = new SolrResourceLoader( null );
    }
    this.loader = loader;
    this.name = name;
    this.prefix = (prefix != null && !prefix.endsWith("/"))? prefix + '/' : prefix;
    try {
      javax.xml.parsers.DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      
      if (is == null) {
        is = new InputSource(loader.openConfig(name));
        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(name + " XML parser doesn't support XInclude option");
        }
      }
      
      final DocumentBuilder db = dbf.newDocumentBuilder();
      db.setEntityResolver(new SystemIdResolver(loader));
      db.setErrorHandler(xmllog);
      try {
        doc = db.parse(is);
        origDoc = copyDoc(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 (subProps) {
        DOMUtil.substituteProperties(doc, loader.getCoreProperties());
      }
    } catch (ParserConfigurationException e)  {
      SolrException.log(log, "Exception during parsing file: " + name, e);
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
    } catch (SAXException e)  {
      SolrException.log(log, "Exception during parsing file: " + name, e);
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
    } catch (TransformerException e) {
      SolrException.log(log, "Exception during parsing file: " + name, e);
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
    }
  }
  
  public Config(SolrResourceLoader loader, String name, Document doc) {
    this.prefix = null;
    this.doc = doc;
    try {
      this.origDoc = copyDoc(doc);
    } catch (TransformerException e) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
    }
    this.name = name;
    this.loader = loader;
  }

  
  private static Document copyDoc(Document doc) throws TransformerException {
    TransformerFactory tfactory = TransformerFactory.newInstance();
    Transformer tx = tfactory.newTransformer();
    DOMSource source = new DOMSource(doc);
    DOMResult result = new DOMResult();
    tx.transform(source, result);
    return (Document) result.getNode();
  }
  
  /**
   * @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 void substituteProperties() {
    DOMUtil.substituteProperties(doc, loader.getCoreProperties());
  }


  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 getUnsubstitutedNode(String path, boolean errIfMissing) {
    return getNode(path, origDoc, 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.debug(name + " missing optional " + 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.debug(name + " missing optional " + 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;

    /******
    short typ = nd.getNodeType();
    if (typ==Node.ATTRIBUTE_NODE || typ==Node.TEXT_NODE) {
      return nd.getNodeValue();
    }
    return nd.getTextContent();
    ******/
  }


  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;
   }
   
   public Version getLuceneVersion(String path) {
     return parseLuceneVersionString(getVal(path, true));
   }
   
   public Version getLuceneVersion(String path, Version def) {
     String val = getVal(path, false);
     return val!=null ? parseLuceneVersionString(val) : def;
   }
  
  private static final AtomicBoolean versionWarningAlreadyLogged = new AtomicBoolean(false);
  
  public static final Version parseLuceneVersionString(final String matchVersion) {
    final Version version;
    try {
      version = Version.parseLeniently(matchVersion);
    } catch (ParseException pe) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
        "Invalid luceneMatchVersion.  Should be of the form 'V.V.V' (e.g. 4.8.0)", pe);
    }
    
    if (version == Version.LATEST && !versionWarningAlreadyLogged.getAndSet(true)) {
      log.warn(
        "You should not use LATEST as luceneMatchVersion property: "+
        "if you use this setting, and then Solr upgrades to a newer release of Lucene, "+
        "sizable changes may happen. If precise back compatibility is important "+
        "then you should instead explicitly specify an actual Lucene version."
      );
    }
    
    return version;
  }

  public Config getOriginalConfig() {
    return new Config(loader, null, origDoc);
  }

}
