/*
 * 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 {
            try (BufferedReader contR = new BufferedReader(new InputStreamReader(contIn, "UTF-8"))) {
                String contLine;
                while ((contLine = contR.readLine()) != null) {
                    processLine(contLine, resolverClass, srcDirResourcePath, dstRootDir, contResource);
                }
            }
            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 {
            try (FileOutputStream fileOut = new FileOutputStream(jarFile)) {
                JarOutputStream jarOut = new JarOutputStream(fileOut);
                try {
                    addFilesToJar("", srcDir, jarOut);
                } finally {
                    jarOut.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()));
                try (FileInputStream fileIn = new FileInputStream(entry)) {
                    IOUtils.copy(fileIn, jarOut);
                }
                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);
            }
        }
    }

}
