/*
 * Licensed 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.felix.atomos.utils.core.plugins.index;

import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UncheckedIOException;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.FileTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.stream.Collectors;

import org.apache.felix.atomos.utils.api.Context;
import org.apache.felix.atomos.utils.api.FileType;
import org.apache.felix.atomos.utils.api.IndexInfo;
import org.apache.felix.atomos.utils.api.plugin.JarPlugin;
import org.apache.felix.atomos.utils.core.IndexInfoImpl;
import org.apache.felix.atomos.utils.substrate.impl.config.DefaultResourceConfiguration;
import org.apache.felix.atomos.utils.substrate.impl.json.ResourceJsonUtil;
import org.osgi.framework.Constants;

public class IndexPlugin implements JarPlugin<IndexPluginConfig>
{
    private static final String ATOMOS_BUNDLE_SEPARATOR = "ATOMOS_BUNDLE";

    public static final String ATOMOS_BUNDLES_BASE_PATH = "atomos/";
    public static final String ATOMOS_INDEX_FILE_NAME = "bundles.index";
    public static final String ATOMOS_BUNDLES_INDEX = ATOMOS_BUNDLES_BASE_PATH
        + ATOMOS_INDEX_FILE_NAME;

    public static final String ATOMOS_CATH_ALL = "atomos/.*$";

    private static final String ATOMOS_SUBSTRATE_JAR = "atomos.substrate.jar";

    private static boolean include(JarEntry entry)
    {
        final String path = entry.getName();
        if (entry.isDirectory() || isClass(path))
        {
            return false;
        }
        return true;
    }

    private static boolean isClass(String path)
    {
        return path.endsWith(".class");
    }

    private AtomicLong counter = new AtomicLong();

    JarOutputStream jos;

    private ArrayList<IndexInfo> sis;
    private Map<String, Boolean> uniquePaths;

    private Path substrateJar;

    private IndexPluginConfig config;

    @Override
    public void initJar(JarFile jar, Context context, URLClassLoader classLoader)
    {
        // Detect if there are duplicates using the uniquePaths map
        jar.stream().filter(IndexPlugin::include).forEach(e -> uniquePaths.compute(
            e.getName(),

            (p, b) -> //
                // Always treat the bundle manifest as a duplicate
                "META-INF/MANIFEST.MF".equals(p) //
                // Always treat root resources as duplicate
                || p.indexOf('/') < 0
                // Check if this path was found already
                || b != null //
                    ? Boolean.FALSE
                    : Boolean.TRUE));
    }

    @Override
    public void doJar(JarFile jar, Context context, URLClassLoader classLoader)
    {
        long id = counter.getAndIncrement();

        IndexInfoImpl info = new IndexInfoImpl();

        try
        {
            Manifest mf = jar.getManifest();
            Attributes attributes = mf == null ? null : mf.getMainAttributes();
            if (attributes != null)
            {
                info.setBsn(attributes.getValue(Constants.BUNDLE_SYMBOLICNAME));
                info.setVersion(attributes.getValue(Constants.BUNDLE_VERSION));
            }
        }
        catch (IOException e1)
        {

            e1.printStackTrace();
            return;
        }

        info.setId(Long.toString(id));

        if (info.getBundleSymbolicName() == null)
        {
            return;
        }
        if (info.getVersion() == null)
        {
            info.setVersion("0.0");
        }
        List<String> files = jar.stream().peek(j -> {
            try
            {
                if (Boolean.FALSE == uniquePaths.get(j.getName()))
                {
                    String fileName = ATOMOS_BUNDLES_BASE_PATH + id + "/" + j.getName();
                    if (isJarType())
                    {
                        final JarEntry entry = new JarEntry(fileName);
                        if (j.getCreationTime() != null)
                        {
                            entry.setCreationTime(j.getCreationTime());
                        }
                        if (j.getComment() != null)
                        {
                            entry.setComment(j.getComment());
                        }
                        jos.putNextEntry(entry);
                        jos.write(jar.getInputStream(j).readAllBytes());
                    }
                    else
                    {
                        Path path = config.indexOutputDirectory().resolve(fileName);
                        Files.createDirectories(path.getParent());
                        Files.write(path, jar.getInputStream(j).readAllBytes());
                        BasicFileAttributeView attrs = Files.getFileAttributeView(path,
                            BasicFileAttributeView.class);
                        FileTime time = j.getCreationTime();
                        attrs.setTimes(time, time, time);
                    }
                }
            }
            catch (final IOException e)
            {
                throw new UncheckedIOException(e);
            }

        }).map(JarEntry::getName).collect(Collectors.toList());

        info.setFiles(files);
        sis.add(info);
    }

    @Override
    public void init(IndexPluginConfig config)
    {
        this.config = config;
    }

    /**
     * @return
     */
    private boolean isJarType()
    {
        return IndexOutputType.JAR.equals(config.indexOutputType());
    }

    @Override
    public void postJars(Context context)
    {
        try
        {

            final List<String> bundleIndexLines = new ArrayList<>();
            final Collection<String> resources = new LinkedHashSet<>();
            sis.forEach(s -> {
                if (s.getBundleSymbolicName() != null)
                {
                    bundleIndexLines.add(ATOMOS_BUNDLE_SEPARATOR);
                    bundleIndexLines.add(s.getId());
                    bundleIndexLines.add(s.getBundleSymbolicName());
                    bundleIndexLines.add(s.getVersion());
                    s.getFiles().forEach(f -> {
                        bundleIndexLines.add(f);
                        if (!isClass(f))
                        {
                            if (Boolean.FALSE == uniquePaths.get(f))
                            {
                                resources.add(
                                    ATOMOS_BUNDLES_BASE_PATH + s.getId() + "/" + f);
                            }
                            if (!f.endsWith("/") && !"META-INF/MANIFEST.MF".equals(f))
                            {
                                resources.add(f);
                            }
                        }
                    });
                }
            });
            ByteArrayOutputStream indexBytes;
            try (final ByteArrayOutputStream out = new ByteArrayOutputStream();
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out)))
            {
                indexBytes = out;
                bundleIndexLines.forEach((l) -> {
                    try
                    {
                        writer.append(l).append('\n');
                    }
                    catch (final IOException ex)
                    {
                        throw new UncheckedIOException(ex);
                    }
                });
            }
            writeIndexFile(indexBytes.toByteArray(), context);

            if (isJarType())
            {
                writeGraalResourceConfig(resources, context);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (jos != null)
            {
                try
                {
                    jos.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }

        //after closing
        if (isJarType())
        {
            context.addFile(substrateJar, FileType.INDEX_JAR);
        }
        else
        {
            context.addFile(config.indexOutputDirectory(), FileType.INDEX_DIR);

        }
    }

    @Override
    public void preJars(Context context)
    {

        Path indexOutputDirectory = config.indexOutputDirectory();
        if (!indexOutputDirectory.toFile().isDirectory())
        {
            throw new IllegalArgumentException(
                "Output file must be a directory." + indexOutputDirectory);
        }
        if (!indexOutputDirectory.toFile().exists())
        {
            try
            {
                Files.createDirectories(indexOutputDirectory);
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }

        if (isJarType())
        {
            substrateJar = indexOutputDirectory.resolve(ATOMOS_SUBSTRATE_JAR);
            final Manifest manifest = new Manifest();
            manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
            try
            {
                jos = new JarOutputStream(new FileOutputStream(substrateJar.toFile()),
                    manifest);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
        counter = new AtomicLong(0);
        sis = new ArrayList<>();
        uniquePaths = new HashMap<>();
    }

    private void writeGraalResourceConfig(Collection<String> resources, Context context)
        throws IOException
    {
        resources.add(ATOMOS_CATH_ALL); // This alone could be enough,

        DefaultResourceConfiguration rci = new DefaultResourceConfiguration();
        rci.addResourcePattern(resources);
        context.addResourceConfig(rci);

        final String graalResConfJson = ResourceJsonUtil.json(rci);

        final JarEntry graalResConfEntry = new JarEntry(
            "META-INF/native-image/resource-config.json");
        jos.putNextEntry(graalResConfEntry);
        jos.write(graalResConfJson.getBytes());
        jos.flush();

    }

    private void writeIndexFile(final byte[] bytes, Context context) throws IOException
    {
        if (isJarType())
        {
            final JarEntry atomosIndexEntry = new JarEntry(ATOMOS_BUNDLES_INDEX);
            jos.putNextEntry(atomosIndexEntry);
            jos.write(bytes);
        }
        else
        {
            Files.write(config.indexOutputDirectory().resolve(ATOMOS_BUNDLES_INDEX),
                bytes);
        }
        DefaultResourceConfiguration resourceConfig = new DefaultResourceConfiguration();
        resourceConfig.addResourcePattern(ATOMOS_BUNDLES_INDEX);
        context.addResourceConfig(resourceConfig);
    }
}