/*
 * 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;

import static org.junit.Assert.assertArrayEquals;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;

import org.apache.commons.AbstractVfsTestCase;
import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
import org.apache.commons.vfs2.provider.AbstractFileSystem;
import org.apache.commons.vfs2.provider.local.DefaultLocalFileProvider;
import org.junit.Assert;

import junit.framework.Test;
import junit.framework.TestCase;

/**
 * File system test cases, which verifies the structure and naming functionality.
 * <p>
 * Works from a base folder, and assumes a particular structure under that base folder.
 */
public abstract class AbstractProviderTestCase extends AbstractVfsTestCase {
    private FileObject baseFolder;
    private FileObject readFolder;
    private FileObject writeFolder;
    private DefaultFileSystemManager manager;
    private ProviderTestConfig providerConfig;
    private Method method;
    private boolean addEmptyDir;

    // Expected contents of "file1.txt"
    public static final String FILE1_CONTENT = "This is a test file.";

    // Expected contents of test files
    public static final String TEST_FILE_CONTENT = "A test file.";

    /**
     * Sets the test method.
     */
    public void setMethod(final Method method) {
        this.method = method;
    }

    /**
     * Configures this test.
     */
    public void setConfig(final DefaultFileSystemManager manager, final ProviderTestConfig providerConfig,
            final FileObject baseFolder, final FileObject readFolder, final FileObject writeFolder) {
        this.manager = manager;
        this.providerConfig = providerConfig;
        this.baseFolder = baseFolder;
        this.readFolder = readFolder;
        this.writeFolder = writeFolder;
        assertNotNull("setConfig manager", manager);
        assertNotNull("setConfig providerConfig", providerConfig);
        assertNotNull("setConfig baseFolder", baseFolder);
        assertNotNull("setConfig readFolder", readFolder);
        assertNotNull("setConfig writeFolder", writeFolder);
    }

    /**
     * Returns the file system manager used by this test.
     */
    protected DefaultFileSystemManager getManager() {
        return manager;
    }

    /**
     * creates a new uninitialized file system manager
     *
     * @throws Exception
     */
    protected DefaultFileSystemManager createManager() throws Exception {
        final DefaultFileSystemManager fs = getProviderConfig().getDefaultFileSystemManager();
        fs.setFilesCache(getProviderConfig().getFilesCache());
        getProviderConfig().prepare(fs);
        if (!fs.hasProvider("file")) {
            fs.addProvider("file", new DefaultLocalFileProvider());
        }
        return fs;
    }

    /**
     * some provider config do some post-initialization in getBaseTestFolder. This is a hack to allow access to this
     * code for {@code createManager}
     */
    public FileObject getBaseTestFolder(final FileSystemManager fs) throws Exception {
        return providerConfig.getBaseTestFolder(fs);
    }

    protected FileSystem getFileSystem() {
        final FileObject rFolder = getReadFolder();
        Assert.assertNotNull("This test's read folder should not be null", rFolder);
        return rFolder.getFileSystem();
    }

    /**
     * Returns the base test folder. This is the parent of both the read test and write test folders.
     */
    public FileObject getBaseFolder() {
        return baseFolder;
    }

    /**
     * get the provider configuration
     */
    public ProviderTestConfig getProviderConfig() {
        return providerConfig;
    }

    /**
     * Returns the read test folder.
     */
    protected FileObject getReadFolder() {
        return readFolder;
    }

    /**
     * Returns the write test folder.
     */
    protected FileObject getWriteFolder() {
        return writeFolder;
    }

    /**
     * Sets the write test folder.
     *
     * @param folder
     */
    protected void setWriteFolder(final FileObject folder) {
        writeFolder = folder;
    }

    /**
     * Returns the capabilities required by the tests of this test case. The tests are not run if the provider being
     * tested does not support all the required capabilities. Return null or an empty array to always run the tests.
     * <p>
     * This implementation returns null.
     */
    protected Capability[] getRequiredCapabilities() {
        return null;
    }

    /**
     * Runs the test. This implementation short-circuits the test if the provider being tested does not have the
     * capabilities required by this test.
     * <p>
     * TODO - Handle negative caps as well - ie, only run a test if the provider does not have certain caps.
     * </p>
     * <p>
     * TODO - Figure out how to remove the test from the TestResult if the test is skipped.
     * </p>
     */
    @Override
    protected void runTest() throws Throwable {
        // Check the capabilities
        final Capability[] caps = getRequiredCapabilities();
        if (caps != null) {
            for (final Capability cap2 : caps) {
                final Capability cap = cap2;
                final FileSystem fs = getFileSystem();
                if (!fs.hasCapability(cap)) {
                    // String name = fs.getClass().getName();
                    // int index = name.lastIndexOf('.');
                    // String fsName = (index > 0) ? name.substring(index + 1) : name;
                    // System.out.println("skipping " + getName() + " because " +
                    // fsName + " does not have capability " + cap);
                    return;
                }
            }
        }

        // Provider has all the capabilities - execute the test
        if (method != null) {
            try {
                method.invoke(this, (Object[]) null);
            } catch (final InvocationTargetException e) {
                throw e.getTargetException();
            }
        } else {
            super.runTest();
        }

        if (readFolder != null && ((AbstractFileSystem) readFolder.getFileSystem()).isOpen()) {
            String name = "unknown";
            if (method != null) {
                name = method.getName();
            }

            throw new IllegalStateException(getClass().getName() + ": filesystem has open streams after: " + name);
        }
    }

    /**
     * Asserts that the content of a file is the same as expected. Checks the length reported by getContentLength() is
     * correct, then reads the content as a byte stream and compares the result with the expected content. Assumes files
     * are encoded using UTF-8.
     */
    protected void assertSameURLContent(final String expected, final URLConnection connection) throws Exception {
        // Get file content as a binary stream
        final byte[] expectedBin = expected.getBytes(StandardCharsets.UTF_8);

        // Check lengths
        assertEquals("same content length", expectedBin.length, connection.getContentLength());

        // Read content into byte array
        final InputStream instr = connection.getInputStream();
        final ByteArrayOutputStream outstr;
        try {
            outstr = new ByteArrayOutputStream();
            final byte[] buffer = new byte[256];
            int nread = 0;
            while (nread >= 0) {
                outstr.write(buffer, 0, nread);
                nread = instr.read(buffer);
            }
        } finally {
            instr.close();
        }

        // Compare
        assertArrayEquals("same binary content", expectedBin, outstr.toByteArray());
    }

    /**
     * Asserts that the content of a file is the same as expected. Checks the length reported by getSize() is correct,
     * then reads the content as a byte stream and compares the result with the expected content. Assumes files are
     * encoded using UTF-8.
     */
    protected void assertSameContent(final String expected, final FileObject file) throws Exception {
        // Check the file exists, and is a file
        assertTrue(file.exists());
        assertSame(FileType.FILE, file.getType());
        assertTrue(file.isFile());

        // Get file content as a binary stream
        final byte[] expectedBin = expected.getBytes(StandardCharsets.UTF_8);

        // Check lengths
        final FileContent content = file.getContent();
        assertEquals("same content length", expectedBin.length, content.getSize());

        // Read content into byte array
        final InputStream instr = content.getInputStream();
        final ByteArrayOutputStream outstr;
        try {
            outstr = new ByteArrayOutputStream(expectedBin.length);
            final byte[] buffer = new byte[256];
            int nread = 0;
            while (nread >= 0) {
                outstr.write(buffer, 0, nread);
                nread = instr.read(buffer);
            }
        } finally {
            instr.close();
        }

        // Compare
        assertArrayEquals("same binary content", expectedBin, outstr.toByteArray());
    }

    /**
     * Builds the expected structure of the read tests folder.
     *
     * @throws FileSystemException (possibly)
     */
    protected FileInfo buildExpectedStructure() throws FileSystemException {
        // Build the expected structure
        final FileInfo base = new FileInfo(getReadFolder().getName().getBaseName(), FileType.FOLDER);
        base.addFile("file1.txt", FILE1_CONTENT);
        // file%.txt - test out encoding
        base.addFile("file%25.txt", FILE1_CONTENT);

        // file?test.txt - test out encoding (test.txt is not the queryString)
        // as we do not know if the current file provider we need to
        // ask it to normalize the name
        // todo: move this into the FileInfo class to do it generally?
        /*
         * webdav-bug?: didnt manage to get the "?" correctly through webdavlib FileSystemManager fsm =
         * getReadFolder().getFileSystem().getFileSystemManager(); FileName fn =
         * fsm.resolveName(getReadFolder().getName(), "file%3ftest.txt"); String baseName = fn.getBaseName();
         * base.addFile(baseName, FILE1_CONTENT);
         */
        base.addFile("file space.txt", FILE1_CONTENT);

        base.addFile("empty.txt", "");
        if (addEmptyDir) {
            base.addFolder("emptydir");
        }

        final FileInfo dir = base.addFolder("dir1");
        dir.addFile("file1.txt", TEST_FILE_CONTENT);
        dir.addFile("file2.txt", TEST_FILE_CONTENT);
        dir.addFile("file3.txt", TEST_FILE_CONTENT);

        final FileInfo subdir1 = dir.addFolder("subdir1");
        subdir1.addFile("file1.txt", TEST_FILE_CONTENT);
        subdir1.addFile("file2.txt", TEST_FILE_CONTENT);
        subdir1.addFile("file3.txt", TEST_FILE_CONTENT);

        final FileInfo subdir2 = dir.addFolder("subdir2");
        subdir2.addFile("file1.txt", TEST_FILE_CONTENT);
        subdir2.addFile("file2.txt", TEST_FILE_CONTENT);
        subdir2.addFile("file3.txt", TEST_FILE_CONTENT);

        final FileInfo subdir3 = dir.addFolder("subdir3");
        subdir3.addFile("file1.txt", TEST_FILE_CONTENT);
        subdir3.addFile("file2.txt", TEST_FILE_CONTENT);
        subdir3.addFile("file3.txt", TEST_FILE_CONTENT);

        final FileInfo subdir4 = dir.addFolder("subdir4.jar");
        subdir4.addFile("file1.txt", TEST_FILE_CONTENT);
        subdir4.addFile("file2.txt", TEST_FILE_CONTENT);
        subdir4.addFile("file3.txt", TEST_FILE_CONTENT);

        return base;
    }

    protected void addEmptyDir(final boolean addEmptyDir) {
        this.addEmptyDir = addEmptyDir;
    }

    protected static Test notConfigured(final Class<?> testClass) {
        return warning(testClass + " is not configured for tests, skipping");
    }

    private static Test warning(final String message) {
        return new TestCase("warning") {
            @Override
            protected void runTest() {
                System.out.println(message);
            }
        };
    }

    @Override
    public String toString() {
        return "AbstractProviderTestCase [baseFolder=" + baseFolder + ", readFolder=" + readFolder + ", writeFolder="
                + writeFolder + ", manager=" + manager + ", providerConfig=" + providerConfig + ", method=" + method
                + ", addEmptyDir=" + addEmptyDir + "]";
    }
}
