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

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Collections;
import java.util.regex.Pattern;

import freemarker.template.utility.StringUtil;

final class FileUtil {
    
    private static final int READ_BUFFER_SIZE = 4096;

    // Can't be instantiated
    private FileUtil() {
        // nop
    }
    
    private static final int COPY_BUFFER_SIZE = 64 * 1024; 

    /**
     * Copies a class-loader resource into a plain file of the same name.
     * The path of the source resource is calculated as
     * {@link srcDirClass}'s package path +
     * {@link srcDirFurtherPath} +
     * {@link srcRelativePath}.
     * The path of the destination file is calculated as
     * {@link destDir} + {@link srcRelativePath}. 
     *    
     * @param srcBaseDir Possibly {@code null}.
     */
    static void copyResourceIntoFile(
            Class<?> srcBaseClass, String srcBaseDir,
            String srcRelativePath, File destDir)
            throws IOException {
        File dstFile = new File(
                destDir,
                srcRelativePath.replace('/', File.separatorChar));

        File curDestDir = dstFile.getParentFile();
        if (!curDestDir.isDirectory() && !curDestDir.mkdirs()) {
            throw new IOException("Failed to create destination directory: "
                    + curDestDir.getAbsolutePath());
        }

        byte[] buffer = new byte[COPY_BUFFER_SIZE];
        String finalResourcePath;
        if (srcBaseDir == null || srcBaseDir.length() == 0) {
            finalResourcePath = srcRelativePath;
        } else {
            finalResourcePath = srcBaseDir + "/" + srcRelativePath;
        }
        InputStream in = srcBaseClass.getResourceAsStream(finalResourcePath);
        if (in == null) {
            throw new IOException("Failed to open class-loader resource: "
                    + finalResourcePath + " relatively to "
                    + Transform.class.getPackage().getName());
        }
        try {
            OutputStream out = new FileOutputStream(dstFile);
            try {
                int ln;
                while ((ln = in.read(buffer)) != -1) {
                    out.write(buffer, 0, ln);
                }
            } finally {
                out.close();
            }
        } finally {
            in.close();
        }
    }

    static int copyDir(
            File srcDir, File destDir) throws IOException {
        return copyDir(srcDir, destDir, srcDir, Collections.emptySet());
    }

    static int copyDir(
            File srcDir, File destDir, Collection<Pattern> ignoredFilePathPatterns)
            throws IOException {
        return copyDir(srcDir, destDir, srcDir, ignoredFilePathPatterns);
    }
    
    /**
     * @return the number of files copied.
     */
    private static int copyDir(
            File srcDir, File destDir, File srcBaseDir, Collection<Pattern> ignoredFilePathPatterns)
            throws IOException {
        int fileCounter = 0;
        
        destDir = destDir.getAbsoluteFile();
        srcDir = srcDir.getAbsoluteFile();
        String srcBaseDirPath = ensureEndsWithFileSeparator(srcBaseDir.getAbsolutePath());
        
        if (!destDir.isDirectory()) {
            if (destDir.exists()) {
                throw new IOException("Can't create directory, because a "
                        + "file with the same name already exists: "
                        + destDir.getAbsolutePath());
            }
            if (!destDir.mkdir()) {
                throw new IOException("Failed to create directory: "
                        + destDir.getAbsolutePath());
            }
        }
        
        File[] ls = srcDir.listFiles();
        if (ls == null) {
            throw new IOException("Failed to list directory: "
                    + srcDir.getAbsolutePath());
        }
        for (File f : srcDir.listFiles()) {
            String fName = f.getName(); 
            if (isUsualIgnorableFileOrDirectory(fName) || isDocgenFile(fName)) {
                continue;
            }
            File dest = new File(destDir, fName);
            if (f.isFile()) {
                if (!isIgnoredFile(f, srcBaseDirPath, ignoredFilePathPatterns)) {
                    copyFile(f, dest);
                    fileCounter++;
                }
            } else if (f.isDirectory()) {
                fileCounter += copyDir(f, dest, srcBaseDir, ignoredFilePathPatterns);
            } else {
                throw new IOException(
                        "Failed decide if it's a file or a directory: "
                        + f.getAbsolutePath());
            }
        }
        
        return fileCounter;
    }

    private static boolean isIgnoredFile(File f, String srcBaseDirPath, Collection<Pattern> ignoredFilePathPatterns)
            throws IOException {
        if (ignoredFilePathPatterns.isEmpty()) {
            return false;
        }
        
        srcBaseDirPath = ensureEndsWithFileSeparator(srcBaseDirPath);
        
        String filePath = f.getAbsolutePath();
        if (!filePath.startsWith(srcBaseDirPath)) {
            throw new IOException("Unexpected: " + StringUtil.jQuote(filePath) + " doesn't start with "
                    + StringUtil.jQuote(srcBaseDirPath));
        }
        String slashRelFilePath = pathToUnixStyle(filePath.substring(srcBaseDirPath.length() - 1));
        for (Pattern pattern : ignoredFilePathPatterns) {
            if (pattern.matcher(slashRelFilePath).matches()) {
                return true;
            }
        }
        return false;
    }

    private static void copyFile(File src, File dst) throws IOException {
        byte[] buffer = new byte[COPY_BUFFER_SIZE];
        InputStream in = new FileInputStream(src);
        try {
            long srcLMD = 0L;
            srcLMD = src.lastModified();
            if (srcLMD == 0) {
                throw new IOException("Failed to get the last modification "
                        + "time of " + src.getAbsolutePath());
            }
            OutputStream out = new FileOutputStream(dst);
            try {
                int ln;
                while ((ln = in.read(buffer)) != -1) {
                    out.write(buffer, 0, ln);
                }
            } finally {
                out.close();
            }
            if (srcLMD != 0L) {
                if (!dst.setLastModified(srcLMD)) {
                    throw new IOException(
                            "Failed to set last-modification-date for: "
                            + dst.getAbsolutePath());
                }
            }
        } finally {
            in.close();
        }
    }
    
    static boolean isDocgenFile(String fName) {
        fName = fName.toLowerCase();
        return fName.startsWith("docgen-") || fName.startsWith("docgen.")
                || fName.equals("docgen");
    }
    
    static boolean isUsualIgnorableFileOrDirectory(String fName) {
        fName = fName.toLowerCase();
        int i = fName.lastIndexOf(".");
        
        String fExt;
        if (i == -1) {
            fExt = "";
        } else {
            fExt = fName.substring(i + 1);
        }
        
        // CVS files:
        if (fName.equals(".cvsignore")  
                || fName.equals("cvs")
                || (fName.length() > 2 && fName.startsWith(".#"))) {
            return true;
        }
        
        // SVN files:
        if (fName.equals(".svn")) {
            return true;
        }

        // Temporary/backup files:
        if (
                (
                    fExt.equals("bak")
                    || fExt.equals("lock")
                    || fExt.startsWith("~"))
                || (fName.length() > 2 && (
                    (fName.startsWith("#") && fName.endsWith("#"))
                    || (fName.startsWith("%") && fName.endsWith("%"))
                    || fName.startsWith("._")))
                || (fName.length() > 1 && (
                    fName.endsWith("~")
                    || fName.startsWith("~")))
                ) {
            return true;
        }
        
        return false;
    }

    public static String loadString(File f, Charset charset) throws IOException {
        FileInputStream in = new FileInputStream(f);
        try {
            return loadString(in, charset);
        } finally {
            in.close();
        }
    }
    
    public static String loadString(InputStream in, Charset charset)
            throws IOException {
        Reader r = new InputStreamReader(in, charset);
        StringBuilder sb = new StringBuilder(256);
        try {
            char[] buf = new char[READ_BUFFER_SIZE];
            int ln;
            while ((ln = r.read(buf)) != -1) {
                sb.append(buf, 0, ln);
            }
        } finally {
            r.close();
        }
        return sb.toString();
    }

    /**
     * Converts UN*X style path to regular expression. In additional to standard UN*X path meta characters (
     * <code>*</code>, <code>?</code>) it understands <code>**</code>, that is the same as in Ant. It assumes that the
     * matched path always starts with slash (they are absoulte paths to an imaginary base), and uses slash instead of
     * backslash.
     */
    public static Pattern globToRegexp(String text) {
        StringBuilder sb = new StringBuilder();
    
        if (!text.startsWith("/")) {
            text = "/" + text;
        }
        if (text.endsWith("/")) {
            text += "**";
        }
        
        char[] chars = text.toCharArray();
        int ln = chars.length;
        for (int i = 0; i < ln; i++) {
            char c = chars[i];
            if (c == '\\' || c == '^' || c == '.' || c == '$' || c == '|'
                    || c == '(' || c == ')' || c == '[' || c == ']'
                    || c == '+' || c == '{'
                    || c == '}' || c == '@') {
                sb.append('\\');
                sb.append(c);
            } else if (i == 0 && ln > 2
                    && chars[0] == '*' && chars[1] == '*'
                    && chars[2] == '/') {
                sb.append(".*/");
                i += 2;
            } else if (c == '/' && i + 2 < ln
                    && chars[i + 1] == '*' && chars[i + 2] == '*') {
                if (i + 3 == ln) {
                    sb.append("/.*");
                } else {
                    sb.append("(/.*)?");
                }
                i += 2;
            } else if (c == '*') {
                sb.append("[^/]*");
            } else if (c == '?') {
                sb.append("[^/]");
            } else {
                sb.append(c);
            }
        }
    
        return Pattern.compile(sb.toString());
    }
    
    public static String pathToUnixStyle(String path) {
        return path.replace(File.separatorChar, '/');
    }

    public static String ensureEndsWithFileSeparator(String path) {
        return path.length() > 0 && path.charAt(path.length() - 1) == File.separatorChar
                ? path : path + File.separatorChar;
    }
    
}
