/*
 * 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.commons.vfs2.filter;

import static org.junit.Assert.fail;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSelectInfo;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.VFS;
import org.junit.Assert;

/**
 * Base class for test cases.
 */
public abstract class BaseFilterTest {

    /**
     * Verifies at least all given objects are in the list.
     *
     * @param list    List to use.
     * @param objects Objects to find.
     */
    protected static void assertContains(final List<?> list, final Object... objects) {
        for (final Object obj : objects) {
            Assert.assertTrue("Couldn't find " + obj + " in " + Arrays.asList(objects), list.indexOf(obj) > -1);
        }
    }

    /**
     * Verifies only the given objects are in the list.
     *
     * @param list    List to scan.
     * @param objects Objects to find.
     */
    protected static void assertContainsOnly(final List<?> list, final Object... objects) {
        for (final Object obj : objects) {
            Assert.assertTrue("Couldn't find " + obj + " in " + Arrays.asList(objects), list.indexOf(obj) > -1);
        }
        Assert.assertEquals(objects.length, list.size());
    }

    /**
     * Concatenate a path and a file name taking {@code null} and empty string
     * values into account.
     *
     * @param path      Path - Can be {@code null} or an empty string.
     * @param fileName  Filename - Cannot be {@code null}.
     * @param separator Separator for directories - Can be {@code null} or an
     *                  empty string.
     *
     * @return Path and file name divided by the separator.
     */
    public static String concatPathAndFilename(final String path, final String fileName, final String separator) {

        if (fileName == null) {
            throw new IllegalArgumentException("file name cannot be null");
        }
        if (fileName.trim().isEmpty()) {
            throw new IllegalArgumentException("file name cannot be empty");
        }
        if (separator == null) {
            throw new IllegalArgumentException("separator cannot be null");
        }
        if (separator.trim().isEmpty()) {
            throw new IllegalArgumentException("separator cannot be empty");
        }

        if (path == null) {
            return fileName;
        }
        final String trimmedPath = path.trim();
        if (trimmedPath.isEmpty()) {
            return fileName;
        }
        final String trimmedFilename = fileName.trim();
        if (trimmedPath.endsWith(separator)) {
            return trimmedPath + trimmedFilename;
        }
        return trimmedPath + separator + trimmedFilename;
    }

    /**
     * Creates a file select info object for the given file.
     *
     * @param file File to create an info for.
     * @return File select info.
     */
    protected static FileSelectInfo createFileSelectInfo(final File file) {
        try {
            final FileSystemManager fsManager = VFS.getManager();
            final FileObject fileObject = fsManager.toFileObject(file);
            return new FileSelectInfo() {
                @Override
                public FileObject getBaseFolder() {
                    try {
                        return fileObject.getParent();
                    } catch (final FileSystemException ex) {
                        throw new RuntimeException(ex);
                    }
                }

                @Override
                public int getDepth() {
                    return 0;
                }

                @Override
                public FileObject getFile() {
                    return fileObject;
                }

                @Override
                public String toString() {
                    return Objects.toString(fileObject);
                }
            };
        } catch (final FileSystemException ex) {
            throw new RuntimeException(ex);
        }
    }

    protected static void delete(final File file) {
        if (file != null) {
            file.delete();
        }
    }

    /**
     * Returns the temporary directory.
     *
     * @return java.io.tmpdir
     */
    protected static File getTempDir() {
        return new File(System.getProperty("java.io.tmpdir"));
    }

    /**
     * Returns a subdirectory of the temporary directory.
     *
     * @param name Name of the subdirectory.
     *
     * @return Subdirectory of java.io.tmpdir.
     */
    protected static File getTestDir(final String name) {
        final File file = new File(getTempDir(), name);
        file.mkdirs();
        return file;
    }

    /**
     * Returns a ZIP file object.
     *
     * @param file File to resolve.
     *
     * @return File object.
     *
     * @throws FileSystemException Error resolving the file.
     */
    protected static FileObject getZipFileObject(final File file) throws FileSystemException {
        final FileSystemManager fsManager = VFS.getManager();
        return fsManager.resolveFile("zip:" + file.toURI());
    }

    /**
     * List all files for a directory.
     *
     * @param srcDir Directory to list the files for - Cannot be {@code null}
     *               and must be a valid directory.
     * @param filter Filter or {@code null} for all files.
     *
     * @return List of child entries of the directory.
     */
    private static File[] listFiles(final File srcDir, final FileFilter filter) {

        final File[] files;
        if (filter == null) {
            files = srcDir.listFiles();
        } else {
            files = srcDir.listFiles(filter);
        }
        return files;
    }

    /**
     * Creates a ZIP file and adds all files in a directory and all it's
     * subdirectories to the archive. Only entries are added that comply to the file
     * filter.
     *
     * @param srcDir   Directory to add - Cannot be {@code null} and must be a
     *                 valid directory.
     * @param filter   Filter or {@code null} for all files/directories.
     * @param destPath Path to use for the ZIP archive - May be {@code null} or
     *                 an empty string.
     * @param destFile Target ZIP file - Cannot be {@code null}.
     *
     * @throws IOException Error writing to the output stream.
     */
    public static void zipDir(final File srcDir, final FileFilter filter, final String destPath, final File destFile)
            throws IOException {

        if (srcDir == null) {
            throw new IllegalArgumentException("srcDir cannot be null");
        }
        if (!srcDir.exists()) {
            throw new IllegalArgumentException("srcDir does not exist");
        }
        if (!srcDir.isDirectory()) {
            throw new IllegalArgumentException("srcDir is not a directory");
        }
        if (destFile == null) {
            throw new IllegalArgumentException("destFile cannot be null");
        }

        try (ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(Files.newOutputStream(destFile.toPath())))) {
            zipDir(srcDir, filter, destPath, out);
        }

    }

    /**
     * Add a directory to a ZIP output stream.
     *
     * @param srcDir   Directory to add - Cannot be {@code null} and must be a
     *                 valid directory.
     * @param filter   Filter or {@code null} for all files.
     * @param destPath Path to use for the ZIP archive - May be {@code null} or
     *                 an empty string.
     * @param out      Destination stream - Cannot be {@code null}.
     *
     * @throws IOException Error writing to the output stream.
     */
    private static void zipDir(final File srcDir, final FileFilter filter, final String destPath,
            final ZipOutputStream out) throws IOException {

        final File[] files = listFiles(srcDir, filter);
        for (final File file : files) {
            if (file.isDirectory()) {
                zipDir(file, filter, concatPathAndFilename(destPath, file.getName(), File.separator), out);
            } else {
                zipFile(file, destPath, out);
            }
        }

    }

    /**
     * Creates a ZIP file and adds all files in a directory and all it's
     * subdirectories to the archive.
     *
     * @param srcDir   Directory to add - Cannot be {@code null} and must be a
     *                 valid directory.
     * @param destPath Path to use for the ZIP archive - May be {@code null} or
     *                 an empty string.
     * @param destFile Target ZIP file - Cannot be {@code null}.
     *
     * @throws IOException Error writing to the output stream.
     */
    public static void zipDir(final File srcDir, final String destPath, final File destFile) throws IOException {

        zipDir(srcDir, null, destPath, destFile);
    }

    /**
     * Adds a file to a ZIP output stream.
     *
     * @param srcFile  File to add - Cannot be {@code null}.
     * @param destPath Path to use for the file - May be {@code null} or empty.
     * @param out      Destination stream - Cannot be {@code null}.
     *
     * @throws IOException Error writing to the output stream.
     */
    private static void zipFile(final File srcFile, final String destPath, final ZipOutputStream out)
            throws IOException {

        final byte[] buf = new byte[1024];
        try (InputStream in = new BufferedInputStream(Files.newInputStream(srcFile.toPath()))) {
            final ZipEntry zipEntry = new ZipEntry(concatPathAndFilename(destPath, srcFile.getName(), File.separator));
            zipEntry.setTime(srcFile.lastModified());
            out.putNextEntry(zipEntry);
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
            out.closeEntry();
        }
    }

    /**
     * Asserts that the array contains the given file names.
     *
     * @param files     Array to check.
     * @param fileNames names File names to find.
     */
    protected void assertContains(final FileObject[] files, final String... fileNames) {
        for (final String fileName : fileNames) {
            if (!find(files, fileName)) {
                fail("File '" + fileName + "' not found in: " + Arrays.asList(files));
            }
        }
    }

    private boolean find(final FileObject[] files, final String fileName) {
        for (final FileObject file : files) {
            final String name = file.getName().getBaseName();
            if (name.equals(fileName)) {
                return true;
            }
        }
        return false;
    }

}
