/*
 * 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.jdo.exectck;

import java.net.MalformedURLException;
import java.nio.charset.Charset;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.io.FileUtils;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import javax.jdo.JDOEnhancer;
import javax.jdo.JDOHelper;

/**
 * Goal that enhances test classes for testing a JDO implementation.
 */
@Mojo( name = "enhance" )
public class Enhance extends AbstractTCKMojo {

    private static final String[] PC_PKG_DIRS = {
        "org" + File.separator + "apache" + File.separator + "jdo" + File.separator + "tck" + File.separator + "api" + File.separator,
        "org" + File.separator + "apache" + File.separator + "jdo" + File.separator + "tck" + File.separator + "pc" + File.separator,
        "org" + File.separator + "apache" + File.separator + "jdo" + File.separator + "tck" + File.separator + "models" + File.separator + "inheritance" + File.separator
    };
    /**
     * Location of TCK generated output.
     */
    @Parameter( property = "jdo.tck.doEnhance", defaultValue = "true", required = true)
    private boolean doEnhance;

    /**
     * Root of the TCK source installation.
     */
    @Parameter( property = "project.src.directory", defaultValue = "${basedir}/src/main/resources", required = true)
    private String srcDirectory;

    /**
     * List of identity types to be tested.
     */
    @Parameter( property = "jdo.tck.identitytypes", defaultValue = "applicationidentity datastoreidentity", required = true)
    private String identitytypes;

    private Collection<String> idtypes;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {

        if (!doEnhance) {
            System.out.println("Skipping Enhance goal!");
            return;
        }

        idtypes = new HashSet<String>();
        PropertyUtils.string2Set(identitytypes, idtypes);

        // Reset logfile content (may not be empty if previous run crashed)
        resetFileContent(implLogFile);

        // Create directory for enhancer logs
        String enhanceLogsDirName = logsDirectory + File.separator + "enhanced";
        File enhancerLogsDir = new File(enhanceLogsDirName);
        if (!(enhancerLogsDir.exists()) && !(enhancerLogsDir.mkdirs())) {
            throw new MojoExecutionException("Failed to create directory "
                    + enhancerLogsDir);
        }

        try {
            copyLog4j2ConfigurationFile();
        } catch (IOException ex) {
            Logger.getLogger(Enhance.class.getName()).log(Level.SEVERE, null, ex);
        }

        // Create directory for enhanced classes
        String enhancedDirName = buildDirectory + File.separator + "enhanced"
                + File.separator + impl + File.separator;
        File enhancedDir = new File(enhancedDirName);
        if (!(enhancedDir.exists()) && !(enhancedDir.mkdirs())) {
            throw new MojoExecutionException("Failed to create directory "
                    + enhancedDir);
        }

        String[] metadataExtensions = {"jdo", "jdoquery", "orm", "xml", "properties"};
        String[] srcDirs = {"jdo", "orm", "testdata"};
        File toFile = null;
        File fromFile = null;
        String fromFileName = null;
        String pkgName = null;
        int startIdx = -1;
        Iterator<File> fi = null;
        String[] classArray = new String[10];
        String enhancedIdDirName = null;
        String classesDirName = buildDirectory + File.separator
                        + "classes" + File.separator;
        ArrayList<String> classes = null;

        // Copy metadata from src to enhanced
        for (String idtype : idtypes) {
            for (String srcDir : srcDirs) {
                String srcDirName = srcDirectory + File.separator + srcDir;
                // iterator over list of abs name of metadata files in src
                fi = FileUtils.iterateFiles(
                        new File(srcDirName), metadataExtensions, true);

                while (fi.hasNext()) {
                    try {
                        fromFile = fi.next();
                        fromFileName = fromFile.toString();
                        if ((startIdx = fromFileName.indexOf(idtype + File.separator)) > -1) {
                            // fully specified name of file (idtype + package + filename)
                            pkgName = fromFileName.substring(startIdx);
                            toFile = new File(enhancedDirName + File.separator
                                    + pkgName);
                            FileUtils.copyFile(fromFile, toFile);
                        } else if (srcDir.equals("testdata")) {
                            startIdx = fromFileName.indexOf("org" + File.separator);
                            pkgName = fromFileName.substring(startIdx);
                            toFile = new File(enhancedDirName + File.separator
                                    + idtype + File.separator + pkgName);
                            FileUtils.copyFile(fromFile, toFile);
                        } else {
                            continue;  // idtype not in pathname, do not copy
                        }
                    } catch (IOException ex) {
                        throw new MojoExecutionException("Failed to copy files from "
                                + fromFileName + " to " + toFile.toString()
                                + ": " + ex.getLocalizedMessage());
                    }
                }

                // Copy pc and pa classes from target/classes to enhanced
                String[] extensions = {"class"};
                enhancedIdDirName = enhancedDirName + idtype + File.separator;
                classes = new ArrayList<String>();
                for (String pcPkgName : PC_PKG_DIRS) {
                    // iterator over list of abs name of class files in target/classes
                    fi = FileUtils.iterateFiles(
                            new File(classesDirName + pcPkgName), extensions, true);
                    while (fi.hasNext()) {
                        try {
                            fromFile = fi.next();
                            fromFileName = fromFile.toString();
                            // fully specified name of file (package + filename)
                            int index = fromFileName.indexOf(pcPkgName);
                            if (index == -1) {
                                throw new MojoExecutionException(
                                        "Cannot get index of package path " + pcPkgName
                                        + " in file name" + fromFileName);
                            }
                            toFile = new File(enhancedIdDirName + fromFileName.substring(index));
                            FileUtils.copyFile(fromFile, toFile);
                            classes.add(toFile.toString());
                        } catch (IOException ex) {
                            throw new MojoExecutionException("Failed to copy files from "
                                    + fromFileName + " to " + toFile.toString()
                                    + ": " + ex.getLocalizedMessage());
                        }
                    }
                }
            }

            // Enhance classes

            // Build ClassLoader for finding enhancer
            URL[] classPathURLs1 = new URL[2];
            ArrayList<URL> cpList1 = new ArrayList<URL>();
            ClassLoader enhancerLoader = null;
            try {
                // Must add enhancedIdDirName first!!
                cpList1.add((new File(enhancedIdDirName)).toURI().toURL());
                cpList1.add((new File(classesDirName)).toURI().toURL());
                for (String dependency : this.dependencyClasspath.split(File.pathSeparator)) {
                    cpList1.add(new File(dependency).toURI().toURL());
                }
                enhancerLoader = new URLClassLoader(cpList1.toArray(classPathURLs1),
                        getClass().getClassLoader());
                System.out.println("ClassLoader enhancerLoader:");
                Utilities.printClasspath(enhancerLoader);
            } catch (MalformedURLException ex) {
                Logger.getLogger(Enhance.class.getName()).log(Level.SEVERE, null, ex);
            }
            
            // Context classloader for finding log4j2 configuration
            ClassLoader prevCl = Thread.currentThread().getContextClassLoader();
            try {
                URL enhancedClassesUrl = (new File(enhancedIdDirName)).toURI().toURL();
                // Classes dir needed for org.apache.jdo.tck.util.TCKFileAppender
                URL classesUrl = (new File(classesDirName)).toURI().toURL();
                ClassLoader loggingPropsCl =
                        URLClassLoader.newInstance(new URL[]{
                        enhancedClassesUrl, classesUrl}, prevCl);
                Thread.currentThread().setContextClassLoader(loggingPropsCl);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("ClassLoader ContextClassLoader:");
            Utilities.printClasspath(Thread.currentThread().getContextClassLoader());
            System.out.println("Get enhancer");
            JDOEnhancer enhancer = JDOHelper.getEnhancer(enhancerLoader);
            System.out.println("enhancer.setVerbose()");
            enhancer.setVerbose(true);
            System.out.println("enhancer.setClassLoader()");
            enhancer.setClassLoader(enhancerLoader);
            String[] classArr = classes.toArray(classArray);
            enhancer.addClasses(classArr);
            System.out.println("Enhancing classes for identity type " + idtype);
            // enhancer needs  org/apache/jdo/tck/util/DeepEquality
            enhancer.enhance();
            Thread.currentThread().setContextClassLoader(prevCl);

            // Move log to per-test location
            String idname = "dsid";
            if (idtype.trim().equals("applicationidentity")) {
                idname = "app";
            }
            String testLogFilename = logsDirectory + File.separator +
                    "enhanced" + File.separator + idname +
                    "-" + impl + ".txt";
            System.out.println("testLogFilename is " + testLogFilename);
            try {
                File logFile = new File(implLogFile);
                File testLogFile = new File(testLogFilename);
                FileUtils.copyFile(logFile, testLogFile);
                // reset file content
                FileUtils.write(logFile, "", Charset.defaultCharset());
                FileUtils.forceDeleteOnExit(logFile);
            } catch (Exception e) {
                System.out.println(">> Error moving implementation log file: " +
                    e.getMessage());
            }
        }
        System.out.println("");
    }
}
