/*
 * 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.jackrabbit.filevault.maven.packaging.it;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.BoundedReader;
import org.apache.maven.it.VerificationException;
import org.apache.maven.it.Verifier;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.shared.utils.StringUtils;
import org.apache.maven.shared.utils.io.FileUtils;
import org.apache.maven.shared.utils.io.IOUtil;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.hamcrest.Description;
import org.hamcrest.Matchers;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import aQute.bnd.header.Attrs;
import aQute.bnd.header.Parameters;

/**
 * Helper class to build and verify a maven project.
 */
public class ProjectBuilder {

    /**
     * default logger
     */
    private static final Logger log = LoggerFactory.getLogger(ProjectBuilder.class);

    private static final Set<String> IGNORED_MANIFEST_ENTRIES = new HashSet<>(Arrays.asList("Build-Jdk-Spec", "Created-By"));

    public static final String TEST_PROJECTS_ROOT = "target/test-classes/test-projects";

    static final String TEST_PACKAGE_DEFAULT_NAME = "target/package-plugin-test-pkg-1.0.0-SNAPSHOT.zip";

    static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("%(\\d*)%");

    private File testProjectsRoot;

    private File testProjectDir;

    private File testPackageFile;

    private Properties testProperties;

    private String[] testGoals = {"clean", "package"};

    private List<String> pkgZipEntries;

    private File expectedFilesFile;

    private File expectedOrderFile;

    private File expectedManifestFile;

    private File expectedFilterFile;
    
    private File expectedFilesWithChecksumsFile;

    private File expectedLogLinesFile;

    private File logTxtFile;

    private boolean buildExpectedToFail;

    private boolean verifyPackageContents = true;

    public ProjectBuilder() {
        testProjectsRoot = new File(TEST_PROJECTS_ROOT);
        testProperties = new Properties();

        testProperties.put("plugin.version", getPluginVersion());
        testProperties.put("testcontent.directory", new File("target/test-classes/test-content").getAbsolutePath());
        testProperties.put("maven.compiler.source", "1.8");
        testProperties.put("maven.compiler.target", "1.8");
    }

    /**
     * Retrieves the version of the {@code filevault-package-maven-plugin} of the current project. The version is used in the
     * test poms so that the cli build uses the current plugin. Usually the version is set via the system property
     * {@code plugin.version} via the failsafe plugin. If the property is missing the method tries to read it from the
     * {@code pom.xml} of the project. this is useful when running the tests in an IDE.
     *
     * @return the version of the current {@code filevault-package-maven-plugin}
     * @throws IllegalArgumentException if the version cannot be determined.
     */
    private String getPluginVersion() {
        String pluginVersion  = System.getProperty("plugin.version");
        if (pluginVersion == null) {
            try (FileReader fileReader = new FileReader("pom.xml")) {
                // try to read from project
                MavenXpp3Reader reader = new MavenXpp3Reader();
                Model model = reader.read(fileReader);
                pluginVersion = model.getVersion();
            } catch (IOException | XmlPullParserException e) {
                log.error("Unable to read version from pom", e);
            }
        }
        if (pluginVersion == null) {
            throw new IllegalArgumentException("Unable to detect plugin.version");
        }
        return pluginVersion;
    }

    public ProjectBuilder setTestProjectsRoot(File testProjectsRoot) {
        if (testProjectDir != null) {
            throw new IllegalArgumentException("projects root can't be changed after projects dir is set.");
        }
        this.testProjectsRoot = testProjectsRoot;
        return this;
    }

    public ProjectBuilder setTestProjectDir(File testProjectDir) {
        this.testProjectDir = testProjectDir;
        this.testPackageFile = new File(testProjectDir, TEST_PACKAGE_DEFAULT_NAME);

        // if we ever need different files, just create the setters.
        this.expectedFilesFile = new File(testProjectDir, "expected-files.txt");
        this.expectedOrderFile = new File(testProjectDir, "expected-file-order.txt");
        this.expectedManifestFile = new File(testProjectDir, "expected-manifest.txt");
        this.expectedFilterFile = new File(testProjectDir, "expected-filter.xml");
        this.expectedFilesWithChecksumsFile = new File(testProjectDir, "expected-files-with-checksums.txt");
        this.expectedLogLinesFile = new File(testProjectDir, "expected-log-lines.txt");
        this.logTxtFile = new File(testProjectDir, "log.txt");
        
        return this;
    }

    public ProjectBuilder setTestProjectDir(String relPath) {
        return setTestProjectDir(new File(testProjectsRoot, relPath));
    }

    
    public File getTestProjectDir() {
        return testProjectDir;
    }

    public ProjectBuilder setTestPackageFile(File testPackageFile) {
        this.testPackageFile = testPackageFile;
        return this;
    }

    public ProjectBuilder setTestPackageFile(String testPackageFileName) {
        this.setTestPackageFile(new File(testProjectDir, testPackageFileName));
        return this;
    }

    public File getTestPackageFile() {
        return testPackageFile;
    }

    public ProjectBuilder setTestGoals(String ... testGoals) {
        if (testGoals != null && testGoals.length != 0) {
            this.testGoals = testGoals;
        }
        return this;
    }

    public ProjectBuilder setBuildExpectedToFail(boolean buildExpectedToFail) {
        this.buildExpectedToFail = buildExpectedToFail;
        return this;
    }

    public ProjectBuilder setVerifyPackageContents(boolean verifyPackageContents) {
        this.verifyPackageContents = verifyPackageContents;
        return this;
    }

    public ProjectBuilder setProperty(String name, String value) {
        testProperties.put(name, value);
        return this;
    }

    public ProjectBuilder setExpectedFilesWithChecksumsFile(String expectedFilesWithChecksumsFile) {
        this.expectedFilesWithChecksumsFile = new File(testProjectDir, expectedFilesWithChecksumsFile);
        return this;
    }

    public ProjectBuilder build() throws VerificationException, IOException {
        Verifier verifier = new Verifier(testProjectDir.getAbsolutePath());
        verifier.setSystemProperties(testProperties);
        verifier.setDebug(true);
        verifier.setAutoclean(false);
        // verifier.setDebugJvm(true);
        // verifier.setMavenDebug(true);
        // propagate jacoco agent settings
        String jacocoAgentSettings = System.getProperty("jacoco.command");
        if (StringUtils.isNotBlank(jacocoAgentSettings)) {
            verifier.setEnvironmentVariable("MAVEN_OPTS", jacocoAgentSettings);
        }
        try {
            verifier.executeGoals(Arrays.asList(testGoals));
            assertFalse("Build expected to fail in project " + testProjectDir.getAbsolutePath(), buildExpectedToFail);
        } catch (VerificationException e) {
            if (buildExpectedToFail) {
                return this;
            }
            throw e;
        } finally {
            verifier.resetStreams();
        }
        verifier.verify(true);

        if (!verifyPackageContents) {
            return this;
        }

        // read zip
        pkgZipEntries = verifyPackageZipEntries(testPackageFile);
        return this;
    }

    static List<String> verifyPackageZipEntries(File packageFile) throws IOException {
        assertTrue("Project generates package file at " + packageFile, packageFile.exists());

        List<String> pkgZipEntries = new ArrayList<>();
        try (JarFile jar = new JarFile(packageFile)) {
            Enumeration<JarEntry> e = jar.entries();
            while (e.hasMoreElements()) {
                pkgZipEntries.add(e.nextElement().getName());
            }
        }
        // ensure that MANIFEST.MF is first entry
        String first = pkgZipEntries.get(0);
        if ("META-INF/".equals(first)) {
            first = pkgZipEntries.get(1);
        }
        assertEquals("MANIFEST.MF must be first entry in package " + packageFile, "META-INF/MANIFEST.MF", first);

        // ensure that there is a jcr_root directory
        assertTrue("Package does not contain mandatory 'jcr_root' folder in package " + packageFile, pkgZipEntries.contains("jcr_root/"));
        return pkgZipEntries;
    }
    public ProjectBuilder verifyPackageProperty(String key, String value) throws IOException {
        if (buildExpectedToFail) {
            return this;
        }
        assertEquals("Property '" + key + "' has correct value", value, getPackageProperty(key));
        return this;
    }

    public String getPackageProperty(String key) throws ZipException, IOException {
        Properties properties;
        try (ZipFile zip = new ZipFile(testPackageFile)) {
            ZipEntry propertiesFile = zip.getEntry("META-INF/vault/properties.xml");
            assertThat(propertiesFile, notNullValue());

            properties = new Properties();
            properties.loadFromXML(zip.getInputStream(propertiesFile));
        }
        return properties.getProperty(key);
    }

    public ProjectBuilder verifyExpectedManifest() throws IOException {
        final String expected = FileUtils.fileRead(expectedManifestFile);
        List<String> entries;
        String result;
        try (JarFile jar = new JarFile(testPackageFile)) {
            entries = new ArrayList<>();
            for (Map.Entry<Object, Object> e : jar.getManifest().getMainAttributes().entrySet()) {
                String key = e.getKey().toString();
                if (IGNORED_MANIFEST_ENTRIES.contains(key)) {
                    continue;
                }
                if ("Import-Package".equals(key)) {
                    // split export package so that we have a sorted set
                    Parameters params = new Parameters(e.getValue().toString());
                    for (Map.Entry<String, Attrs> entry : params.entrySet()) {
                        entries.add(key + ":" + entry.getKey() + ";" + entry.getValue());
                    }
                    continue;
                }
                entries.add(e.getKey() + ":" + e.getValue());
            }
        }
        Collections.sort(entries);
        result = StringUtils.join(entries.iterator(), "\n");
        assertEquals("Manifest", normalizeWhitespace(expected), normalizeWhitespace(result));
        return this;
    }

    public ProjectBuilder verifyExpectedFiles() throws IOException {
        verifyExpectedFiles(expectedFilesFile, pkgZipEntries);
        return this;
    }

    public ProjectBuilder verifyExpectedFiles(File expectedFilesFile, List<String> pkgZipEntries) throws IOException {
        // first check that only the expected entries are there in the package (regardless of the order)
        List<String> expectedEntries = Files.readAllLines(expectedFilesFile.toPath(), StandardCharsets.UTF_8);
        assertEquals("Package contains the expected entry names",
                toTidyString(expectedEntries),
                toTidyString(pkgZipEntries));
        return this;
    }

    public ProjectBuilder verifyExpectedFilesChecksum() throws IOException {
        List<String> expectedEntriesWithChecksums = Files.readAllLines(expectedFilesWithChecksumsFile.toPath(), StandardCharsets.UTF_8);
        for (String expectedEntryWithChecksum : expectedEntriesWithChecksums) {
            // split name and checksum
            String[] parts = expectedEntryWithChecksum.split(" ", 2);
            verifyExpectedFileChecksum(parts[0], parts[1]);
        }
        return this;
    }

    public ProjectBuilder verifyExpectedFileChecksum(String name, String checksum) throws IOException {
        // the second part must be a hexadecimal CRC32 checksum
        final long expectedChecksum = Long.parseLong(checksum, 16);
        try (JarFile jar = new JarFile(testPackageFile)) {
            JarEntry entry = jar.getJarEntry(name);
            if (entry == null) {
                fail("Could not find entry with name " + name + " in package " + testPackageFile);
            }
            Assert.assertThat(entry, new JarEntryMatcher(name, jar, expectedChecksum));
        }
        return this;
    }

    private final static class JarEntryMatcher extends TypeSafeMatcher<JarEntry> {

        private final String name;
        private final long expectedCrc; 
        private final JarFile jarFile;
        public JarEntryMatcher(String name, JarFile jarFile, long expectedCrc) {
            this.name = name;
            this.jarFile = jarFile;
            this.expectedCrc = expectedCrc;
        }

        @Override
        protected void describeMismatchSafely(JarEntry item, Description mismatchDescription) {
            mismatchDescription.appendText("was Jar entry with name ").appendValue(item.getName()).appendText(" having the CRC ").appendValue(Long.toHexString(item.getCrc()));
            try (Reader reader = new BoundedReader(new InputStreamReader(jarFile.getInputStream(item), StandardCharsets.UTF_8), 8000)) {
                String content = IOUtils.toString(reader);
                // make new line visible
                content = content.replaceAll("\r", Matcher.quoteReplacement("\r")).replaceAll("\n",  Matcher.quoteReplacement("\n"));
                mismatchDescription.appendText(" (").appendValue(content).appendText(")");
            } catch (IOException e) {
                mismatchDescription.appendText(" (Could not extract value due to exception ").appendValue(e).appendText(")");
            }
        }

        @Override
        protected boolean matchesSafely(JarEntry item) {
            return expectedCrc == item.getCrc();
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("Jar entry with name ").appendValue(name).appendText(" having the CRC ").appendValue(Long.toHexString(expectedCrc));
        }
    }

    public ProjectBuilder verifyExpectedFilesOrder() throws IOException {
        List<String> expectedEntriesInOrder= Files.readAllLines(expectedOrderFile.toPath(), StandardCharsets.UTF_8);
        assertThat("Order of entries within package", pkgZipEntries, Matchers.containsInRelativeOrder(expectedEntriesInOrder.toArray()));
        return this;
    }

    public ProjectBuilder verifyExpectedFilter() throws IOException {
        if (buildExpectedToFail) {
            return this;
        }
        try (ZipFile zip = new ZipFile(testPackageFile)) {
            ZipEntry entry = zip.getEntry("META-INF/vault/filter.xml");
            assertNotNull("package has a filter.xml", entry);
            String result = IOUtil.toString(zip.getInputStream(entry), "utf-8");
            String expected = FileUtils.fileRead(expectedFilterFile);
            assertEquals("filter.xml is correct", normalizeWhitespace(expected), normalizeWhitespace(result));
        }
        return this;
    }

    public ProjectBuilder verifyExpectedFilterInWorkDirectory(final String workDirectory) throws IOException {
        if (buildExpectedToFail) {
            return this;
        }
        File workDirFile = new File(testProjectDir, workDirectory);
        assertTrue("workDirectory should exist: " + workDirFile.toString(), workDirFile.isDirectory());
        File filterFile = new File(workDirFile, "META-INF/vault/filter.xml");
        assertTrue("filterFile should exist: " + filterFile.toString(), filterFile.isFile());
        String result = FileUtils.fileRead(filterFile);
        String expected = FileUtils.fileRead(expectedFilterFile);
        assertEquals("filter.xml is incorrect", normalizeWhitespace(expected), normalizeWhitespace(result));
        return this;
    }

    public ProjectBuilder verifyExpectedLogLines(String... placeholderValues) throws IOException {
        List<String> expectedLogLines = Files.readAllLines(expectedLogLinesFile.toPath());
        List<String> actualLogLines = getBuildOutput();
        for (String expectedLogLine : expectedLogLines) {
            // do placeholder replacement
            
            Matcher matcher = PLACEHOLDER_PATTERN.matcher(expectedLogLine);
            while (matcher.find()) {
                int placeholderIndex = Integer.parseInt(matcher.group(1));
                if (placeholderIndex >= placeholderValues.length) {
                    throw new IllegalArgumentException("At least " + placeholderIndex + " placeholder values need to be given, but only "+ placeholderValues.length + " received.");
                }
                // replace current item in iterator with the new value
                expectedLogLine = matcher.replaceAll(Matcher.quoteReplacement(placeholderValues[placeholderIndex]));
            }
            // update list
            assertThat("Could not find the expected log line in the output '" + logTxtFile +"'", actualLogLines, Matchers.hasItem(expectedLogLine));
        }
        // support not and exists
        return this;
    }
    public List<String> getBuildOutput() throws IOException {
        return Files.readAllLines(logTxtFile.toPath(), StandardCharsets.UTF_8);
    }

    private String toTidyString(List<String> lines) {
        String[] copy = lines.toArray(new String[lines.size()]);
        Arrays.sort(copy);
        StringBuilder buf = new StringBuilder();
        for (String line: copy) {
            buf.append(line).append("\n");
        }
        return buf.toString();
    }

    /**
     * Eliminates differences in line separators when executing tests on different platform (*nix / windows)
     */
    private String normalizeWhitespace(String s) {
        return s.replaceAll("[\r\n]+", "\n");
    }
}
