/*
 * 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.sling.maven.slingstart;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.lang.reflect.Field;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.handler.ArtifactHandler;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Build;
import org.apache.maven.project.MavenProject;
import org.apache.sling.provisioning.model.Model;
import org.apache.sling.provisioning.model.io.ModelReader;
import org.codehaus.plexus.archiver.UnArchiver;
import org.codehaus.plexus.archiver.manager.ArchiverManager;
import org.junit.Test;
import org.mockito.Mockito;

public class PreparePackageMojoTest {
    @Test
    public void testBSNRenaming() throws Exception {
        // Provide the system with some artifacts that are known to be in the local .m2 repo
        // These are explicitly included in the test section of the pom.xml
        PreparePackageMojo ppm = getMojoUnderTest(
                "org.apache.sling/org.apache.sling.commons.classloader/1.3.2",
                "org.apache.sling/org.apache.sling.commons.classloader/1.3.2/app",
                "org.apache.sling/org.apache.sling.commons.johnzon/1.0.0");
        try {
            String modelTxt = "[feature name=:launchpad]\n" +
                    "[artifacts]\n" +
                    "  org.apache.sling/org.apache.sling.commons.classloader/1.3.2\n" +
                    "" +
                    "[feature name=rename_test]\n" +
                    "  org.apache.sling/org.apache.sling.commons.johnzon/1.0.0 [bundle:rename-bsn=r-foo.bar.renamed.sling.commons.johnzon]\n";

            Model model = ModelReader.read(new StringReader(modelTxt), null);
            ppm.execute(model);

            File orgJar = getMavenArtifactFile(getMavenRepoRoot(), "org.apache.sling", "org.apache.sling.commons.johnzon", "1.0.0");
            File generatedJar = new File(ppm.getTmpDir(), "r-foo.bar.renamed.sling.commons.johnzon-1.0.0.jar");

            compareJarContents(orgJar, generatedJar);

            try (JarFile jfOrg = new JarFile(orgJar);
                JarFile jfNew = new JarFile(generatedJar)) {
                Manifest mfOrg = jfOrg.getManifest();
                Manifest mfNew = jfNew.getManifest();

                Attributes orgAttrs = mfOrg.getMainAttributes();
                Attributes newAttrs = mfNew.getMainAttributes();
                for (Object key : orgAttrs.keySet()) {
                    String orgVal = orgAttrs.getValue(key.toString());
                    String newVal = newAttrs.getValue(key.toString());

                    if ("Bundle-SymbolicName".equals(key.toString())) {
                        assertEquals("Should have recorded the original Bundle-SymbolicName",
                                orgVal, newAttrs.getValue("X-Original-Bundle-SymbolicName"));

                        assertEquals("r-foo.bar.renamed.sling.commons.johnzon", newVal);
                    } else {
                        assertEquals("Different keys: " + key, orgVal, newVal);
                    }
                }
            }
        } finally {
            FileUtils.deleteDirectory(new File(ppm.project.getBuild().getDirectory()));
        }
    }

    private static void compareJarContents(File orgJar, File actualJar) throws IOException {
        try (JarInputStream jis1 = new JarInputStream(new FileInputStream(orgJar));
            JarInputStream jis2 = new JarInputStream(new FileInputStream(actualJar))) {
            JarEntry je1 = null;
            while ((je1 = jis1.getNextJarEntry()) != null) {
                if (je1.isDirectory())
                    continue;

                JarEntry je2 = null;
                while((je2 = jis2.getNextJarEntry()) != null) {
                    if (!je2.isDirectory())
                        break;
                }

                assertEquals(je1.getName(), je2.getName());
                assertEquals(je1.getSize(), je2.getSize());

                try {
                    byte[] buf1 = IOUtils.toByteArray(jis1);
                    byte[] buf2 = IOUtils.toByteArray(jis2);

                    assertArrayEquals("Contents not equal: " + je1.getName(), buf1, buf2);
                } finally {
                    jis1.closeEntry();
                    jis2.closeEntry();
                }
            }
        }
    }

    @Test
    public void testSubsystemBaseGeneration() throws Exception {
        // Provide the system with some artifacts that are known to be in the local .m2 repo
        // These are explicitly included in the test section of the pom.xml
        PreparePackageMojo ppm = getMojoUnderTest(
                "org.apache.sling/org.apache.sling.commons.classloader/1.3.2",
                "org.apache.sling/org.apache.sling.commons.classloader/1.3.2/app",
                "org.apache.sling/org.apache.sling.commons.contentdetection/1.0.2",
                "org.apache.sling/org.apache.sling.commons.johnzon/1.0.0",
                "org.apache.sling/org.apache.sling.commons.mime/2.1.8",
                "org.apache.sling/org.apache.sling.commons.threads/3.2.0");

        try {
            // The launchpad feature is a prerequisite for the model
            String modelTxt =
                    "[feature name=:launchpad]\n" +
                    "[artifacts]\n" +
                    "  org.apache.sling/org.apache.sling.commons.classloader/1.3.2\n" +
                    "" +
                    "[feature name=test1 type=osgi.subsystem.composite]\n" +
                    "" +
                    "[:subsystem-manifest startLevel=123]\n" +
                    "  Subsystem-Description: Extra subsystem headers can go here including very long ones that would span multiple lines in a manifest\n" +
                    "  Subsystem-Copyright: (c) 2015 yeah!\n" +
                    "" +
                    "[artifacts startLevel=10]\n" +
                    "  org.apache.sling/org.apache.sling.commons.johnzon/1.0.0\n" +
                    "  org.apache.sling/org.apache.sling.commons.mime/2.1.8\n" +
                    "" +
                    "[artifacts startLevel=20 runModes=foo,bar,:blah]\n" +
                    "  org.apache.sling/org.apache.sling.commons.threads/3.2.0\n" +
                    "" +
                    "[artifacts startLevel=100 runModes=bar]\n" +
                    "  org.apache.sling/org.apache.sling.commons.contentdetection/1.0.2\n";
            Model model = ModelReader.read(new StringReader(modelTxt), null);
            ppm.execute(model);

            File generatedFile = new File(ppm.getTmpDir(), "test1.subsystem-base");
            try (JarFile jf = new JarFile(generatedFile)) {
                // Test META-INF/MANIFEST.MF
                Manifest mf = jf.getManifest();
                Attributes attrs = mf.getMainAttributes();
                String expected = "Potential_Bundles/10/org.apache.sling.commons.johnzon-1.0.0.jar|"
                        + "Potential_Bundles/10/org.apache.sling.commons.mime-2.1.8.jar";
                assertEquals(expected, attrs.getValue("_all_"));
                assertEquals("Potential_Bundles/20/org.apache.sling.commons.threads-3.2.0.jar", attrs.getValue("foo"));
                assertEquals("Potential_Bundles/20/org.apache.sling.commons.threads-3.2.0.jar|"
                        + "Potential_Bundles/100/org.apache.sling.commons.contentdetection-1.0.2.jar", attrs.getValue("bar"));

                // Test SUBSYSTEM-MANIFEST-BASE.MF
                ZipEntry smbZE = jf.getEntry("SUBSYSTEM-MANIFEST-BASE.MF");
                try (InputStream smbIS = jf.getInputStream(smbZE)) {
                    Manifest smbMF = new Manifest(smbIS);
                    Attributes smbAttrs = smbMF.getMainAttributes();
                    assertEquals("test1", smbAttrs.getValue("Subsystem-SymbolicName"));
                    assertEquals("osgi.subsystem.composite", smbAttrs.getValue("Subsystem-Type"));
                    assertEquals("(c) 2015 yeah!", smbAttrs.getValue("Subsystem-Copyright"));
                    assertEquals("Extra subsystem headers can go here including very long ones "
                            + "that would span multiple lines in a manifest",
                            smbAttrs.getValue("Subsystem-Description"));
                }

                // Test embedded bundles
                File mrr = getMavenRepoRoot();

                File sjj = getMavenArtifactFile(mrr, "org.apache.sling", "org.apache.sling.commons.johnzon", "1.0.0");
                ZipEntry sjZE = jf.getEntry("Potential_Bundles/10/org.apache.sling.commons.johnzon-1.0.0.jar");
                try (InputStream is = jf.getInputStream(sjZE)) {
                    assertArtifactsEqual(sjj, is);
                }

                File smj = getMavenArtifactFile(mrr, "org.apache.sling", "org.apache.sling.commons.mime", "2.1.8");
                ZipEntry smjZE = jf.getEntry("Potential_Bundles/10/org.apache.sling.commons.mime-2.1.8.jar");
                try (InputStream is = jf.getInputStream(smjZE)) {
                    assertArtifactsEqual(smj, is);
                }

                File stj = getMavenArtifactFile(mrr, "org.apache.sling", "org.apache.sling.commons.threads", "3.2.0");
                ZipEntry stjZE = jf.getEntry("Potential_Bundles/20/org.apache.sling.commons.threads-3.2.0.jar");
                try (InputStream is = jf.getInputStream(stjZE)) {
                    assertArtifactsEqual(stj, is);
                }

                File ctj = getMavenArtifactFile(mrr, "org.apache.sling", "org.apache.sling.commons.contentdetection", "1.0.2");
                ZipEntry ctjZE = jf.getEntry("Potential_Bundles/100/org.apache.sling.commons.contentdetection-1.0.2.jar");
                try (InputStream is = jf.getInputStream(ctjZE)) {
                    assertArtifactsEqual(ctj, is);
                }
            }
        } finally {
            FileUtils.deleteDirectory(new File(ppm.project.getBuild().getDirectory()));
        }
    }

    private void assertArtifactsEqual(File f, InputStream is) throws IOException {
        byte[] bytes1 = Files.readAllBytes(f.toPath());
        byte[] bytes2 = IOUtils.toByteArray(is);
        assertArrayEquals("Bytes not equal on file " + f.getName(), bytes1, bytes2);
    }

    private PreparePackageMojo getMojoUnderTest(String ... knownArtifacts) throws Exception {
        File mrr = getMavenRepoRoot();

        ArtifactHandler ah = Mockito.mock(ArtifactHandler.class);
        ArtifactHandlerManager ahm = Mockito.mock(ArtifactHandlerManager.class);
        Mockito.when(ahm.getArtifactHandler(Mockito.anyString())).thenReturn(ah);

        Set<org.apache.maven.artifact.Artifact> artifacts = new HashSet<>();
        for (String s : knownArtifacts) {
            String[] parts = s.split("[/]");
            switch (parts.length) {
            case 3:
                artifacts.add(getMavenArtifact(mrr, ah, parts[0], parts[1], parts[2]));
                break;
            case 4:
                artifacts.add(getMavenArtifact(mrr, ah, parts[0], parts[1], parts[2], parts[3]));
                break;
            default: throw new IllegalStateException(s);
            }
        }

        MavenProject mavenPrj = new MavenProject();
        Build build = new Build();
        Path tempDir = Files.createTempDirectory(getClass().getSimpleName());
        build.setOutputDirectory(tempDir.toString());
        build.setDirectory(tempDir.toString());
        mavenPrj.setBuild(build);
        mavenPrj.setDependencyArtifacts(artifacts);

        PreparePackageMojo ppm = new PreparePackageMojo();
        ppm.mavenSession = Mockito.mock(MavenSession.class);
        ppm.project = mavenPrj;
        ArchiverManager am = Mockito.mock(ArchiverManager.class);
        UnArchiver ua = Mockito.mock(UnArchiver.class);
        Mockito.when(am.getUnArchiver(Mockito.isA(File.class))).thenReturn(ua);
        setPrivateField(ppm, "archiverManager", am);
        setPrivateField(ppm, "artifactHandlerManager", ahm);
        setPrivateField(ppm, "resolver", Mockito.mock(ArtifactResolver.class));
        return ppm;
    }

    private org.apache.maven.artifact.Artifact getMavenArtifact(File repoRoot, ArtifactHandler ah, String gid, String aid, String ver) {
        return getMavenArtifact(repoRoot, ah, gid, aid, ver, null);
    }

    private org.apache.maven.artifact.Artifact getMavenArtifact(File repoRoot, ArtifactHandler ah, String gid, String aid, String ver, String classifier) {
        DefaultArtifact art = new DefaultArtifact(gid, aid, ver, "compile", "jar", classifier, ah);
        art.setFile(getMavenArtifactFile(repoRoot, gid, aid, ver));
        return art;
    }

    private File getMavenArtifactFile(File repoRoot, String gid, String aid, String ver) {
        return new File(repoRoot, gid.replace('.', File.separatorChar) + File.separatorChar + aid + File.separatorChar
                + ver + File.separatorChar + aid + '-' + ver + ".jar");
    }

    private File getMavenRepoRoot() throws IOException {
        URL res = getClass().getClassLoader().getResource(
                Test.class.getName().replace('.', '/') + ".class");

        String u = res.toExternalForm();
        if (u.startsWith("jar:"))
            u = u.substring(4);

        int idx = u.indexOf("junit");
        if (idx < 0)
            throw new IllegalStateException("Cannot infer maven repo root: " + res);

        return new File(new URL(u.substring(0, idx)).getFile());
    }

    private void setPrivateField(Object obj, String name, Object val) throws Exception {
        Field f = obj.getClass().getDeclaredField(name);
        f.setAccessible(true);
        f.set(obj, val);
    }
}
