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

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.Value;

import org.apache.commons.io.FileUtils;
import org.apache.commons.vfs2.AbstractProviderTestConfig;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.ProviderTestSuite;
import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
import org.apache.commons.vfs2.provider.temp.TemporaryFileProvider;
import org.apache.commons.vfs2.provider.webdav.WebdavFileProvider;
import org.apache.commons.vfs2.provider.webdav.WebdavFileSystemConfigBuilder;
import org.apache.commons.vfs2.util.FreeSocketPortUtil;
import org.apache.jackrabbit.core.TransientRepository;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import junit.framework.Test;

/**
 * Test cases for the WebDAV provider.
 *
 */
public class WebdavProviderTestCase extends AbstractProviderTestConfig {
    private static final char[] PASSWORD = new char[0];

    private static final String USER_ID = "admin";

    private static int SocketPort;

    private static final String TEST_URI = "test.webdav.uri";

    private static JackrabbitMain JrMain;

    /**
     * Use %40 for @ in URLs
     */
    private static String ConnectionUri;

    private static File RepoDirectory;

    private static final boolean DEBUG = Boolean.getBoolean("WebdavProviderTestCase.Debug");

    static File createTempDirectory() throws IOException {
        // create base folder
        final File base = new File("./target/test").getCanonicalFile();
        base.mkdirs();

        final File tempFile = File.createTempFile("WebdavProviderTestCase_", ".tmp", base);

        if (!tempFile.delete()) {
            throw new IOException("Could not delete temp file: " + tempFile.getAbsolutePath());
        }

        if (!tempFile.mkdir()) {
            throw new IOException("Could not create temp directory: " + tempFile.getAbsolutePath());
        }

        if (DEBUG) {
            System.out.println("Working in " + tempFile);
        }

        return tempFile;
    }

    private static void dump(final File repoDirectory) throws Exception {
        final TransientRepository repository = getTransientRepository(repoDirectory);
        try {
            final Session session = getSession(repository);
            message("Root node dump:");
            dump(session.getRootNode());
            session.logout();
        } finally {
            repository.shutdown();
        }
    }

    /** Recursively outputs the contents of the given node. */
    private static void dump(final Node node) throws RepositoryException {
        // First output the node path
        message(node.getPath());
        // Skip the virtual (and large!) jcr:system subtree
        if (node.getName().equals("jcr:system")) {
            return;
        }

        if (node.getName().equals("jcr:content")) {
            return;
        }

        // Then output the properties
        final PropertyIterator properties = node.getProperties();
        while (properties.hasNext()) {
            final Property property = properties.nextProperty();
            if (property.getDefinition().isMultiple()) {
                // A multi-valued property, print all values
                final Value[] values = property.getValues();
                for (final Value value : values) {
                    message(property.getPath() + " = " + value.getString());
                }
            } else {
                // A single-valued property
                message(property.getPath() + " = " + property.getString());
            }
        }

        // Finally output all the child nodes recursively
        final NodeIterator nodes = node.getNodes();
        while (nodes.hasNext()) {
            dump(nodes.nextNode());
        }
    }

    private static Session getSession(final TransientRepository repository) throws RepositoryException {
        return repository.login(new SimpleCredentials(USER_ID, PASSWORD));
    }

    private static String getSystemTestUriOverride() {
        return System.getProperty(TEST_URI);
    }

    private static TransientRepository getTransientRepository(final File repoDirectory) throws IOException {
        // Jackrabbit 1.6:
        // TransientRepository repository = new TransientRepository(repoDirectory);
        // Jackrabbit 1.5.2:
        return new TransientRepository(new File(repoDirectory, "repository.xml").toString(), repoDirectory.toString());
    }

    private static void importFiles(final File repoDirectory, final File sourceDir) throws Exception {
        final TransientRepository repository = getTransientRepository(repoDirectory);
        try {
            final Session session = getSession(repository);
            importFiles(session.getRootNode(), sourceDir);
            session.save();
            session.logout();
        } finally {
            repository.shutdown();
        }
    }

    private static void importFiles(final Node parent, final File sourceDir) throws RepositoryException, IOException {
        final File[] files = sourceDir.listFiles();
        for (final File file : files) {
            if (file.isFile()) {
                try (InputStream data = Files.newInputStream(file.toPath())) {
                    message("Importing file " + file);
                    JcrUtils.putFile(parent, file.getName(), "application/octet-stream", data);
                }
            } else if (file.isDirectory()) {
                message("Importing folder " + file);
                final Node folder = JcrUtils.getOrAddFolder(parent, file.getName());
                importFiles(folder, file);
            }
        }
    }

    private static void message(final IOException e) {
        if (DEBUG) {
            e.printStackTrace();
        }
    }

    private static void message(final String string) {
        if (DEBUG) {
            System.out.println(string);
        }
    }

    /**
     * Creates and starts an embedded Apache WebDAV Server (Jackrabbit).
     *
     * @throws Exception
     */
    private static void setUpClass() throws Exception {
        // Create temp dir for repo
        RepoDirectory = createTempDirectory();
        message("Created temp directory " + RepoDirectory);
        // Populate repo
        importFiles(RepoDirectory, new File(getTestDirectory()));
        dump(RepoDirectory);
        // Start server with temp repo
        startJackrabbit(RepoDirectory);
        message("Returned from org.apache.jackrabbit.standalone.Main " + SocketPort);
    }

    /**
     * Starts an embedded Apache Jackrabbit server.
     *
     * @param repoDirectory
     * @throws Exception
     */
    private static void startJackrabbit(final File repoDirectory) throws Exception {
        boolean quiet = false;
        if (!DEBUG) {
            Logger.getLogger("org.apache.jackrabbit").setLevel(Level.WARN);
            Logger.getLogger("org.apache.commons.httpclient").setLevel(Level.ERROR);
            Logger.getLogger("org.apache.commons.vfs2").setLevel(Level.WARN);
            Logger.getLogger("org.mortbay").setLevel(Level.WARN);
            quiet = true;
        }
        JrMain = new JackrabbitMain(new String[] { "--port", Integer.toString(SocketPort), "--repo",
                repoDirectory.toString(), quiet ? "--quiet" : "" });
        JrMain.run();
    }

    public static Test suite() throws Exception {
        return new ProviderTestSuite(new WebdavProviderTestCase()) {
            @Override
            protected void setUp() throws Exception {
                if (getSystemTestUriOverride() == null) {
                    setUpClass();
                }
                super.setUp();
            }

            @Override
            protected void tearDown() throws Exception {
                tearDownClass();
                super.tearDown();
            }
        };
    }

    /**
     * Tears down resources for this test case.
     * <ol>
     * <li>Shuts down the embedded Jackrabbit</li>
     * <li>Extra clean up for org.apache.commons.httpclient.MultiThreadedHttpConnectionManager</li>
     * <li>Remove temporary repository directory.</li>
     * </ol>
     * Stops the embedded Apache WebDAV Server.
     *
     * @throws Exception @throws
     */
    private static void tearDownClass() throws Exception {
        // Main JR shutdown
        JrMain.shutdown();

        if (DEBUG) {
            message("Skipping cleanup of " + RepoDirectory);
            return;
        }

        // Remove repo dir
        try {
            message("Deleting temp directory " + RepoDirectory);
            FileUtils.deleteDirectory(RepoDirectory);
        } catch (final IOException e) {
            message(e);
            if (RepoDirectory.exists()) {
                message("Directory will be deleted on VM exit " + RepoDirectory);
                RepoDirectory.deleteOnExit();
            }
        }
    }

    public WebdavProviderTestCase() throws IOException {
        SocketPort = FreeSocketPortUtil.findFreeLocalPort();
        message("FreeSocketPortUtil.findFreeLocalPort() = " + SocketPort);
        // Use %40 for @ in a URL
        // Any user id and password will do with the default Jackrabbit set up.
        ConnectionUri = String.format("webdav://%s@localhost:%d/repository/default", USER_ID, SocketPort);
    }

    /**
     * Returns the base folder for tests.
     */
    @Override
    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception {
        String uri = getSystemTestUriOverride();
        if (uri == null) {
            uri = ConnectionUri;
        }
        final WebdavFileSystemConfigBuilder builder = (WebdavFileSystemConfigBuilder) manager
                .getFileSystemConfigBuilder("webdav");
        final FileSystemOptions opts = new FileSystemOptions();
        builder.setRootURI(opts, uri);
        return manager.resolveFile(uri, opts);
    }

    @Override
    public boolean isFileSystemRootAccessible() {
        return false;
    }

    /**
     * Prepares the file system manager.
     */
    @Override
    public void prepare(final DefaultFileSystemManager manager) throws Exception {
        manager.addProvider("webdav", new WebdavFileProvider());
        manager.addProvider("tmp", new TemporaryFileProvider());
    }

}
