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

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLConnection;
import java.util.Arrays;

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

import org.apache.commons.AbstractVfsTestCase;
import org.apache.commons.vfs.Capability;
import org.apache.commons.vfs.FileContent;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystem;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.impl.DefaultFileSystemManager;
import org.apache.commons.vfs.provider.AbstractFileSystem;
import org.apache.commons.vfs.provider.local.DefaultLocalFileProvider;

/**
 * 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.
 *
 * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
 * @version $Revision$ $Date$
 */
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;
    }

    /**
     * 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
    {
        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</code>
     */
    public FileObject getBaseTestFolder(FileSystemManager fs) throws Exception
    {
        return providerConfig.getBaseTestFolder(fs);
    }

    /**
     * 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(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/>
     * <p>This implementation returns null.
     */
    protected Capability[] getRequiredCaps()
    {
        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.
     *
     * @todo Handle negative caps as well - ie, only run a test if the provider does not have certain caps.
     * @todo Figure out how to remove the test from the TestResult if the test is skipped.
     */
    protected void runTest() throws Throwable
    {
        // Check the capabilities
        final Capability[] caps = getRequiredCaps();
        if (caps != null)
        {
            for (int i = 0; i < caps.length; i++)
            {
                final Capability cap = caps[i];
                FileSystem fs = readFolder.getFileSystem();
                String name = fs.getClass().getName();
                int index = name.lastIndexOf('.');
                String fsName = (index > 0) ? name.substring(index + 1) : name;
                if (!fs.hasCapability(cap))
                {
                    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 (((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("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
        assertTrue("same binary content", Arrays.equals(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());

        // Get file content as a binary stream
        final byte[] expectedBin = expected.getBytes("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
        assertTrue("same binary content", Arrays.equals(expectedBin, outstr.toByteArray()));
    }

    /**
     * Builds the expected structure of the read tests folder.
     */
    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);

        return base;
    }

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

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

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