/*
 * 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.rat.mp;

import static org.apache.rat.mp.util.ConfigurationHelper.newInstance;
import static org.apache.rat.mp.util.ExclusionHelper.addEclipseDefaults;
import static org.apache.rat.mp.util.ExclusionHelper.addIdeaDefaults;
import static org.apache.rat.mp.util.ExclusionHelper.addMavenDefaults;
import static org.apache.rat.mp.util.ExclusionHelper.addPlexusAndScmDefaults;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.xml.transform.TransformerConfigurationException;


import org.apache.commons.io.IOUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.rat.Defaults;
import org.apache.rat.Report;
import org.apache.rat.ReportConfiguration;
import org.apache.rat.analysis.IHeaderMatcher;
import org.apache.rat.analysis.util.HeaderMatcherMultiplexer;
import org.apache.rat.api.RatException;
import org.apache.rat.config.SourceCodeManagementSystems;
import org.apache.rat.license.ILicenseFamily;
import org.apache.rat.mp.util.ScmIgnoreParser;
import org.apache.rat.report.IReportable;
import org.apache.rat.report.claim.ClaimStatistic;
import org.codehaus.plexus.util.DirectoryScanner;

/**
 * Abstract base class for Mojos, which are running Rat.
 */
public abstract class AbstractRatMojo extends AbstractMojo {

    /**
     * The base directory, in which to search for files.
     */
    @Parameter(property = "rat.basedir", defaultValue = "${basedir}", required = true)
    private File basedir;

    /**
     * Specifies the licenses to accept. Deprecated, use {@link #licenses}
     * instead.
     *
     * @deprecated Use {@link #licenses} instead.
     */
    @Deprecated
    @Parameter
    private HeaderMatcherSpecification[] licenseMatchers;

    /**
     * Specifies the licenses to accept. By default, these are added to the
     * default licenses, unless you set {@link #addDefaultLicenseMatchers} to
     * false.
     *
     * @since 0.8
     */
    @Parameter
    private IHeaderMatcher[] licenses;

    /**
     * The set of approved license family names.
     *
     * @deprecated Use {@link #licenseFamilies} instead.
     */
    @Deprecated
    private LicenseFamilySpecification[] licenseFamilyNames;

    /**
     * Specifies the license families to accept.
     *
     * @since 0.8
     */
    @Parameter
    private ILicenseFamily[] licenseFamilies;

    /**
     * Whether to add the default list of license matchers.
     */
    @Parameter(property = "rat.addDefaultLicenseMatchers", defaultValue = "true")
    private boolean addDefaultLicenseMatchers;

    /**
     * Specifies files, which are included in the report. By default, all files
     * are included.
     */
    @Parameter
    private String[] includes;

    /**
     * Specifies a file, from which to read includes. Basically, an alternative to
     * specifying the includes as a list.
     */
    @Parameter(property="rat.includesFile")
    private String includesFile;

    /**
     * Specifies the include files character set. Defaults to @code{${project.build.sourceEncoding}),
     * or @code{UTF8}.
     */
    @Parameter(property="rat.includesFileCharset", defaultValue="${project.build.sourceEncoding}")
    private String includesFileCharset;
    
    /**
     * Specifies files, which are excluded in the report. By default, no files
     * are excluded.
     */
    @Parameter
    private String[] excludes;

    /**
     * Specifies a file, from which to read excludes. Basically, an alternative to
     * specifying the excludes as a list.  The excludesFile is assumed to be using the
     * UFT8 character set.
     */
    @Parameter(property="rat.excludesFile")
    private String excludesFile;

    /**
     * Specifies the include files character set. Defaults to @code{${project.build.sourceEncoding}),
     * or @code{UTF8}.
     */
    @Parameter(property="rat.excludesFileCharset", defaultValue="${project.build.sourceEncoding}")
    private String excludesFileCharset;

    /**
     * Whether to use the default excludes when scanning for files. The default
     * excludes are:
     * <ul>
     * <li>meta data files for source code management / revision control systems,
     * see {@link SourceCodeManagementSystems}</li>
     * <li>temporary files used by Maven, see <a
     * href="#useMavenDefaultExcludes">useMavenDefaultExcludes</a></li>
     * <li>configuration files for Eclipse, see <a
     * href="#useEclipseDefaultExcludes">useEclipseDefaultExcludes</a></li>
     * <li>configuration files for IDEA, see <a
     * href="#useIdeaDefaultExcludes">useIdeaDefaultExcludes</a></li>
     * </ul>
     */
    @Parameter(property = "rat.useDefaultExcludes", defaultValue = "true")
    private boolean useDefaultExcludes;

    /**
     * Whether to use the Maven specific default excludes when scanning for
     * files. Maven specific default excludes are given by the constant
     * MAVEN_DEFAULT_EXCLUDES: The <code>target</code> directory, the
     * <code>cobertura.ser</code> file, and so on.
     */
    @Parameter(property = "rat.useMavenDefaultExcludes", defaultValue = "true")
    private boolean useMavenDefaultExcludes;

    /**
     * Whether to parse source code management system (SCM) ignore files and use their contents as excludes.
     * At the moment this works for the following SCMs:
     *
     * @see org.apache.rat.config.SourceCodeManagementSystems
     */
    @Parameter(property = "rat.parseSCMIgnoresAsExcludes", defaultValue = "true")
    private boolean parseSCMIgnoresAsExcludes;

    /**
     * Whether to use the Eclipse specific default excludes when scanning for
     * files. Eclipse specific default excludes are given by the constant
     * ECLIPSE_DEFAULT_EXCLUDES: The <code>.classpath</code> and
     * <code>.project</code> files, the <code>.settings</code> directory, and so
     * on.
     */
    @Parameter(property = "rat.useEclipseDefaultExcludes", defaultValue = "true")
    private boolean useEclipseDefaultExcludes;

    /**
     * Whether to use the IDEA specific default excludes when scanning for
     * files. IDEA specific default excludes are given by the constant
     * IDEA_DEFAULT_EXCLUDES: The <code>*.iml</code>, <code>*.ipr</code> and
     * <code>*.iws</code> files and the <code>.idea</code> directory.
     */
    @Parameter(property = "rat.useIdeaDefaultExcludes", defaultValue = "true")
    private boolean useIdeaDefaultExcludes;

    /**
     * Whether to exclude subprojects. This is recommended, if you want a
     * separate apache-rat-plugin report for each subproject.
     */
    @Parameter(property = "rat.excludeSubprojects", defaultValue = "true")
    private boolean excludeSubProjects;

    /**
     * Will skip the plugin execution, e.g. for technical builds that do not take license compliance into account.
     *
     * @since 0.11
     */
    @Parameter(property = "rat.skip", defaultValue = "false")
    protected boolean skip;

    /**
     * Holds the maven-internal project to allow resolution of artifact properties during mojo runs.
     */
    @Parameter(defaultValue = "${project}", required = true, readonly = true)
    private MavenProject project;

    /**
     * @return Returns the Maven project.
     */
    protected MavenProject getProject() {
        return project;
    }

    /**
     * Returns the set of {@link IHeaderMatcher header matchers} to use.
     *
     * @return list of license matchers to use
     * @throws MojoFailureException   An error in the plugin configuration was detected.
     * @throws MojoExecutionException An error occurred while calculating the result.
     */
    private List<IHeaderMatcher> mergeLicenseMatchers()
            throws MojoFailureException, MojoExecutionException {
        List<IHeaderMatcher> matchers = new ArrayList<IHeaderMatcher>();

        if (licenses != null) {
            matchers.addAll(Arrays.asList(licenses));
            getLog().info("Added " + licenses.length + " additional default licenses.");
        }

        if (licenseMatchers != null) {
            for (final HeaderMatcherSpecification spec : licenseMatchers) {
                matchers.add(newInstance(IHeaderMatcher.class, spec.getClassName()));
            }
        }

        if (addDefaultLicenseMatchers) {
            getLog().info("Enabled default license matchers.");
            matchers.addAll(Defaults.DEFAULT_MATCHERS);
        }
        logLicenseMatchers(matchers);

        return matchers;
    }

    private void logLicenseMatchers(List<IHeaderMatcher> matchers) {
        if (getLog().isDebugEnabled()) {
            getLog().debug("The following license matchers are activated:");
            for (IHeaderMatcher matcher : matchers) {
                getLog().debug("* " + matcher.toString());
            }
        }

    }

    /**
     * Creates an iterator over the files to check.
     *
     * @return A container of files, which are being checked.
     */
    protected IReportable getResources() throws MojoExecutionException {
        final DirectoryScanner ds = new DirectoryScanner();
        ds.setBasedir(basedir);
        setExcludes(ds);
        setIncludes(ds);
        ds.scan();
        whenDebuggingLogExcludedFiles(ds);
        final String[] files = ds.getIncludedFiles();
        logAboutIncludedFiles(files);
        try {
            return new FilesReportable(basedir, files);
        } catch (final IOException e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    private void logAboutIncludedFiles(final String[] files) {
        if (files.length == 0) {
            getLog().warn("No resources included.");
        } else {
            getLog().info(
                    files.length
                            + " resources included (use -debug for more details)");
            if (getLog().isDebugEnabled()) {
                for (final String resource : files) {
                    getLog().debug(" - included " + resource);
                }
            }
        }
    }

    private void whenDebuggingLogExcludedFiles(final DirectoryScanner ds) {
        if (getLog().isDebugEnabled()) {
            final String[] excludedFiles = ds.getExcludedFiles();
            if (excludedFiles.length == 0) {
                getLog().debug("No excluded resources.");
            } else {
                getLog().debug(
                        "Excluded " + excludedFiles.length + " resources:");
                for (final String resource : excludedFiles) {
                    getLog().debug(" - excluded " + resource);
                }
            }
        }
    }

    private void setIncludes(DirectoryScanner ds) throws MojoExecutionException {
        if ((includes != null  &&  includes.length > 0)  ||  includesFile != null) {
        	final List<String> includeList = new ArrayList<String>();
        	if (includes != null) {
        		includeList.addAll(Arrays.asList(includes));
        	}
        	if (includesFile != null) {
        		final String charset = includesFileCharset == null ? "UTF8" : includesFileCharset;
        		final File f = new File(includesFile);
        		if (!f.isFile()) {
        			getLog().error("IncludesFile not found: " + f.getAbsolutePath());
        		} else {
        			getLog().info("Includes loaded from file " + includesFile + ", using character set " + charset);
        		}
        		includeList.addAll(getPatternsFromFile(f, charset));
        	}
            ds.setIncludes(includeList.toArray(new String[includeList.size()]));
        }
    }

    private List<String> getPatternsFromFile(File pFile, String pCharset) throws MojoExecutionException {
    	InputStream is = null;
    	BufferedInputStream bis = null;
    	Reader r = null;
    	BufferedReader br = null;
    	Throwable th = null;
    	final List<String> patterns = new ArrayList<String>();
    	try {
    		is = new FileInputStream(pFile);
    		bis = new BufferedInputStream(is);
    		r = new InputStreamReader(bis, pCharset);
    		br = new BufferedReader(r);
    		for (;;) {
    			final String s = br.readLine();
    			if (s == null) {
    				break;
    			}
    			patterns.add(s);
    		}
    		br.close();
    		br = null;
    		r.close();
    		r = null;
    		bis.close();
    		bis = null;
    		is.close();
    		is = null;
    	} catch (Throwable t) {
    		th = t;
    	} finally {
    		if (br != null) { try { br.close(); } catch (Throwable t) { if (th == null) { th = t; } } }
    		if (r != null) { try { r.close(); } catch (Throwable t) { if (th == null) { th = t; } } }
    		if (bis != null) { try { bis.close(); } catch (Throwable t) { if (th == null) { th = t; } } }
    		if (is != null) { try { is.close(); } catch (Throwable t) { if (th == null) { th = t; } } }
    	}
    	if (th != null) {
    		if (th instanceof RuntimeException) { throw (RuntimeException) th; }
    		if (th instanceof Error) { throw (Error) th; }
    		throw new MojoExecutionException(th.getMessage(), th);
    	}
    	return patterns;
    }
    
    private void setExcludes(DirectoryScanner ds) throws MojoExecutionException {
        final List<String> excludeList = mergeDefaultExclusions();
        if (excludes == null || excludes.length == 0) {
            getLog().info("No excludes explicitly specified.");
        } else {
        	for (final String exclude : excludes) {
                getLog().info("Exclude: " + exclude);
            }
        }
        if (excludes != null) {
            Collections.addAll(excludeList, excludes);
        }
        if (!excludeList.isEmpty()) {
            final String[] allExcludes = excludeList.toArray(new String[excludeList
                    .size()]);
            ds.setExcludes(allExcludes);
        }
    }

    private List<String> mergeDefaultExclusions() throws MojoExecutionException {
        final Set<String> results = new HashSet<String>();

        addPlexusAndScmDefaults(getLog(), useDefaultExcludes, results);
        addMavenDefaults(getLog(), useMavenDefaultExcludes, results);
        addEclipseDefaults(getLog(), useEclipseDefaultExcludes, results);
        addIdeaDefaults(getLog(), useIdeaDefaultExcludes, results);

        if (parseSCMIgnoresAsExcludes) {
            getLog().info("Will parse SCM ignores for exclusions...");
            results.addAll(ScmIgnoreParser.getExclusionsFromSCM(getLog(), project.getBasedir()));
            getLog().info("Finished adding exclusions from SCM ignore files.");
        }

        if (excludeSubProjects && project != null
                && project.getModules() != null) {
            for (final Object o : project.getModules()) {
                final String moduleSubPath = (String) o;
                results.add(moduleSubPath + "/**/*");
            }
        }

        getLog().debug("Finished creating list of implicit excludes.");
        if (results.isEmpty()) {
            getLog().info("No excludes implicitly specified.");
        } else {
            getLog().info(
                    results.size()
                            + " implicit excludes (use -debug for more details).");
            for (final String exclude : results) {
                getLog().debug("Implicit exclude: " + exclude);
            }
        }
        if (excludesFile != null) {
        	final File f = new File(excludesFile);
        	if (!f.isFile()) {
        		getLog().error("Excludes file not found: " + f.getAbsolutePath());
        	}
        	if (!f.canRead()) {
        		getLog().error("Excludes file not readable: " + f.getAbsolutePath());
        	}
        	final String charset = excludesFileCharset == null ? "UTF8" : excludesFileCharset;
        	getLog().info("Loading excludes from file " + f + ", using character set " + charset);
        	results.addAll(getPatternsFromFile(f, charset));
        }

        return new ArrayList<String>(results);
    }

    /**
     * Creates the report as a string.
     *
     * @param styleSheet The style sheet to use when formatting the report
     * @return Report contents
     * @throws MojoFailureException   An error in the plugin configuration was detected.
     * @throws MojoExecutionException An error occurred while creating the report.
     */
    protected String createReport(InputStream styleSheet)
            throws MojoExecutionException, MojoFailureException {
        StringWriter sw = new StringWriter();
        PrintWriter pw = null;
        try {
            pw = new PrintWriter(sw);
            createReport(new PrintWriter(sw), styleSheet);
            final String result = sw.toString();
            pw.close();
            pw = null;
            sw.close();
            sw = null;
            return result;
        } catch (IOException e) {
            throw new MojoExecutionException(e.getMessage(), e);
        } finally {
            IOUtils.closeQuietly(pw);
            IOUtils.closeQuietly(sw);
        }
    }

    /**
     * Writes the report to the given stream.
     *
     * @param out   The target writer, to which the report is being written.
     * @param style The stylesheet to use, or <code>null</code> for raw XML
     * @return the current statistic.
     * @throws MojoFailureException   An error in the plugin configuration was detected.
     * @throws MojoExecutionException Another error occurred while creating the report.
     */
    protected ClaimStatistic createReport(Writer out, InputStream style)
            throws MojoExecutionException, MojoFailureException {
        final ReportConfiguration configuration = getConfiguration();
        try {
            if (style != null) {
                return Report.report(out, getResources(), style, configuration);
            } else {
                return Report.report(getResources(), out, configuration);
            }
        } catch (final TransformerConfigurationException e) {
            throw new MojoExecutionException(e.getMessage(), e);
        } catch (final IOException e) {
            throw new MojoExecutionException(e.getMessage(), e);
        } catch (final InterruptedException e) {
            throw new MojoExecutionException(e.getMessage(), e);
        } catch (final RatException e) {
            throw new MojoExecutionException(e.getMessage(), e);
        }
    }

    protected ReportConfiguration getConfiguration()
            throws MojoFailureException, MojoExecutionException {
        final ReportConfiguration configuration = new ReportConfiguration();
        configuration.setHeaderMatcher(new HeaderMatcherMultiplexer(
                mergeLicenseMatchers()));
        configuration.setApprovedLicenseNames(mergeApprovedLicenseNames());
        configuration.setApproveDefaultLicenses(addDefaultLicenseMatchers);
        return configuration;
    }

    private List<ILicenseFamily> mergeApprovedLicenseNames()
            throws MojoExecutionException, MojoFailureException {
        final List<ILicenseFamily> list = new ArrayList<ILicenseFamily>();
        if (licenseFamilies != null) {
            getLog().info("Added " + licenseFamilies.length + " custom approved licenses.");
            list.addAll(Arrays.asList(licenseFamilies));
        }
        if (licenseFamilyNames != null) {
            for (final LicenseFamilySpecification spec : licenseFamilyNames) {
                list.add(newInstance(ILicenseFamily.class, spec.getClassName()));
            }
        }
        return list;
    }
}
