/*
 * 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.fit.maven;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.LoaderClassPath;
import javassist.NotFoundException;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.Annotation;
import javassist.bytecode.annotation.MemberValue;
import javassist.bytecode.annotation.StringMemberValue;

import org.apache.commons.io.IOUtils;
import org.apache.commons.io.LineIterator;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.apache.uima.fit.descriptor.ResourceMetaData;
import org.apache.uima.fit.factory.ConfigurationParameterFactory;
import org.apache.uima.fit.factory.ExternalResourceFactory;
import org.apache.uima.fit.factory.ResourceMetaDataFactory;
import org.apache.uima.fit.internal.EnhancedClassFile;
import org.apache.uima.fit.maven.util.Util;
import org.codehaus.plexus.util.FileUtils;
import org.sonatype.plexus.build.incremental.BuildContext;

import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.thoughtworks.qdox.model.JavaSource;

/**
 * Enhance UIMA components with automatically generated uimaFIT annotations.
 */
@Mojo(name = "enhance", defaultPhase = LifecyclePhase.PROCESS_CLASSES, requiresDependencyResolution = ResolutionScope.COMPILE, requiresDependencyCollection = ResolutionScope.COMPILE)
public class EnhanceMojo extends AbstractMojo {
  @Component
  private MavenProject project;

  @Component
  private BuildContext buildContext;

  private ClassLoader componentLoader;

  /**
   * Override component description in generated descriptors.
   */
  @Parameter(defaultValue = "false", required = true)
  private boolean overrideComponentDescription;

  /**
   * Override version in generated descriptors.
   * 
   * @see #componentVersion
   */
  @Parameter(defaultValue = "false", required = true)
  private boolean overrideComponentVersion;

  /**
   * Version to use in generated descriptors.
   */
  @Parameter(defaultValue = "${project.version}", required = false)
  private String componentVersion;

  /**
   * Override vendor in generated descriptors.
   * 
   * @see #componentVendor
   */
  @Parameter(defaultValue = "false", required = true)
  private boolean overrideComponentVendor;

  /**
   * Vendor to use in generated descriptors.
   */
  @Parameter(defaultValue = "${project.organization.name}", required = false)
  private String componentVendor;

  /**
   * Override copyright in generated descriptors.
   * 
   * @see #componentCopyright
   */
  @Parameter(defaultValue = "false", required = true)
  private boolean overrideComponentCopyright;

  /**
   * Copyright to use in generated descriptors.
   */
  @Parameter(required = false)
  private String componentCopyright;

  /**
   * Source file encoding.
   */
  @Parameter(defaultValue = "${project.build.sourceEncoding}", required = true)
  private String encoding;

  /**
   * Generate a report of missing meta data in {@code $ project.build.directory}
   * /uimafit-missing-meta-data-report.txt}
   */
  @Parameter(defaultValue = "true", required = true)
  private boolean generateMissingMetaDataReport;

  /**
   * Fail on missing meta data. This setting has no effect unless
   * {@code generateMissingMetaDataReport} is enabled.
   */
  @Parameter(defaultValue = "false", required = true)
  private boolean failOnMissingMetaData;

  /**
   * Constant name prefixes used for parameters and external resources, e.g. "PARAM_".
   */
  @Parameter(required = false)
  private String[] parameterNameConstantPrefixes = { "PARAM_" };

  /**
   * Constant name prefixes used for parameters and external resources, e.g. "KEY_", and "RES_".
   */
  @Parameter(required = false)
  private String[] externalResourceNameConstantPrefixes = { "KEY_", "RES_" };

  /**
   * Start of a line containing a class name in the missing meta data report file
   */
  private static final String MARK_CLASS = "Class:";

  /**
   * Marker that no missing meta data report was found.
   */
  private static final String MARK_NO_MISSING_META_DATA = "No missing meta data was found.";

  public void execute() throws MojoExecutionException, MojoFailureException {
    // Get the compiled classes from this project
    String[] files = FileUtils.getFilesFromExtension(project.getBuild().getOutputDirectory(),
            new String[] { "class" });

    componentLoader = Util.getClassloader(project, getLog());

    // Set up class pool with all the project dependencies and the project classes themselves
    ClassPool classPool = new ClassPool(true);
    classPool.appendClassPath(new LoaderClassPath(componentLoader));

    // Set up map to keep a report per class.
    Multimap<String, String> reportData = LinkedHashMultimap.create();

    // Determine where to write the missing meta data report file
    File reportFile = new File(project.getBuild().getDirectory(),
            "uimafit-missing-meta-data-report.txt");

    // Read existing report
    if (generateMissingMetaDataReport) {
      readMissingMetaDataReport(reportFile, reportData);
    }

    // Remember the names of all examined components, whether processed or not.
    List<String> examinedComponents = new ArrayList<String>();

    int countAlreadyEnhanced = 0;
    int countEnhanced = 0;
    
    for (String file : files) {
      String clazzName = Util.getClassName(project, file);

      // Check if this is a UIMA component
      Class<?> clazz;
      try {
        clazz = componentLoader.loadClass(clazzName);

        // Do not process a class twice
        // UIMA-3853 workaround for IBM Java 8 beta 3
        if (clazz.getAnnotation(EnhancedClassFile.class) != null) {
          countAlreadyEnhanced++;
          getLog().debug("Class [" + clazzName + "] already enhanced");
          // Remember that class was examined
          examinedComponents.add(clazzName);
          continue;
        }

        // Only process UIMA components
        if (!Util.isComponent(componentLoader, clazz)) {
          continue;
        }
      } catch (ClassNotFoundException e) {
        getLog().warn("Cannot analyze class [" + clazzName + "]", e);
        continue;
      }

      // Remember that class was examined
      examinedComponents.add(clazzName);

      // Forget any previous missing meta data report we have on the class
      reportData.removeAll(clazzName);

      // Get the Javassist class
      CtClass ctClazz;
      try {
        ctClazz = classPool.get(clazzName);
      } catch (NotFoundException e) {
        throw new MojoExecutionException("Class [" + clazzName + "] not found in class pool: "
                + ExceptionUtils.getRootCauseMessage(e), e);
      }

      // Get the source file
      String sourceFile = getSourceFile(clazzName);

      // Try to extract parameter descriptions from JavaDoc in source file
      if (sourceFile != null) {
        countEnhanced++;
        getLog().debug("Enhancing class [" + clazzName + "]");

        // Parse source file so we can extract the JavaDoc
        JavaSource ast = parseSource(sourceFile);

        // Enhance meta data
        enhanceResourceMetaData(ast, clazz, ctClazz, reportData);

        // Enhance configuration parameters
        enhanceConfigurationParameter(ast, clazz, ctClazz, reportData);

        // Add the EnhancedClassFile annotation.
        markAsEnhanced(ctClazz);
      } else {
        getLog().warn("No source file found for class [" + clazzName + "]");
      }

      try {
        if (ctClazz.isModified()) {
          getLog().debug("Writing enhanced class [" + clazzName + "]");
          // Trying to work around UIMA-2611, see
          // http://stackoverflow.com/questions/13797919/javassist-add-method-and-invoke
          ctClazz.toBytecode();
          ctClazz.writeFile(project.getBuild().getOutputDirectory());
        } else {
          getLog().debug("No changes to class [" + clazzName + "]");
        }
      } catch (IOException e) {
        throw new MojoExecutionException("Enhanced class [" + clazzName + "] cannot be written: "
                + ExceptionUtils.getRootCauseMessage(e), e);
      } catch (CannotCompileException e) {
        throw new MojoExecutionException("Enhanced class [" + clazzName + "] cannot be compiled: "
                + ExceptionUtils.getRootCauseMessage(e), e);
      }
    }
    
    getLog().info(
            "Enhanced " + countEnhanced + " class" + (countEnhanced != 1 ? "es" : "") + " ("
                    + countAlreadyEnhanced + " already enhanced).");

    if (generateMissingMetaDataReport) {
      // Remove any classes from the report that are no longer part of the build
      List<String> deletedClasses = new ArrayList<String>(reportData.keySet());
      deletedClasses.removeAll(examinedComponents);
      reportData.removeAll(deletedClasses);

      // Write updated report
      writeMissingMetaDataReport(reportFile, reportData);

      if (failOnMissingMetaData && !reportData.isEmpty()) {
        throw new MojoFailureException("Component meta data missing. A report of the missing "
                + "meta data can be found in " + reportFile);
      }
    }
  }

  /**
   * Add the EnhancedClassFile annotation.
   */
  private void markAsEnhanced(CtClass aCtClazz) {
    ClassFile classFile = aCtClazz.getClassFile();
    ConstPool constPool = classFile.getConstPool();

    AnnotationsAttribute annoAttr = (AnnotationsAttribute) classFile
            .getAttribute(AnnotationsAttribute.visibleTag);

    // Create annotation attribute if it does not exist
    if (annoAttr == null) {
      annoAttr = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
    }

    // Create annotation if it does not exist
    Annotation a = new Annotation(EnhancedClassFile.class.getName(), constPool);

    // Replace annotation
    annoAttr.addAnnotation(a);

    // Replace annotation attribute
    classFile.addAttribute(annoAttr);
  }

  /**
   * Enhance resource meta data
   */
  private void enhanceResourceMetaData(JavaSource aAST, Class<?> aClazz, CtClass aCtClazz,
          Multimap<String, String> aReportData) {
    ClassFile classFile = aCtClazz.getClassFile();
    ConstPool constPool = classFile.getConstPool();

    AnnotationsAttribute annoAttr = (AnnotationsAttribute) classFile
            .getAttribute(AnnotationsAttribute.visibleTag);

    // Create annotation attribute if it does not exist
    if (annoAttr == null) {
      annoAttr = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
    }

    // Create annotation if it does not exist
    Annotation a = annoAttr.getAnnotation(ResourceMetaData.class.getName());
    if (a == null) {
      a = new Annotation(ResourceMetaData.class.getName(), constPool);
      // Add a name, otherwise there will be none in the generated descriptor.
      a.addMemberValue("name", new StringMemberValue(
              ResourceMetaDataFactory.getDefaultName(aClazz), constPool));
    }

    // Update description from JavaDoc
    String doc = Util.getComponentDocumentation(aAST, aClazz.getName());
    enhanceMemberValue(a, "description", doc, overrideComponentDescription,
            ResourceMetaDataFactory.getDefaultDescription(aClazz), constPool, aReportData, aClazz);

    // Update version
    enhanceMemberValue(a, "version", componentVersion, overrideComponentVersion,
            ResourceMetaDataFactory.getDefaultVersion(aClazz), constPool, aReportData, aClazz);

    // Update vendor
    enhanceMemberValue(a, "vendor", componentVendor, overrideComponentVendor,
            ResourceMetaDataFactory.getDefaultVendor(aClazz), constPool, aReportData, aClazz);

    // Update copyright
    enhanceMemberValue(a, "copyright", componentCopyright, overrideComponentCopyright,
            ResourceMetaDataFactory.getDefaultCopyright(aClazz), constPool, aReportData, aClazz);

    // Replace annotation
    annoAttr.addAnnotation(a);

    // Replace annotation attribute
    classFile.addAttribute(annoAttr);
  }

  /**
   * Set a annotation member value if no value is present, if the present value is the default
   * generated by uimaFIT or if a override is active.
   * 
   * @param aAnnotation
   *          an annotation
   * @param aName
   *          the name of the member value
   * @param aNewValue
   *          the value to set
   * @param aOverride
   *          set value even if it is already set
   * @param aDefault
   *          default value set by uimaFIT - if the member has this value, it is considered unset
   */
  private void enhanceMemberValue(Annotation aAnnotation, String aName, String aNewValue,
          boolean aOverride, String aDefault, ConstPool aConstPool,
          Multimap<String, String> aReportData, Class<?> aClazz) {
    String value = getStringMemberValue(aAnnotation, aName);
    boolean isEmpty = value.length() == 0;
    boolean isDefault = value.equals(aDefault);

    if (isEmpty || isDefault || aOverride) {
      if (aNewValue != null) {
        aAnnotation.addMemberValue(aName, new StringMemberValue(aNewValue, aConstPool));
        getLog().debug("Enhanced component meta data [" + aName + "]");
      } else {
        getLog().debug("No meta data [" + aName + "] found");
        aReportData.put(aClazz.getName(), "No meta data [" + aName + "] found");
      }
    } else {
      getLog().debug("Not overwriting component meta data [" + aName + "]");
    }
  }

  private String getStringMemberValue(Annotation aAnnotation, String aValue) {
    MemberValue v = aAnnotation.getMemberValue(aValue);
    if (v == null) {
      return "";
    } else {
      return ((StringMemberValue) v).getValue();
    }
  }

  /**
   * Enhance descriptions in configuration parameters.
   */
  private void enhanceConfigurationParameter(JavaSource aAST, Class<?> aClazz, CtClass aCtClazz,
          Multimap<String, String> aReportData) throws MojoExecutionException {
    // Get the parameter name constants
    Map<String, String> parameterNameFields = getParameterConstants(aClazz,
            parameterNameConstantPrefixes);
    Map<String, String> resourceNameFields = getParameterConstants(aClazz,
            externalResourceNameConstantPrefixes);

    // Fetch configuration parameters from the @ConfigurationParameter annotations in the
    // compiled class. We only need the fields in the class itself. Superclasses should be
    // enhanced by themselves.
    for (Field field : aClazz.getDeclaredFields()) {
      final String pname;
      final String type;
      final String pdesc;

      // Is this a configuration parameter?
      if (ConfigurationParameterFactory.isConfigurationParameterField(field)) {
        type = "parameter";
        // Extract configuration parameter information from the uimaFIT annotation
        pname = ConfigurationParameterFactory.createPrimitiveParameter(field).getName();
        // Extract JavaDoc for this resource from the source file
        pdesc = Util.getParameterDocumentation(aAST, field.getName(),
                parameterNameFields.get(pname));
      }

      // Is this an external resource?
      else if (ExternalResourceFactory.isExternalResourceField(field)) {
        type = "external resource";
        // Extract resource key from the uimaFIT annotation
        pname = ExternalResourceFactory.createExternalResourceDependency(field).getKey();
        // Extract JavaDoc for this resource from the source file
        pdesc = Util.getParameterDocumentation(aAST, field.getName(), 
                resourceNameFields.get(pname));
      } else {
        continue;
      }

      if (pdesc == null) {
        String msg = "No description found for " + type + " [" + pname + "]";
        getLog().debug(msg);
        aReportData.put(aClazz.getName(), msg);
        continue;
      }

      // Update the "description" field of the annotation
      try {
        CtField ctField = aCtClazz.getField(field.getName());
        AnnotationsAttribute annoAttr = (AnnotationsAttribute) ctField.getFieldInfo().getAttribute(
                AnnotationsAttribute.visibleTag);

        // Locate and update annotation
        if (annoAttr != null) {
          Annotation[] annotations = annoAttr.getAnnotations();

          // Update existing annotation
          for (Annotation a : annotations) {
            if (a.getTypeName().equals(
                    org.apache.uima.fit.descriptor.ConfigurationParameter.class.getName())
                    || a.getTypeName().equals(
                            org.apache.uima.fit.descriptor.ExternalResource.class.getName())
                    || a.getTypeName().equals("org.uimafit.descriptor.ConfigurationParameter")
                    || a.getTypeName().equals("org.uimafit.descriptor.ExternalResource")) {
              if (a.getMemberValue("description") == null) {
                a.addMemberValue("description", new StringMemberValue(pdesc, aCtClazz
                        .getClassFile().getConstPool()));
                getLog().debug("Enhanced description of " + type + " [" + pname + "]");
                // Replace updated annotation
                annoAttr.addAnnotation(a);
              } else {
                // Extract configuration parameter information from the uimaFIT annotation
                // We only want to override if the description is not set yet.
                getLog().debug("Not overwriting description of " + type + " [" + pname + "] ");
              }
            }
          }
        }

        // Replace annotations
        ctField.getFieldInfo().addAttribute(annoAttr);
      } catch (NotFoundException e) {
        throw new MojoExecutionException("Field [" + field.getName() + "] not found in byte code: "
                + ExceptionUtils.getRootCauseMessage(e), e);
      }
    }
  }

  /**
   * Get a map of parameter name to parameter name constant field, e.g. ("value",
   * Field("PARAM_VALUE")).
   */
  private Map<String, String> getParameterConstants(Class<?> aClazz, String[] aPrefixes) {
    Map<String, String> result = new HashMap<String, String>();
    for (Field f : aClazz.getFields()) {
      boolean hasPrefix = false;
      // Check if any of the registered prefixes matches
      for (String prefix : aPrefixes) {
        if (f.getName().startsWith(prefix)) {
          hasPrefix = true;
          break;
        }
      }

      // If none matched, continue
      if (!hasPrefix) {
        continue;
      }

      // If one matched, record the field
      try {
        String parameterName = (String) f.get(null);
        result.put(parameterName, f.getName());
      } catch (IllegalAccessException e) {
        getLog().warn(
                "Unable to access name constant field [" + f.getName() + "]: "
                        + ExceptionUtils.getRootCauseMessage(e), e);
      }
    }
    return result;
  }

  private JavaSource parseSource(String aSourceFile) throws MojoExecutionException {
    try {
      return Util.parseSource(aSourceFile, encoding);
    } catch (IOException e) {
      throw new MojoExecutionException("Unable to parse source file [" + aSourceFile + "]: "
              + ExceptionUtils.getRootCauseMessage(e), e);
    }
  }

  /**
   * Get the source file for the given class.
   * 
   * @return The path to the source file or {@code null} if no source file was found.
   */
  @SuppressWarnings("unchecked")
  private String getSourceFile(String aClassName) {
    String sourceName = aClassName.replace('.', '/') + ".java";

    for (String root : (List<String>) project.getCompileSourceRoots()) {
      File f = new File(root, sourceName);
      if (f.exists()) {
        return f.getPath();
      }
    }
    return null;
  }

  /**
   * Write a report on any meta data missing from components.
   */
  private void writeMissingMetaDataReport(File aReportFile, Multimap<String, String> aReportData)
          throws MojoExecutionException {
    String[] classes = aReportData.keySet().toArray(new String[aReportData.keySet().size()]);
    Arrays.sort(classes);

    PrintWriter out = null;
    FileUtils.mkdir(aReportFile.getParent());
    try {
      out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(aReportFile), encoding));

      if (classes.length > 0) {
        for (String clazz : classes) {
          out.printf("%s %s%n", MARK_CLASS, clazz);
          Collection<String> messages = aReportData.get(clazz);
          if (messages.isEmpty()) {
            out.printf("  No problems");
          } else {
            for (String message : messages) {
              out.printf("  %s%n", message);
            }
          }
          out.printf("%n");
        }
      } else {
        out.printf("%s%n", MARK_NO_MISSING_META_DATA);
      }
    } catch (IOException e) {
      throw new MojoExecutionException("Unable to write missing meta data report to ["
              + aReportFile + "]" + ExceptionUtils.getRootCauseMessage(e), e);
    } finally {
      IOUtils.closeQuietly(out);
    }
  }

  /**
   * Read the missing meta data report from a previous run.
   */
  private void readMissingMetaDataReport(File aReportFile, Multimap<String, String> aReportData)
          throws MojoExecutionException {
    if (!aReportFile.exists()) {
      // Ignore if the file is missing
      return;
    }

    LineIterator i = null;
    try {
      String clazz = null;
      i = IOUtils.lineIterator(new FileInputStream(aReportFile), encoding);
      while (i.hasNext()) {
        String line = i.next();
        // Report say there is no missing meta data
        if (line.startsWith(MARK_NO_MISSING_META_DATA)) {
          return;
        }
        // Line containing class name
        if (line.startsWith(MARK_CLASS)) {
          clazz = line.substring(MARK_CLASS.length()).trim();
        } else if (StringUtils.isBlank(line)) {
          // Empty line, ignore
        } else {
          // Line containing a missing meta data instance
          if (clazz == null) {
            throw new MojoExecutionException("Missing meta data report has invalid format.");
          }
          aReportData.put(clazz, line.trim());
        }
      }
    } catch (IOException e) {
      throw new MojoExecutionException("Unable to read missing meta data report: "
              + ExceptionUtils.getRootCauseMessage(e), e);
    } finally {
      LineIterator.closeQuietly(i);
    }
  }
}
