/*
 * 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.maven.plugins.clean;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.testing.AbstractMojoTestCase;

import static org.apache.commons.io.FileUtils.copyDirectory;
import static org.codehaus.plexus.util.IOUtil.copy;

/**
 * Test the clean mojo.
 *
 * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
 */
public class CleanMojoTest extends AbstractMojoTestCase {
    /**
     * Tests the simple removal of directories
     *
     * @throws Exception in case of an error.
     */
    public void testBasicClean() throws Exception {
        String pluginPom = getBasedir() + "/src/test/resources/unit/basic-clean-test/plugin-pom.xml";

        // safety
        copyDirectory(
                new File(getBasedir(), "src/test/resources/unit/basic-clean-test"),
                new File(getBasedir(), "target/test-classes/unit/basic-clean-test"));

        CleanMojo mojo = (CleanMojo) lookupMojo("clean", pluginPom);
        assertNotNull(mojo);

        mojo.execute();

        assertFalse(
                "Directory exists",
                checkExists(getBasedir() + "/target/test-classes/unit/" + "basic-clean-test/buildDirectory"));
        assertFalse(
                "Directory exists",
                checkExists(getBasedir() + "/target/test-classes/unit/basic-clean-test/" + "buildOutputDirectory"));
        assertFalse(
                "Directory exists",
                checkExists(getBasedir() + "/target/test-classes/unit/basic-clean-test/" + "buildTestDirectory"));
    }

    /**
     * Tests the removal of files and nested directories
     *
     * @throws Exception in case of an error.
     */
    public void testCleanNestedStructure() throws Exception {
        String pluginPom = getBasedir() + "/src/test/resources/unit/nested-clean-test/plugin-pom.xml";

        // safety
        copyDirectory(
                new File(getBasedir(), "src/test/resources/unit/nested-clean-test"),
                new File(getBasedir(), "target/test-classes/unit/nested-clean-test"));

        CleanMojo mojo = (CleanMojo) lookupMojo("clean", pluginPom);
        assertNotNull(mojo);

        mojo.execute();

        assertFalse(checkExists(getBasedir() + "/target/test-classes/unit/nested-clean-test/target"));
        assertFalse(checkExists(getBasedir() + "/target/test-classes/unit/nested-clean-test/target/classes"));
        assertFalse(checkExists(getBasedir() + "/target/test-classes/unit/nested-clean-test/target/test-classes"));
    }

    /**
     * Tests that no exception is thrown when all internal variables are empty and that it doesn't
     * just remove whats there
     *
     * @throws Exception in case of an error.
     */
    public void testCleanEmptyDirectories() throws Exception {
        String pluginPom = getBasedir() + "/src/test/resources/unit/empty-clean-test/plugin-pom.xml";

        // safety
        copyDirectory(
                new File(getBasedir(), "src/test/resources/unit/empty-clean-test"),
                new File(getBasedir(), "target/test-classes/unit/empty-clean-test"));

        CleanMojo mojo = (CleanMojo) lookupEmptyMojo("clean", pluginPom);
        assertNotNull(mojo);

        mojo.execute();

        assertTrue(checkExists(getBasedir() + "/target/test-classes/unit/empty-clean-test/testDirectoryStructure"));
        assertTrue(checkExists(
                getBasedir() + "/target/test-classes/unit/empty-clean-test/" + "testDirectoryStructure/file.txt"));
        assertTrue(checkExists(getBasedir() + "/target/test-classes/unit/empty-clean-test/"
                + "testDirectoryStructure/outputDirectory"));
        assertTrue(checkExists(getBasedir() + "/target/test-classes/unit/empty-clean-test/"
                + "testDirectoryStructure/outputDirectory/file.txt"));
    }

    /**
     * Tests the removal of files using fileset
     *
     * @throws Exception in case of an error.
     */
    public void testFilesetsClean() throws Exception {
        String pluginPom = getBasedir() + "/src/test/resources/unit/fileset-clean-test/plugin-pom.xml";

        // safety
        copyDirectory(
                new File(getBasedir(), "src/test/resources/unit/fileset-clean-test"),
                new File(getBasedir(), "target/test-classes/unit/fileset-clean-test"));

        CleanMojo mojo = (CleanMojo) lookupMojo("clean", pluginPom);
        assertNotNull(mojo);

        mojo.execute();

        // fileset 1
        assertTrue(checkExists(getBasedir() + "/target/test-classes/unit/fileset-clean-test/target"));
        assertTrue(checkExists(getBasedir() + "/target/test-classes/unit/fileset-clean-test/target/classes"));
        assertFalse(checkExists(getBasedir() + "/target/test-classes/unit/fileset-clean-test/target/test-classes"));
        assertTrue(checkExists(getBasedir() + "/target/test-classes/unit/fileset-clean-test/target/subdir"));
        assertFalse(checkExists(getBasedir() + "/target/test-classes/unit/fileset-clean-test/target/classes/file.txt"));
        assertTrue(checkEmpty(getBasedir() + "/target/test-classes/unit/fileset-clean-test/target/classes"));
        assertFalse(checkEmpty(getBasedir() + "/target/test-classes/unit/fileset-clean-test/target/subdir"));
        assertTrue(checkExists(getBasedir() + "/target/test-classes/unit/fileset-clean-test/target/subdir/file.txt"));

        // fileset 2
        assertTrue(
                checkExists(getBasedir() + "/target/test-classes/unit/fileset-clean-test/" + "buildOutputDirectory"));
        assertFalse(checkExists(
                getBasedir() + "/target/test-classes/unit/fileset-clean-test/" + "buildOutputDirectory/file.txt"));
    }

    /**
     * Tests the removal of a directory as file
     *
     * @throws Exception in case of an error.
     */
    public void testCleanInvalidDirectory() throws Exception {
        String pluginPom = getBasedir() + "/src/test/resources/unit/invalid-directory-test/plugin-pom.xml";

        // safety
        copyDirectory(
                new File(getBasedir(), "src/test/resources/unit/invalid-directory-test"),
                new File(getBasedir(), "target/test-classes/unit/invalid-directory-test"));

        CleanMojo mojo = (CleanMojo) lookupMojo("clean", pluginPom);
        assertNotNull(mojo);

        try {
            mojo.execute();

            fail("Should fail to delete a file treated as a directory");
        } catch (MojoExecutionException expected) {
            assertTrue(true);
        }
    }

    /**
     * Tests the removal of a missing directory
     *
     * @throws Exception in case of an error.
     */
    public void testMissingDirectory() throws Exception {
        String pluginPom = getBasedir() + "/src/test/resources/unit/missing-directory-test/plugin-pom.xml";

        // safety
        copyDirectory(
                new File(getBasedir(), "src/test/resources/unit/missing-directory-test"),
                new File(getBasedir(), "target/test-classes/unit/missing-directory-test"));

        CleanMojo mojo = (CleanMojo) lookupMojo("clean", pluginPom);
        assertNotNull(mojo);

        mojo.execute();

        assertFalse(checkExists(getBasedir() + "/target/test-classes/unit/missing-directory-test/does-not-exist"));
    }

    /**
     * Test the removal of a locked file on Windows systems.
     * <p>
     * Note: Unix systems doesn't lock any files.
     * </p>
     *
     * @throws Exception in case of an error.
     */
    public void testCleanLockedFile() throws Exception {
        if (!System.getProperty("os.name").toLowerCase().contains("windows")) {
            assertTrue("Ignored this test on non Windows based systems", true);
            return;
        }

        String pluginPom = getBasedir() + "/src/test/resources/unit/locked-file-test/plugin-pom.xml";

        // safety
        copyDirectory(
                new File(getBasedir(), "src/test/resources/unit/locked-file-test"),
                new File(getBasedir(), "target/test-classes/unit/locked-file-test"));

        CleanMojo mojo = (CleanMojo) lookupMojo("clean", pluginPom);
        assertNotNull(mojo);

        File f = new File(getBasedir(), "target/test-classes/unit/locked-file-test/buildDirectory/file.txt");
        try (FileChannel channel = new RandomAccessFile(f, "rw").getChannel();
                FileLock ignored = channel.lock()) {
            mojo.execute();
            fail("Should fail to delete a file that is locked");
        } catch (MojoExecutionException expected) {
            assertTrue(true);
        }
    }

    /**
     * Test the removal of a locked file on Windows systems.
     * <p>
     * Note: Unix systems doesn't lock any files.
     * </p>
     *
     * @throws Exception in case of an error.
     */
    public void testCleanLockedFileWithNoError() throws Exception {
        if (!System.getProperty("os.name").toLowerCase().contains("windows")) {
            assertTrue("Ignore this test on non Windows based systems", true);
            return;
        }

        String pluginPom = getBasedir() + "/src/test/resources/unit/locked-file-test/plugin-pom.xml";

        // safety
        copyDirectory(
                new File(getBasedir(), "src/test/resources/unit/locked-file-test"),
                new File(getBasedir(), "target/test-classes/unit/locked-file-test"));

        CleanMojo mojo = (CleanMojo) lookupMojo("clean", pluginPom);
        setVariableValueToObject(mojo, "failOnError", Boolean.FALSE);
        assertNotNull(mojo);

        File f = new File(getBasedir(), "target/test-classes/unit/locked-file-test/buildDirectory/file.txt");
        try (FileChannel channel = new RandomAccessFile(f, "rw").getChannel();
                FileLock ignored = channel.lock()) {
            mojo.execute();
            assertTrue(true);
        } catch (MojoExecutionException expected) {
            fail("Should display a warning when deleting a file that is locked");
        }
    }

    /**
     * Test the followLink option with windows junctions
     * @throws Exception
     */
    public void testFollowLinksWithWindowsJunction() throws Exception {
        if (!System.getProperty("os.name").toLowerCase().contains("windows")) {
            assertTrue("Ignore this test on non Windows based systems", true);
            return;
        }

        testSymlink((link, target) -> {
            Process process = new ProcessBuilder()
                    .directory(link.getParent().toFile())
                    .command("cmd", "/c", "mklink", "/j", link.getFileName().toString(), target.toString())
                    .start();
            process.waitFor();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            copy(process.getInputStream(), baos);
            copy(process.getErrorStream(), baos);
            if (!Files.exists(link)) {
                throw new IOException("Unable to create junction: " + baos);
            }
        });
    }

    /**
     * Test the followLink option with sym link
     * @throws Exception
     */
    public void testFollowLinksWithSymLinkOnPosix() throws Exception {
        if (System.getProperty("os.name").toLowerCase().contains("windows")) {
            assertTrue("Ignore this test on Windows based systems", true);
            return;
        }

        testSymlink((link, target) -> {
            try {
                Files.createSymbolicLink(link, target);
            } catch (IOException e) {
                throw new IOException("Unable to create symbolic link", e);
            }
        });
    }

    @FunctionalInterface
    interface LinkCreator {
        void createLink(Path link, Path target) throws Exception;
    }

    private void testSymlink(LinkCreator linkCreator) throws Exception {
        Cleaner cleaner = new Cleaner(null, null, false, null, null);
        Path testDir = Paths.get("target/test-classes/unit/test-dir").toAbsolutePath();
        Path dirWithLnk = testDir.resolve("dir");
        Path orgDir = testDir.resolve("org-dir");
        Path jctDir = dirWithLnk.resolve("jct-dir");
        Path file = orgDir.resolve("file.txt");

        // create directories, links and file
        Files.createDirectories(dirWithLnk);
        Files.createDirectories(orgDir);
        Files.write(file, Collections.singleton("Hello world"));
        linkCreator.createLink(jctDir, orgDir);
        // delete
        cleaner.delete(dirWithLnk.toFile(), null, false, true, false);
        // verify
        assertTrue(Files.exists(file));
        assertFalse(Files.exists(jctDir));
        assertTrue(Files.exists(orgDir));
        assertFalse(Files.exists(dirWithLnk));

        // create directories, links and file
        Files.createDirectories(dirWithLnk);
        Files.createDirectories(orgDir);
        Files.write(file, Collections.singleton("Hello world"));
        linkCreator.createLink(jctDir, orgDir);
        // delete
        cleaner.delete(dirWithLnk.toFile(), null, true, true, false);
        // verify
        assertFalse(Files.exists(file));
        assertFalse(Files.exists(jctDir));
        assertTrue(Files.exists(orgDir));
        assertFalse(Files.exists(dirWithLnk));
    }

    /**
     * @param dir a dir or a file
     * @return true if a file/dir exists, false otherwise
     */
    private boolean checkExists(String dir) {
        return new File(new File(dir).getAbsolutePath()).exists();
    }

    /**
     * @param dir a directory
     * @return true if a dir is empty, false otherwise
     */
    private boolean checkEmpty(String dir) {
        File[] files = new File(dir).listFiles();
        return files == null || files.length == 0;
    }
}
