/*
 * 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 freemarker.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.io.Files;

import freemarker.template.utility.StringUtil;

/**
 * Extracts a collection of resources from a Java package into a file system directory, based on the {@value ResourcesExtractor#CONTENTS_TXT}
 * resource in it. It won't scan to find resources automatically, so everything has to be added to this file.
 * 
 * <p>Regarding the content of {@value ResourcesExtractor#CONTENTS_TXT}:
 * <ul>
 *   <li>Lines starting with {code //} or {code /*} or {code *} are comments.
 *   <li>Each non-empty line in the {@value ResourcesExtractor#CONTENTS_TXT} that isn't comment, there must be
 *       a resource path relative to the "directory" that contains {@value ResourcesExtractor#CONTENTS_TXT}. Only the
 *       files referred this way will be copied. (Referring to directories doesn't copy the files in them.)
 *   <li>If the entry ends with {@code "/"}, then it denotes a directory that must be created even if there will be
 *       no files in it. Otherwise it's redundant to add such entries. 
 *   <li>The content of "subdirectories" whose name ends with  {@value ResourcesExtractor#SUFFIX_JAR} will be copied
 *       into a jar file with similar name, instead of into a directory.
 *   <li>An line may contains {@value #ARROW}, in which case the left side of the {@value #ARROW} is the
 *       <em>absolute</em> path of the copied resource, and the right side of the {@value #ARROW} is the target
 *       relative path (like the path in the usual lines). This is useful for copying class files generated by
 *       the normal Java compilation mechanism into target subdirectories like {@code WEB-INF\classes\com\example}.
 * </ul>
 */
public final class ResourcesExtractor {
    
    private static final String ARROW = "->";
    private static final String DOT_TMP = ".tmp";
    public static final String CONTENTS_TXT = "CONTENTS.txt";
    public static final String SUFFIX_JAR = ".jar";

    private static final Logger LOG = LoggerFactory.getLogger(ResourcesExtractor.class);
    
    private ResourcesExtractor() {
        // Not meant to be instantiated
    }
    
    /**
     * @param resolverClass
     *            The class with which the resources are loaded.
     * @param srcDirResourcePath
     *            The resource path to which the paths in {@value ResourcesExtractor#CONTENTS_TXT} are relative to. If
     *            the value of this parameter doesn't start with {@code "/"}, then it's relative to the package of the
     *            {@code resolverClass}.
     * 
     * @return The temporary directory into which the resource where extracted to. Don't forget to delete it when it's
     *         not used anymore.
     */
    public static File extract(Class resolverClass, String srcDirResourcePath, File dstRootDir) throws IOException {
        if (!srcDirResourcePath.endsWith("/")) {
            srcDirResourcePath += "/";
        }
        
        String contResource = srcDirResourcePath + CONTENTS_TXT;
        InputStream contIn = resolverClass.getResourceAsStream(contResource);
        if (contIn == null) {
            throw new IOException("Can't find resource: class=" + resolverClass + ", path=" + contResource);
        }
        
        boolean deleteDstRootDir;
        if (dstRootDir == null) {
            dstRootDir = Files.createTempDir();
            deleteDstRootDir = true;
        } else {
            deleteDstRootDir = !dstRootDir.exists();
        }
        try {
            BufferedReader contR = new BufferedReader(new InputStreamReader(contIn, "UTF-8"));
            try {
                String contLine;
                while ((contLine = contR.readLine()) != null) {
                    processLine(contLine, resolverClass, srcDirResourcePath, dstRootDir, contResource);
                }
            } finally {
                contR.close();
            }
            jarMarkedSubdirectories(dstRootDir);
            deleteDstRootDir = false;
        } finally {
            if (deleteDstRootDir) {
                try {
                    if (dstRootDir.getParentFile() == null) {
                        throw new IOException("Won't delete the root directory");
                    }
                    FileUtils.deleteDirectory(dstRootDir);
                } catch (IOException e) {
                    LOG.error("Failed to delete destination directory: " + dstRootDir, e);
                }
            }
        }
        
        return dstRootDir;
    }
    
    private static void processLine(String contLine, Class<?> resolverClass, String srcDirResourcePath, File dstRootDir,
            String contResource) throws IOException {
        contLine = contLine.trim();
        if (contLine.isEmpty() || contLine.startsWith("//") || contLine.startsWith("/*")
                || contLine.startsWith("*")) {
            return;
        }
        
        String contSrcPath = contLine;
        String contDstPath = contLine;
        boolean contSrcPathRelative;
        int arrowIdx = contLine.indexOf(ARROW);
        if (arrowIdx != -1) {
            if (!contLine.startsWith("/")) {
                throw new IOException("In " + StringUtil.jQuote(contResource) + ", this line must start with "
                        + "\"/\" as it uses the " + StringUtil.jQuote(ARROW) + " operator : "
                        + contLine);
            }
            contSrcPath = contLine.substring(0, arrowIdx).trim();
            contDstPath = contLine.substring(arrowIdx + ARROW.length()).trim();
            contSrcPathRelative = false;
        } else {
            if (contLine.startsWith("/")) {
                throw new IOException("In " + StringUtil.jQuote(contResource)
                        + ", this line can't start with \"/\": " + contLine);
            }
            contSrcPathRelative = true;
            contSrcPath = contLine;
            contDstPath = contLine;
        }
        File dstFile = new File(dstRootDir, contDstPath);
        if (contLine.endsWith("/")) {
            if (!dstFile.mkdirs()) {
                throw new IOException("Failed to create directory: " + dstFile);
            }
        } else {
            String srcEntryPath = contSrcPathRelative ? srcDirResourcePath + contSrcPath : contSrcPath;
            InputStream entryIn = resolverClass.getResourceAsStream(srcEntryPath);
            if (entryIn == null) {
                throw new IOException("Can't find resource: class=" + resolverClass + ", path=" + srcEntryPath);
            }
            try {
                if (dstFile.exists()) {
                    throw new IOException(
                            "Destination already exists; check if " + StringUtil.jQuote(contDstPath)
                            + " occurs for multiple times in \"" + CONTENTS_TXT + "\".");
                }
                FileUtils.copyInputStreamToFile(entryIn, dstFile);
            } catch (IOException e) {
                File parent = dstFile;
                while ((parent = dstFile.getParentFile()) != null) {
                    if (parent.isFile()) {
                        throw new IOException("An ancestor directory of " + StringUtil.jQuote(dstFile) + ", "
                        + StringUtil.jQuote(parent) + " already exists, but as a file, not as a directory. "
                        + "Check if you have accidentally added the directory itself to \"" + CONTENTS_TXT
                        + "\". Only files should be listed there.");
                    }
                }
                throw e;
            } finally {
                entryIn.close();
            }
        }
    }
    
    /**
     * @param extension
     *            The file extension of the resulting jar archive, or {@code null} if the archive name will be the same
     *            as the directory name.
     */
    private static File replaceDirectoryWithJar(File srcDir, String extension) throws IOException {
        String workJarFileName;
        String finalJarFileName;
        if (extension == null) {
            finalJarFileName = srcDir.getName();
            workJarFileName = finalJarFileName + DOT_TMP;
        } else {
            finalJarFileName = srcDir.getName() + "." + extension;
            workJarFileName = finalJarFileName;
        }
        
        File workJarFile = new File(srcDir.getParentFile(), workJarFileName);
        jarDirectory(srcDir, workJarFile);
        
        if (srcDir.getParentFile() == null) {
            throw new IOException("Won't delete the root directory");
        }
        FileUtils.deleteDirectory(srcDir);
        
        File finalJarFile;
        if (!workJarFileName.equals(finalJarFileName)) {
            finalJarFile = new File(workJarFile.getParentFile(), finalJarFileName);
            FileUtils.moveFile(workJarFile, finalJarFile);
        } else {
            finalJarFile = workJarFile; 
        }
        
        return finalJarFile;        
    }

    private static void jarDirectory(File srcDir, File jarFile) throws FileNotFoundException, IOException {
        boolean finished = false;
        try {
            FileOutputStream fileOut = new FileOutputStream(jarFile);
            try {
                JarOutputStream jarOut = new JarOutputStream(fileOut);
                try {
                    addFilesToJar("", srcDir, jarOut);
                } finally {
                    jarOut.close();
                }
            } finally {
                fileOut.close();
            }
            finished = true;
        } finally {
            if (!finished) {
                if (!jarFile.delete()) {
                    LOG.error("Failed to delete file: {}", jarFile);
                }
            }
        }
    }

    private static void jarMarkedSubdirectories(File dir) throws IOException {
        File[] entries = dir.listFiles();
        if (entries == null) {
            throw new IOException("Failed to list directory: " + dir);
        }
        for (File entry : entries) {
            if (entry.isDirectory()) {
                jarMarkedSubdirectories(entry);
                if (entry.getName().endsWith(SUFFIX_JAR)) {
                    replaceDirectoryWithJar(entry, null);
                }
            }
        }
    }

    private static void addFilesToJar(String entryBasePath, File dir, JarOutputStream jarOut) throws IOException {
        File[] entries = dir.listFiles();
        if (entries == null) {
            throw new IOException("Couldn't list directory: " + dir);
        }
        for (File entry : entries) {
            if (entry.isFile()) {
                jarOut.putNextEntry(new ZipEntry(entryBasePath + entry.getName()));
                FileInputStream fileIn = new FileInputStream(entry);
                try {
                    IOUtils.copy(fileIn, jarOut);
                } finally {
                    fileIn.close();
                }
                jarOut.closeEntry();
            } else if (entry.isDirectory()) {
                String dirPath = entryBasePath + entry.getName() + "/";
                jarOut.putNextEntry(new ZipEntry(dirPath));
                jarOut.closeEntry();
                addFilesToJar(dirPath, entry, jarOut);
            } else {
                throw new IOException("Couldn't open source entry: " + entry);
            }
        }
    }

}
