/*
 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package jdk.tools.jlink.internal.plugins;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import jdk.tools.jlink.internal.ModuleEntryImpl;
import jdk.tools.jlink.plugin.PluginException;
import jdk.tools.jlink.plugin.ModuleEntry;
import jdk.tools.jlink.plugin.ModulePool;
import jdk.tools.jlink.plugin.TransformerPlugin;
import jdk.tools.jlink.internal.Utils;

/**
 *
 * Copy files to image from various locations.
 */
public class FileCopierPlugin implements TransformerPlugin {

    public static final String NAME = "copy-files";

    private static final class CopiedFile {

        Path source;
        Path target;
    }
    public static final String FAKE_MODULE = "$jlink-file-copier";

    private final List<CopiedFile> files = new ArrayList<>();

    /**
     * Symbolic link to another path.
     */
    public static abstract class SymImageFile extends ModuleEntryImpl {

        private final String targetPath;

        public SymImageFile(String targetPath, String module, String path,
                ModuleEntry.Type type, InputStream stream, long size) {
            super(module, path, type, stream, size);
            this.targetPath = targetPath;
        }

        public String getTargetPath() {
            return targetPath;
        }
    }

    private static final class SymImageFileImpl extends SymImageFile {

        public SymImageFileImpl(String targetPath, Path file, String module,
                String path, ModuleEntry.Type type) {
            super(targetPath, module, path, type, newStream(file), length(file));
        }
    }

    private static long length(Path file) {
        try {
            return Files.size(file);
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    private static InputStream newStream(Path file) {
        try {
            return Files.newInputStream(file);
        } catch (IOException ex) {
            throw new UncheckedIOException(ex);
        }
    }

    private static final class DirectoryCopy implements FileVisitor<Path> {

        private final Path source;
        private final ModulePool pool;
        private final String targetDir;
        private final List<SymImageFile> symlinks = new ArrayList<>();

        DirectoryCopy(Path source, ModulePool pool, String targetDir) {
            this.source = source;
            this.pool = pool;
            this.targetDir = targetDir;
        }

        @Override
        public FileVisitResult preVisitDirectory(Path dir,
                BasicFileAttributes attrs) throws IOException {
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFile(Path file,
                BasicFileAttributes attrs) throws IOException {
            Objects.requireNonNull(file);
            Objects.requireNonNull(attrs);
            String path = targetDir + "/" + source.relativize(file);
            if (attrs.isSymbolicLink()) {
                Path symTarget = Files.readSymbolicLink(file);
                if (!Files.exists(symTarget)) {
                    // relative to file parent?
                    Path parent = file.getParent();
                    if (parent != null) {
                        symTarget = parent.resolve(symTarget);
                    }
                }
                if (!Files.exists(symTarget)) {
                    System.err.println("WARNING: Skipping sym link, target "
                            + Files.readSymbolicLink(file) + "not found");
                    return FileVisitResult.CONTINUE;
                }
                SymImageFileImpl impl = new SymImageFileImpl(symTarget.toString(),
                        file, path, Objects.requireNonNull(file.getFileName()).toString(),
                        ModuleEntry.Type.OTHER);
                symlinks.add(impl);
            } else {
                addFile(pool, file, path);
            }
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc)
                throws IOException {
            if (exc != null) {
                throw exc;
            }
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFileFailed(Path file, IOException exc)
                throws IOException {
            throw exc;
        }
    }

    private static void addFile(ModulePool pool, Path file, String path)
            throws IOException {
        Objects.requireNonNull(pool);
        Objects.requireNonNull(file);
        Objects.requireNonNull(path);
        ModuleEntry impl = ModuleEntry.create(FAKE_MODULE,
                "/" + FAKE_MODULE + "/other/" + path,
                ModuleEntry.Type.OTHER, newStream(file), length(file));
        try {
            pool.add(impl);
        } catch (Exception ex) {
            throw new IOException(ex);
        }
    }

    @Override
    public Set<Category> getType() {
        Set<Category> set = new HashSet<>();
        set.add(Category.TRANSFORMER);
        return Collections.unmodifiableSet(set);
    }

    @Override
    public void configure(Map<String, String> config) {
        List<String> arguments = Utils.parseList(config.get(NAME));
        if (arguments.isEmpty()) {
            throw new RuntimeException("Invalid argument for " + NAME);
        }

        String javahome = System.getProperty("java.home");
        for (String a : arguments) {
            int i = a.indexOf("=");
            CopiedFile cf = new CopiedFile();
            if (i == -1) {
                Path file = Paths.get(a);
                if (file.isAbsolute()) {
                    cf.source = file;
                    // The target is the image root directory.
                    cf.target = file.getFileName();
                } else {
                    file = new File(javahome, a).toPath();
                    cf.source = file;
                    cf.target = Paths.get(a);
                }
            } else {
                String target = a.substring(i + 1);
                String f = a.substring(0, i);
                Path file = Paths.get(f);
                if (file.isAbsolute()) {
                    cf.source = file;
                } else {
                    cf.source = new File(javahome,
                            file.toFile().getPath()).toPath();
                }
                cf.target = Paths.get(target);
            }
            if (!Files.exists(cf.source)) {
                System.err.println("Skipping file " + cf.source
                        + ", it doesn't exist");
            } else {
                files.add(cf);
            }
        }
    }

    @Override
    public void visit(ModulePool in, ModulePool out) {
        in.transformAndCopy((file) -> {
            return file;
        }, out);

        // Add new files.
        try {
            for (CopiedFile file : files) {
                if (Files.isRegularFile(file.source)) {
                    addFile(out, file.source, file.target.toString());
                } else if (Files.isDirectory(file.source)) {
                    DirectoryCopy dc = new DirectoryCopy(file.source,
                            out, file.target.toString());
                    Files.walkFileTree(file.source, dc);
                    // Add symlinks after actual content
                    for (SymImageFile imf : dc.symlinks) {
                        try {
                            out.add(imf);
                        } catch (Exception ex) {
                            throw new PluginException(ex);
                        }
                    }
                }
            }
        } catch (IOException ex) {
            throw new UncheckedIOException(ex);
        }
    }

    @Override
    public String getName() {
        return NAME;
    }

    @Override
    public String getDescription() {
        return PluginsResourceBundle.getDescription(NAME);
    }

    @Override
    public boolean hasArguments() {
        return true;
    }

    @Override
    public String getArgumentsDescription() {
       return PluginsResourceBundle.getArgument(NAME);
    }
}
