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

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
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.project.MavenProject;
import org.apache.sling.maven.htl.compiler.HTLClassInfo;
import org.apache.sling.maven.htl.compiler.HTLJavaImportsAnalyzer;
import org.apache.sling.maven.htl.compiler.ScriptCompilationUnit;
import org.apache.sling.scripting.sightly.compiler.CompilationResult;
import org.apache.sling.scripting.sightly.compiler.CompilerMessage;
import org.apache.sling.scripting.sightly.compiler.SightlyCompiler;
import org.apache.sling.scripting.sightly.java.compiler.ClassInfo;
import org.apache.sling.scripting.sightly.java.compiler.JavaClassBackendCompiler;
import org.apache.sling.scripting.sightly.java.compiler.JavaImportsAnalyzer;
import org.codehaus.plexus.util.Scanner;
import org.sonatype.plexus.build.incremental.BuildContext;

/**
 * Validates HTL scripts.
 */
@Mojo(
        name = "validate",
        defaultPhase = LifecyclePhase.COMPILE,
        threadSafe = true
)
public class ValidateMojo extends AbstractMojo {

    private static final String DEFAULT_INCLUDES = "**/*.html";
    private static final int _16K = 16384;

    @Component
    private BuildContext buildContext;

    @Parameter(defaultValue = "${project}", readonly = true, required = true)
    protected MavenProject project;

    /**
     * Defines the root folder where this Mojo expects to find Sightly scripts to validate.
     *
     * @since 1.0.0
     */
    @Parameter(property = "htl.sourceDirectory", defaultValue = "${project.build.sourceDirectory}")
    private File sourceDirectory;

    /**
     * List of files to include. Specified as fileset patterns which are relative to the input directory whose contents will be scanned
     * (see the sourceDirectory configuration option).
     *
     * @since 1.0.0
     */
    @Parameter(defaultValue = DEFAULT_INCLUDES)
    private String[] includes;

    /**
     * List of files to exclude. Specified as fileset patterns which are relative to the input directory whose contents will be scanned
     * (see the sourceDirectory configuration option).
     *
     * @since 1.0.0
     */
    @Parameter
    private String[] excludes;

    /**
     * If set to "true" it will fail the build on compiler warnings.
     *
     * @since 1.0.0
     */
    @Parameter(property = "htl.failOnWarnings", defaultValue = "false")
    private boolean failOnWarnings;

    /**
     * If set to "true" it will generate the Java classes resulted from transpiling the HTL scripts to Java. The generated classes will
     * be stored in the folder identified by the {@code generatedJavaClassesDirectory} parameter.
     *
     * @since 1.1.0
     */
    @Parameter(property = "htl.generateJavaClasses", defaultValue = "false")
    private boolean generateJavaClasses;

    /**
     * Defines the folder where the generated Java classes resulted from transpiling the project's HTL scripts will be stored. This
     * folder will be added to the list of source folders for this project.
     *
     * @since 1.1.0
     */
    @Parameter(property = "htl.generatedJavaClassesDirectory", defaultValue = "${project.build.directory}/generated-sources/htl")
    private File generatedJavaClassesDirectory;

    /**
     * Defines the package prefix under which the HTL compilers will generate the Java classes. By default the plugin doesn't provide any
     * prefix.
     *
     * @since 1.2.0-1.4.0
     */
    @Parameter(property = "htl.generatedJavaClassesPrefix")
    private String generatedJavaClassesPrefix;

    /**
     * Defines a list of Java packages that should be ignored when generating the import statements for the Java classes resulted from
     * transpiling the project's HTL scripts. Subpackages of these packages will also be part automatically of the ignore list.
     *
     * @since 1.1.0
     */
    @Parameter(property = "htl.ignoreImports")
    private Set<String> ignoreImports;

    /**
     * If set to "true" the validation will be skipped.
     *
     * @since 1.0.2
     */
    @Parameter(property = "htl.skip", defaultValue = "false")
    private boolean skip;

    private boolean hasWarnings = false;
    private boolean hasErrors = false;
    private List<File> processedFiles = Collections.emptyList();

    public void execute() throws MojoExecutionException, MojoFailureException {
        if (skip) {
            getLog().info("Skipping validation.");
            return;
        }

        long start = System.currentTimeMillis();

        if (!sourceDirectory.isAbsolute()) {
            sourceDirectory = new File(project.getBasedir(), sourceDirectory.getPath());
        }
        if (!sourceDirectory.exists()) {
            getLog().info("Source directory does not exist, skipping.");
            return;
        }
        if (!sourceDirectory.isDirectory()) {
            throw new MojoExecutionException(
                    String.format("Configured sourceDirectory={%s} is not a directory.", sourceDirectory.getAbsolutePath()));
        }
        if (generateJavaClasses) {
            // validate generated Java classes folder
            if (!generatedJavaClassesDirectory.isAbsolute()) {
                generatedJavaClassesDirectory = new File(project.getBasedir(), generatedJavaClassesDirectory.getPath());
            }
            if (generatedJavaClassesDirectory.exists() && !generatedJavaClassesDirectory.isDirectory()) {
                throw new MojoExecutionException(String.format("Configured generatedJavaClassesDirectory={%s} is not a directory.",
                        generatedJavaClassesDirectory.getAbsolutePath()));
            }
            if (!generatedJavaClassesDirectory.exists()) {
                if (!generatedJavaClassesDirectory.mkdirs()) {
                    throw new MojoExecutionException(String.format("Unable to generate generatedJavaClassesDirectory={%s}.",
                            generatedJavaClassesDirectory.getAbsolutePath()));
                }
            }
            project.addCompileSourceRoot(generatedJavaClassesDirectory.getPath());
        }

        if (!buildContext.hasDelta(sourceDirectory)) {
            getLog().info("No files found to validate, skipping.");
            return;
        }

        // don't fail execution in Eclipse as it generates an error marker in the POM file, which is not desired
        boolean mayFailExecution = !buildContext.getClass().getName().startsWith("org.eclipse.m2e");

        try {
            Scanner scanner = buildContext.newScanner(sourceDirectory);
            scanner.setExcludes(excludes);
            scanner.setIncludes(includes);
            scanner.scan();

            String[] includedFiles = scanner.getIncludedFiles();

            processedFiles = new ArrayList<>(includedFiles.length);
            for (String includedFile : includedFiles) {
                processedFiles.add(new File(sourceDirectory, includedFile));
            }
            Map<File, CompilationResult> compilationResults;
            if (generateJavaClasses) {
                compilationResults = transpileHTLScriptsToJavaClasses(processedFiles, new SightlyCompiler(), new HTLJavaImportsAnalyzer
                        (ignoreImports));
            } else {
                compilationResults = compileHTLScripts(processedFiles, new SightlyCompiler());
            }
            for (Map.Entry<File, CompilationResult> entry : compilationResults.entrySet()) {
                File script = entry.getKey();
                CompilationResult result = entry.getValue();
                buildContext.removeMessages(script);

                if (result.getWarnings().size() > 0) {
                    for (CompilerMessage message : result.getWarnings()) {
                        buildContext.addMessage(script, message.getLine(), message.getColumn(), message.getMessage(),
                                BuildContext.SEVERITY_WARNING, null);
                    }
                    hasWarnings = true;
                }
                if (result.getErrors().size() > 0) {
                    for (CompilerMessage message : result.getErrors()) {
                        String messageString = message.getMessage().replaceAll(System.lineSeparator(), "");
                        buildContext
                                .addMessage(script, message.getLine(), message.getColumn(), messageString, BuildContext.SEVERITY_ERROR,
                                        null);
                    }
                    hasErrors = true;
                }
            }

            getLog().info("Processed " + processedFiles.size() + " files in " + (System.currentTimeMillis() - start) + "ms");

            if (mayFailExecution && hasWarnings && failOnWarnings) {
                throw new MojoFailureException("Compilation warnings were configured to fail the build.");
            }
            if (mayFailExecution && hasErrors) {
                throw new MojoFailureException("Please check the reported syntax errors.");
            }
        } catch (IOException e) {
            throw new MojoExecutionException(String.format("Cannot filter files from {%s} with includes {%s} and excludes {%s}.",
                    sourceDirectory.getAbsolutePath(), Arrays.asList(includes), Arrays.asList(excludes)), e);
        }

    }

    private Map<File, CompilationResult> transpileHTLScriptsToJavaClasses(List<File> scripts, SightlyCompiler compiler, JavaImportsAnalyzer
            javaImportsAnalyzer) throws IOException {
        Map<File, CompilationResult> compilationResult = new LinkedHashMap<>(scripts.size());
        for (File script : scripts) {
            JavaClassBackendCompiler backendCompiler = new JavaClassBackendCompiler(javaImportsAnalyzer);
            ScriptCompilationUnit compilationUnit = new ScriptCompilationUnit(sourceDirectory, script);
            compilationResult.put(script, compiler.compile(compilationUnit, backendCompiler));
            
            // strip off source directory path from script path for class info
            File scriptFile = new File(script.getPath());
            File sourceDirectoryDir = new File(sourceDirectory.getAbsolutePath());
            String shortenedScriptPath = StringUtils.substringAfter(scriptFile.getCanonicalPath(), sourceDirectoryDir.getCanonicalPath());
            
            ClassInfo classInfo = StringUtils.isNotEmpty(generatedJavaClassesPrefix)? new HTLClassInfo(generatedJavaClassesPrefix,
                    shortenedScriptPath) : new HTLClassInfo(shortenedScriptPath);
            String javaSourceCode = backendCompiler.build(classInfo);
            File generatedClassFile = new File(generatedJavaClassesDirectory, classInfo.getFullyQualifiedClassName()
                    .replaceAll("\\.", Matcher.quoteReplacement(File.separator)) + ".java");
            FileUtils.forceMkdirParent(generatedClassFile);
            IOUtils.write(javaSourceCode, new FileOutputStream(generatedClassFile), StandardCharsets.UTF_8);
            compilationUnit.dispose();
        }
        return compilationResult;
    }

    private Map<File, CompilationResult> compileHTLScripts(List<File> scripts, SightlyCompiler compiler) throws IOException {
        Map<File, CompilationResult> compilationResult = new LinkedHashMap<>(scripts.size());
        for (File script : scripts) {
            ScriptCompilationUnit scriptCompilationUnit = new ScriptCompilationUnit(sourceDirectory, script);
            compilationResult.put(script, compiler.compile(scriptCompilationUnit));
            scriptCompilationUnit.dispose();
        }
        return compilationResult;
    }
    // visible for testing only
    void setBuildContext(BuildContext buildContext) {
        this.buildContext = buildContext;
    }

    boolean hasWarnings() {
        return hasWarnings;
    }

    boolean hasErrors() {
        return hasErrors;
    }

    List<File> getProcessedFiles() {
        return processedFiles;
    }
}
