/*
 * 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.uima.ruta.engine;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.uima.UIMAFramework;
import org.apache.uima.analysis_engine.AnalysisEngine;
import org.apache.uima.analysis_engine.AnalysisEngineDescription;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.analysis_engine.metadata.AnalysisEngineMetaData;
import org.apache.uima.cas.CAS;
import org.apache.uima.cas.FeatureStructure;
import org.apache.uima.fit.factory.AnalysisEngineFactory;
import org.apache.uima.fit.util.JCasUtil;
import org.apache.uima.jcas.JCas;
import org.apache.uima.jcas.cas.FSArray;
import org.apache.uima.jcas.tcas.Annotation;
import org.apache.uima.resource.ResourceConfigurationException;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.resource.ResourceManager;
import org.apache.uima.resource.ResourceSpecifier;
import org.apache.uima.resource.metadata.ConfigurationParameterSettings;
import org.apache.uima.resource.metadata.TypeSystemDescription;
import org.apache.uima.ruta.type.DebugBlockApply;
import org.apache.uima.ruta.type.DebugMatchedRuleMatch;
import org.apache.uima.ruta.type.DebugRuleApply;
import org.apache.uima.ruta.type.DebugRuleMatch;
import org.apache.uima.ruta.type.DebugScriptApply;
import org.apache.uima.util.CasCreationUtils;
import org.apache.uima.util.FileUtils;
import org.apache.uima.util.InvalidXMLException;
import org.apache.uima.util.XMLInputSource;

public class Ruta {

  /**
   * This applies the given rule on the given JCas object
   * 
   * @param jcas
   *          - the current document
   * @param rule
   *          - String containing one or more rules in valid ruta syntax
   * @param configurationData
   *          - additional configuration parameter pairs
   * @throws AnalysisEngineProcessException
   *           - problem while processing
   * @throws ResourceInitializationException
   *           - problem while initializing
   */
  public static void applyRule(JCas jcas, String rule, Object... configurationData)
          throws ResourceInitializationException, AnalysisEngineProcessException {
    AnalysisEngine ae = null;
    if (configurationData == null || configurationData.length == 0) {
      ae = AnalysisEngineFactory.createEngine(RutaEngine.class, RutaEngine.PARAM_RULES, rule);
    } else {
      Object[] config = ArrayUtils.addAll(configurationData, RutaEngine.PARAM_RULES, rule);
      ae = AnalysisEngineFactory.createEngine(RutaEngine.class, config);
    }
    ae.process(jcas);
    ae.destroy();
  }

  public static void apply(CAS cas, String script, Map<String, Object> parameters)
          throws IOException, InvalidXMLException, ResourceInitializationException,
          ResourceConfigurationException, AnalysisEngineProcessException, URISyntaxException {
    String viewName = cas.getViewName();
    URL aedesc = RutaEngine.class.getResource("BasicEngine.xml");
    AnalysisEngine ae = wrapAnalysisEngine(aedesc, viewName, null);

    File scriptFile = File.createTempFile("Ruta", RutaEngine.SCRIPT_FILE_EXTENSION);
    scriptFile.deleteOnExit();
    FileUtils.saveString2File(script, scriptFile, "UTF-8");
    ae.setConfigParameterValue(RutaEngine.PARAM_SCRIPT_PATHS,
            new String[] { scriptFile.getParentFile().getAbsolutePath() });
    String name = scriptFile.getName().substring(0, scriptFile.getName().length() - 5);
    ae.setConfigParameterValue(RutaEngine.PARAM_MAIN_SCRIPT, name);
    if (parameters != null) {
      for (Map.Entry<String, Object> parameter : parameters.entrySet()) {
        ae.setConfigParameterValue(parameter.getKey(), parameter.getValue());
      }
    }
    ae.reconfigure();
    ae.process(cas);
    scriptFile.delete();
    ae.destroy();
  }

  public static void apply(CAS cas, String script)
          throws IOException, InvalidXMLException, ResourceInitializationException,
          ResourceConfigurationException, AnalysisEngineProcessException, URISyntaxException {
    apply(cas, script, null);
  }

  private static List<Annotation> getRuleMatches(JCas jcas) {
    List<Annotation> result = new LinkedList<>();
    Collection<DebugBlockApply> blockApplies = JCasUtil.select(jcas, DebugBlockApply.class);
    for (DebugBlockApply debugBlockApply : blockApplies) {
      collectRuleMatches(debugBlockApply, result);
    }
    return result;
  }

  private static int countRuleApplies(JCas jcas) {
    int result = 0;
    Collection<DebugBlockApply> blockApplies = JCasUtil.select(jcas, DebugBlockApply.class);
    for (DebugBlockApply debugBlockApply : blockApplies) {
      result += countRuleApplies(debugBlockApply);
    }
    return result;
  }

  private static int countRuleApplies(Annotation annotation) {
    int result = 0;
    if (annotation instanceof DebugBlockApply) {
      DebugBlockApply dba = (DebugBlockApply) annotation;
      FSArray<DebugScriptApply> innerApply = dba.getInnerApply();
      for (int i = 0; i < innerApply.size(); i++) {
        Annotation each = (Annotation) innerApply.get(i);
        result += countRuleApplies(each);
      }
    } else if (annotation instanceof DebugRuleApply) {
      DebugRuleApply dra = (DebugRuleApply) annotation;
      result += dra.getApplied();
    }
    return result;
  }

  private static void collectRuleMatches(Annotation annotation, List<Annotation> result) {
    if (annotation instanceof DebugBlockApply) {
      DebugBlockApply dba = (DebugBlockApply) annotation;
      FSArray<DebugScriptApply> innerApply = dba.getInnerApply();
      for (int i = 0; i < innerApply.size(); i++) {
        Annotation each = (Annotation) innerApply.get(i);
        collectRuleMatches(each, result);
      }
    } else if (annotation instanceof DebugRuleApply) {
      DebugRuleApply dra = (DebugRuleApply) annotation;
      FSArray<DebugRuleMatch> rules = dra.getRules();
      for (int i = 0; i < rules.size(); i++) {
        Annotation each = (Annotation) rules.get(i);
        collectRuleMatches(each, result);
      }
    } else if (annotation instanceof DebugMatchedRuleMatch) {
      DebugMatchedRuleMatch dmrm = (DebugMatchedRuleMatch) annotation;
      result.add(dmrm);
    }
  }

  /**
   * Removes all debug annotations from the index.
   * 
   * @param jcas
   *          - the current document
   */
  public static void removeDebugInformation(JCas jcas) {
    jcas.removeAllIncludingSubtypes(DebugBlockApply.type);
    jcas.removeAllIncludingSubtypes(DebugRuleApply.type);
    jcas.removeAllIncludingSubtypes(DebugRuleMatch.type);
  }

  public static String inject(String script, String placeholder, int[] addresses) {
    // TODO provide a robust implementation considering also other $, e.g., in strings
    String quote = Pattern.quote(placeholder);
    Pattern pattern = Pattern.compile(quote);
    Matcher matcher = pattern.matcher(script);
    StringBuilder sb = new StringBuilder();
    int start = 0;
    int counter = 0;
    while (matcher.find(start)) {
      String group = matcher.group();
      sb.append(script.substring(start, matcher.start()));
      if (counter < addresses.length) {
        sb.append("$" + addresses[0]);
      } else {
        sb.append("$" + group);
      }
      start = matcher.end();
    }
    if (start < script.length()) {
      sb.append(script.substring(start, script.length()));
    }
    return sb.toString();
  }

  public static String inject(String script, FeatureStructure... annotations) {
    return inject(script, "$", getAddresses(annotations));
  }

  private static int[] getAddresses(FeatureStructure[] annotations) {
    int[] result = new int[annotations.length];
    for (int i = 0; i < annotations.length; i++) {
      result[i] = annotations[i].getAddress();

    }
    return result;
  }

  /**
   * This method returns the spans of successful rule applies.
   * 
   * @param jcas
   *          - the current document
   * @param rule
   *          - String containing one or more rules in valid ruta syntax
   * @param configurationData
   *          - additional configuration parameter pairs
   * @return list of successful rule matches
   * @throws AnalysisEngineProcessException
   *           - problem while processing
   * @throws ResourceInitializationException
   *           - problem while initializing
   */
  public static List<Annotation> select(JCas jcas, String rule, Object... configurationData)
          throws AnalysisEngineProcessException, ResourceInitializationException {
    Object[] config = ArrayUtils.addAll(configurationData, RutaEngine.PARAM_DEBUG, true,
            RutaEngine.PARAM_DEBUG_WITH_MATCHES, true);
    applyRule(jcas, rule, config);
    List<Annotation> ruleMatches = getRuleMatches(jcas);
    removeDebugInformation(jcas);
    return ruleMatches;
  }

  /**
   * This method returns true if the rule (or one of the rules) was able to match.
   * 
   * @param jcas
   *          - the current document
   * @param rule
   *          - String containing one or more rules in valid ruta syntax
   * @param configurationData
   *          - additional configuration parameter pairs
   * @return true if matched, false otherwise
   * @throws AnalysisEngineProcessException
   *           - problem while processing
   * @throws ResourceInitializationException
   *           - problem while initializing
   */
  public static boolean matches(JCas jcas, String rule, Object... configurationData)
          throws AnalysisEngineProcessException, ResourceInitializationException {
    Object[] config = ArrayUtils.addAll(configurationData, RutaEngine.PARAM_DEBUG, true);
    applyRule(jcas, rule, config);
    int applies = countRuleApplies(jcas);
    removeDebugInformation(jcas);
    return applies > 0;
  }

  public static AnalysisEngine wrapAnalysisEngine(URL descriptorUrl, String viewName,
          ResourceManager resourceManager) throws ResourceInitializationException,
          ResourceConfigurationException, InvalidXMLException, IOException, URISyntaxException {
    return wrapAnalysisEngine(descriptorUrl, viewName, false, Charset.defaultCharset().name(),
            resourceManager);
  }

  public static AnalysisEngine wrapAnalysisEngine(URL descriptorUrl, String viewName,
          boolean rutaEngine, String encoding, ResourceManager resourceManager)
          throws ResourceInitializationException, ResourceConfigurationException,
          InvalidXMLException, IOException, URISyntaxException {
    if (viewName.equals(CAS.NAME_DEFAULT_SOFA)) {
      XMLInputSource in = new XMLInputSource(descriptorUrl);
      ResourceSpecifier specifier = UIMAFramework.getXMLParser().parseResourceSpecifier(in);
      AnalysisEngine ae = UIMAFramework.produceAnalysisEngine(specifier, resourceManager, null);
      return ae;
    } else {
      InputStream inputStream = null;
      if (rutaEngine) {
        inputStream = Ruta.class.getResourceAsStream("AAEDBasicEngine.xml");
      } else {
        inputStream = Ruta.class.getResourceAsStream("AAED.xml");
      }
      String aaedString = IOUtils.toString(inputStream, encoding);
      String absolutePath = descriptorUrl.toExternalForm();
      aaedString = aaedString.replaceAll("\\$\\{sofaName\\}", viewName);
      aaedString = aaedString.replaceAll("\\$\\{descriptorLocation\\}", absolutePath);
      File tempFile = File.createTempFile("RutaAAED", ".xml");
      FileUtils.saveString2File(aaedString, tempFile);
      XMLInputSource in = new XMLInputSource(tempFile);
      ResourceSpecifier specifier = UIMAFramework.getXMLParser().parseResourceSpecifier(in);
      AnalysisEngine ae = UIMAFramework.produceAnalysisEngine(specifier, resourceManager, null);
      tempFile.delete();
      return ae;
    }
  }

  @Deprecated
  public static AnalysisEngineDescription createAnalysisEngineDescription(String script)
          throws IOException, InvalidXMLException, ResourceInitializationException {
    return createAnalysisEngineDescription(script, (TypeSystemDescription[]) null);
  }

  @Deprecated
  public static AnalysisEngineDescription createAnalysisEngineDescription(String script,
          TypeSystemDescription... tsds)
          throws IOException, InvalidXMLException, ResourceInitializationException {
    File scriptFile = File.createTempFile("Ruta", RutaEngine.SCRIPT_FILE_EXTENSION);
    scriptFile.deleteOnExit();
    if (!script.startsWith("PACKAGE")) {
      script = "PACKAGE org.apache.uima.ruta;\n" + script;
    }
    FileUtils.saveString2File(script, scriptFile);
    URL url = RutaEngine.class.getResource("BasicEngine.xml");
    XMLInputSource in = new XMLInputSource(url);
    AnalysisEngineDescription aed = (AnalysisEngineDescription) UIMAFramework.getXMLParser()
            .parseResourceSpecifier(in);
    AnalysisEngineMetaData metaData = aed.getAnalysisEngineMetaData();
    ConfigurationParameterSettings settings = metaData.getConfigurationParameterSettings();
    settings.setParameterValue(RutaEngine.PARAM_SCRIPT_PATHS,
            new String[] { scriptFile.getParentFile().getAbsolutePath() });
    String name = scriptFile.getName().substring(0, scriptFile.getName().length() - 5);
    settings.setParameterValue(RutaEngine.PARAM_MAIN_SCRIPT, name);
    if (tsds != null) {
      List<TypeSystemDescription> tsdList = new ArrayList<TypeSystemDescription>();
      tsdList.add(metaData.getTypeSystem());
      tsdList.addAll(Arrays.asList(tsds));
      TypeSystemDescription typeSystemDescription = CasCreationUtils.mergeTypeSystems(tsdList);
      metaData.setTypeSystem(typeSystemDescription);
    }
    return aed;
  }

}
