/*
 * Copyright (c) 2009, 2012, 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 com.sun.tools.javac.nio;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import javax.lang.model.SourceVersion;
import javax.tools.FileObject;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.StandardLocation;

import static java.nio.file.FileVisitOption.*;
import static javax.tools.StandardLocation.*;

import com.sun.tools.javac.util.BaseFileManager;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;

import static com.sun.tools.javac.main.Option.*;


// NOTE the imports carefully for this compilation unit.
//
// Path:  java.nio.file.Path -- the new NIO type for which this file manager exists
//
// Paths: com.sun.tools.javac.file.Paths -- legacy javac type for handling path options
//      The other Paths (java.nio.file.Paths) is not used

// NOTE this and related classes depend on new API in JDK 7.
// This requires special handling while bootstrapping the JDK build,
// when these classes might not yet have been compiled. To workaround
// this, the build arranges to make stubs of these classes available
// when compiling this and related classes. The set of stub files
// is specified in make/build.properties.

/**
 *  Implementation of PathFileManager: a JavaFileManager based on the use
 *  of java.nio.file.Path.
 *
 *  <p>Just as a Path is somewhat analagous to a File, so too is this
 *  JavacPathFileManager analogous to JavacFileManager, as it relates to the
 *  support of FileObjects based on File objects (i.e. just RegularFileObject,
 *  not ZipFileObject and its variants.)
 *
 *  <p>The default values for the standard locations supported by this file
 *  manager are the same as the default values provided by JavacFileManager --
 *  i.e. as determined by the javac.file.Paths class. To override these values,
 *  call {@link #setLocation}.
 *
 *  <p>To reduce confusion with Path objects, the locations such as "class path",
 *  "source path", etc, are generically referred to here as "search paths".
 *
 *  <p><b>This is NOT part of any supported API.
 *  If you write code that depends on this, you do so at your own risk.
 *  This code and its internal interfaces are subject to change or
 *  deletion without notice.</b>
 */
public class JavacPathFileManager extends BaseFileManager implements PathFileManager {
    protected FileSystem defaultFileSystem;

    /**
     * Create a JavacPathFileManager using a given context, optionally registering
     * it as the JavaFileManager for that context.
     */
    public JavacPathFileManager(Context context, boolean register, Charset charset) {
        super(charset);
        if (register)
            context.put(JavaFileManager.class, this);
        pathsForLocation = new HashMap<>();
        fileSystems = new HashMap<>();
        setContext(context);
    }

    /**
     * Set the context for JavacPathFileManager.
     */
    @Override
    public void setContext(Context context) {
        super.setContext(context);
    }

    @Override
    public FileSystem getDefaultFileSystem() {
        if (defaultFileSystem == null)
            defaultFileSystem = FileSystems.getDefault();
        return defaultFileSystem;
    }

    @Override
    public void setDefaultFileSystem(FileSystem fs) {
        defaultFileSystem = fs;
    }

    @Override
    public void flush() throws IOException {
        contentCache.clear();
    }

    @Override
    public void close() throws IOException {
        for (FileSystem fs: fileSystems.values())
            fs.close();
    }

    @Override
    public ClassLoader getClassLoader(Location location) {
        nullCheck(location);
        Iterable<? extends Path> path = getLocation(location);
        if (path == null)
            return null;
        ListBuffer<URL> lb = new ListBuffer<>();
        for (Path p: path) {
            try {
                lb.append(p.toUri().toURL());
            } catch (MalformedURLException e) {
                throw new AssertionError(e);
            }
        }

        return getClassLoader(lb.toArray(new URL[lb.size()]));
    }

    @Override
    public boolean isDefaultBootClassPath() {
        return locations.isDefaultBootClassPath();
    }

    // <editor-fold defaultstate="collapsed" desc="Location handling">

    public boolean hasLocation(Location location) {
        return (getLocation(location) != null);
    }

    public Iterable<? extends Path> getLocation(Location location) {
        nullCheck(location);
        lazyInitSearchPaths();
        PathsForLocation path = pathsForLocation.get(location);
        if (path == null && !pathsForLocation.containsKey(location)) {
            setDefaultForLocation(location);
            path = pathsForLocation.get(location);
        }
        return path;
    }

    private Path getOutputLocation(Location location) {
        Iterable<? extends Path> paths = getLocation(location);
        return (paths == null ? null : paths.iterator().next());
    }

    public void setLocation(Location location, Iterable<? extends Path> searchPath)
            throws IOException
    {
        nullCheck(location);
        lazyInitSearchPaths();
        if (searchPath == null) {
            setDefaultForLocation(location);
        } else {
            if (location.isOutputLocation())
                checkOutputPath(searchPath);
            PathsForLocation pl = new PathsForLocation();
            for (Path p: searchPath)
                pl.add(p);  // TODO -Xlint:path warn if path not found
            pathsForLocation.put(location, pl);
        }
    }

    private void checkOutputPath(Iterable<? extends Path> searchPath) throws IOException {
        Iterator<? extends Path> pathIter = searchPath.iterator();
        if (!pathIter.hasNext())
            throw new IllegalArgumentException("empty path for directory");
        Path path = pathIter.next();
        if (pathIter.hasNext())
            throw new IllegalArgumentException("path too long for directory");
        if (!isDirectory(path))
            throw new IOException(path + ": not a directory");
    }

    private void setDefaultForLocation(Location locn) {
        Collection<File> files = null;
        if (locn instanceof StandardLocation) {
            switch ((StandardLocation) locn) {
                case CLASS_PATH:
                    files = locations.userClassPath();
                    break;
                case PLATFORM_CLASS_PATH:
                    files = locations.bootClassPath();
                    break;
                case SOURCE_PATH:
                    files = locations.sourcePath();
                    break;
                case CLASS_OUTPUT: {
                    String arg = options.get(D);
                    files = (arg == null ? null : Collections.singleton(new File(arg)));
                    break;
                }
                case SOURCE_OUTPUT: {
                    String arg = options.get(S);
                    files = (arg == null ? null : Collections.singleton(new File(arg)));
                    break;
                }
            }
        }

        PathsForLocation pl = new PathsForLocation();
        if (files != null) {
            for (File f: files)
                pl.add(f.toPath());
        }
        if (!pl.isEmpty())
            pathsForLocation.put(locn, pl);
    }

    private void lazyInitSearchPaths() {
        if (!inited) {
            setDefaultForLocation(PLATFORM_CLASS_PATH);
            setDefaultForLocation(CLASS_PATH);
            setDefaultForLocation(SOURCE_PATH);
            inited = true;
        }
    }
    // where
        private boolean inited = false;

    private Map<Location, PathsForLocation> pathsForLocation;

    private static class PathsForLocation extends LinkedHashSet<Path> {
        private static final long serialVersionUID = 6788510222394486733L;
    }

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="FileObject handling">

    @Override
    public Path getPath(FileObject fo) {
        nullCheck(fo);
        if (!(fo instanceof PathFileObject))
            throw new IllegalArgumentException();
        return ((PathFileObject) fo).getPath();
    }

    @Override
    public boolean isSameFile(FileObject a, FileObject b) {
        nullCheck(a);
        nullCheck(b);
        if (!(a instanceof PathFileObject))
            throw new IllegalArgumentException("Not supported: " + a);
        if (!(b instanceof PathFileObject))
            throw new IllegalArgumentException("Not supported: " + b);
        return ((PathFileObject) a).isSameFile((PathFileObject) b);
    }

    @Override
    public Iterable<JavaFileObject> list(Location location,
            String packageName, Set<Kind> kinds, boolean recurse)
            throws IOException {
        // validatePackageName(packageName);
        nullCheck(packageName);
        nullCheck(kinds);

        Iterable<? extends Path> paths = getLocation(location);
        if (paths == null)
            return List.nil();
        ListBuffer<JavaFileObject> results = new ListBuffer<>();

        for (Path path : paths)
            list(path, packageName, kinds, recurse, results);

        return results.toList();
    }

    private void list(Path path, String packageName, final Set<Kind> kinds,
            boolean recurse, final ListBuffer<JavaFileObject> results)
            throws IOException {
        if (!Files.exists(path))
            return;

        final Path pathDir;
        if (isDirectory(path))
            pathDir = path;
        else {
            FileSystem fs = getFileSystem(path);
            if (fs == null)
                return;
            pathDir = fs.getRootDirectories().iterator().next();
        }
        String sep = path.getFileSystem().getSeparator();
        Path packageDir = packageName.isEmpty() ? pathDir
                : pathDir.resolve(packageName.replace(".", sep));
        if (!Files.exists(packageDir))
            return;

/* Alternate impl of list, superceded by use of Files.walkFileTree */
//        Deque<Path> queue = new LinkedList<Path>();
//        queue.add(packageDir);
//
//        Path dir;
//        while ((dir = queue.poll()) != null) {
//            DirectoryStream<Path> ds = dir.newDirectoryStream();
//            try {
//                for (Path p: ds) {
//                    String name = p.getFileName().toString();
//                    if (isDirectory(p)) {
//                        if (recurse && SourceVersion.isIdentifier(name)) {
//                            queue.add(p);
//                        }
//                    } else {
//                        if (kinds.contains(getKind(name))) {
//                            JavaFileObject fe =
//                                PathFileObject.createDirectoryPathFileObject(this, p, pathDir);
//                            results.append(fe);
//                        }
//                    }
//                }
//            } finally {
//                ds.close();
//            }
//        }
        int maxDepth = (recurse ? Integer.MAX_VALUE : 1);
        Set<FileVisitOption> opts = EnumSet.of(FOLLOW_LINKS);
        Files.walkFileTree(packageDir, opts, maxDepth,
                new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
                Path name = dir.getFileName();
                if (name == null || SourceVersion.isIdentifier(name.toString())) // JSR 292?
                    return FileVisitResult.CONTINUE;
                else
                    return FileVisitResult.SKIP_SUBTREE;
            }

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                if (attrs.isRegularFile() && kinds.contains(getKind(file.getFileName().toString()))) {
                    JavaFileObject fe =
                        PathFileObject.createDirectoryPathFileObject(
                            JavacPathFileManager.this, file, pathDir);
                    results.append(fe);
                }
                return FileVisitResult.CONTINUE;
            }
        });
    }

    @Override
    public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(
        Iterable<? extends Path> paths) {
        ArrayList<PathFileObject> result;
        if (paths instanceof Collection<?>)
            result = new ArrayList<>(((Collection<?>)paths).size());
        else
            result = new ArrayList<>();
        for (Path p: paths)
            result.add(PathFileObject.createSimplePathFileObject(this, nullCheck(p)));
        return result;
    }

    @Override
    public Iterable<? extends JavaFileObject> getJavaFileObjects(Path... paths) {
        return getJavaFileObjectsFromPaths(Arrays.asList(nullCheck(paths)));
    }

    @Override
    public JavaFileObject getJavaFileForInput(Location location,
            String className, Kind kind) throws IOException {
        return getFileForInput(location, getRelativePath(className, kind));
    }

    @Override
    public FileObject getFileForInput(Location location,
            String packageName, String relativeName) throws IOException {
        return getFileForInput(location, getRelativePath(packageName, relativeName));
    }

    private JavaFileObject getFileForInput(Location location, String relativePath)
            throws IOException {
        for (Path p: getLocation(location)) {
            if (isDirectory(p)) {
                Path f = resolve(p, relativePath);
                if (Files.exists(f))
                    return PathFileObject.createDirectoryPathFileObject(this, f, p);
            } else {
                FileSystem fs = getFileSystem(p);
                if (fs != null) {
                    Path file = getPath(fs, relativePath);
                    if (Files.exists(file))
                        return PathFileObject.createJarPathFileObject(this, file);
                }
            }
        }
        return null;
    }

    @Override
    public JavaFileObject getJavaFileForOutput(Location location,
            String className, Kind kind, FileObject sibling) throws IOException {
        return getFileForOutput(location, getRelativePath(className, kind), sibling);
    }

    @Override
    public FileObject getFileForOutput(Location location, String packageName,
            String relativeName, FileObject sibling)
            throws IOException {
        return getFileForOutput(location, getRelativePath(packageName, relativeName), sibling);
    }

    private JavaFileObject getFileForOutput(Location location,
            String relativePath, FileObject sibling) {
        Path dir = getOutputLocation(location);
        if (dir == null) {
            if (location == CLASS_OUTPUT) {
                Path siblingDir = null;
                if (sibling != null && sibling instanceof PathFileObject) {
                    siblingDir = ((PathFileObject) sibling).getPath().getParent();
                }
                return PathFileObject.createSiblingPathFileObject(this,
                        siblingDir.resolve(getBaseName(relativePath)),
                        relativePath);
            } else if (location == SOURCE_OUTPUT) {
                dir = getOutputLocation(CLASS_OUTPUT);
            }
        }

        Path file;
        if (dir != null) {
            file = resolve(dir, relativePath);
            return PathFileObject.createDirectoryPathFileObject(this, file, dir);
        } else {
            file = getPath(getDefaultFileSystem(), relativePath);
            return PathFileObject.createSimplePathFileObject(this, file);
        }

    }

    @Override
    public String inferBinaryName(Location location, JavaFileObject fo) {
        nullCheck(fo);
        // Need to match the path semantics of list(location, ...)
        Iterable<? extends Path> paths = getLocation(location);
        if (paths == null) {
            return null;
        }

        if (!(fo instanceof PathFileObject))
            throw new IllegalArgumentException(fo.getClass().getName());

        return ((PathFileObject) fo).inferBinaryName(paths);
    }

    private FileSystem getFileSystem(Path p) throws IOException {
        FileSystem fs = fileSystems.get(p);
        if (fs == null) {
            fs = FileSystems.newFileSystem(p, null);
            fileSystems.put(p, fs);
        }
        return fs;
    }

    private Map<Path,FileSystem> fileSystems;

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Utility methods">

    private static String getRelativePath(String className, Kind kind) {
        return className.replace(".", "/") + kind.extension;
    }

    private static String getRelativePath(String packageName, String relativeName) {
        return packageName.isEmpty()
                ? relativeName : packageName.replace(".", "/") + "/" + relativeName;
    }

    private static String getBaseName(String relativePath) {
        int lastSep = relativePath.lastIndexOf("/");
        return relativePath.substring(lastSep + 1); // safe if "/" not found
    }

    private static boolean isDirectory(Path path) throws IOException {
        BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
        return attrs.isDirectory();
    }

    private static Path getPath(FileSystem fs, String relativePath) {
        return fs.getPath(relativePath.replace("/", fs.getSeparator()));
    }

    private static Path resolve(Path base, String relativePath) {
        FileSystem fs = base.getFileSystem();
        Path rp = fs.getPath(relativePath.replace("/", fs.getSeparator()));
        return base.resolve(rp);
    }

    // </editor-fold>

}
