/*
 *  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
 *
 *      https://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.ivy.util;

import org.apache.ivy.core.settings.TimeoutConstraint;
import org.apache.ivy.util.url.TimeoutConstrainedURLHandler;
import org.apache.ivy.util.url.URLHandler;
import org.apache.ivy.util.url.URLHandlerRegistry;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.jar.JarOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipInputStream;

import static java.util.jar.Pack200.newUnpacker;

/**
 * Utility class used to deal with file related operations, like copy, full reading, symlink, ...
 */
public final class FileUtil {

    private FileUtil() {
        // Utility class
    }

    // according to tests by users, 64kB seems to be a good value for the buffer used during copy;
    // further improvements could be obtained using NIO API
    private static final int BUFFER_SIZE = 64 * 1024;

    private static final byte[] EMPTY_BUFFER = new byte[0];

    /**
     * Creates a symbolic link at {@code link} whose target will be the {@code target}. Depending
     * on the underlying filesystem, this method may not always be able to create a symbolic link,
     * in which case this method returns {@code false}.
     *
     * @param target    The {@link File} which will be the target of the symlink being created
     * @param link      The path to the symlink that needs to be created
     * @param overwrite {@code true} if any existing file at {@code link} has to be overwritten.
     *                  False otherwise
     * @return Returns true if the symlink was successfully created. Returns false if the symlink
     * could not be created
     * @throws IOException if {@link Files#createSymbolicLink} fails
     */
    public static boolean symlink(final File target, final File link, final boolean overwrite)
            throws IOException {
        // prepare for symlink
        if (target.isFile()) {
            // it's a file that is being symlinked, so do the necessary preparation
            // for the linking, similar to what we do with preparation for copying
            if (!prepareCopy(target, link, overwrite)) {
                return false;
            }
        } else {
            // it's a directory being symlinked

            // see if the directory represented by the "link" exists and is already a symbolic
            // link. If it is and if we are asked to overwrite then we *only* break the link
            // in preparation of symlink creation, later in this method
            if (Files.isSymbolicLink(link.toPath()) && overwrite) {
                Message.verbose("Un-linking existing symbolic link " + link + " during symlink creation, since overwrite=true");
                Files.delete(link.toPath());
            }
            // make sure the "link" that is being created has the necessary parent directories
            // in place before triggering symlink creation
            if (link.getParentFile() != null) {
                link.getParentFile().mkdirs();
            }
        }
        Files.createSymbolicLink(link.toPath(), target.getAbsoluteFile().toPath());
        return true;
    }

    /**
     * This is the same as calling {@link #copy(File, File, CopyProgressListener, boolean)} with
     * {@code overwrite} param as {@code true}
     *
     * @param src  The source to copy
     * @param dest The destination
     * @param l    A {@link CopyProgressListener}. Can be null
     * @return Returns true if the file was copied. Else returns false
     * @throws IOException If any exception occurs during the copy operation
     */
    public static boolean copy(File src, File dest, CopyProgressListener l) throws IOException {
        return copy(src, dest, l, false);
    }

    public static boolean prepareCopy(final File src, final File dest, final boolean overwrite) throws IOException {
        if (src.isDirectory()) {
            if (dest.exists()) {
                if (!dest.isDirectory()) {
                    throw new IOException("impossible to copy: destination is not a directory: "
                            + dest);
                }
            } else {
                dest.mkdirs();
            }
            return true;
        }
        // else it is a file copy
        if (dest.exists()) {
            // If overwrite is specified as "true" and the dest file happens to be a symlink,
            // we delete the "link" (a.k.a unlink it). This is for cases like
            // https://issues.apache.org/jira/browse/IVY-1498 where not unlinking the existing
            // symlink can lead to potentially overwriting the wrong "target" file
            // TODO: This behaviour is intentionally hardcoded here for now, since I don't
            // see a reason (yet) to expose it as a param of this method. If any use case arises
            // we can have this behaviour decided by the callers of this method, by passing
            // a value for this param
            final boolean unlinkSymlinkIfOverwrite = true;
            if (!dest.isFile()) {
                throw new IOException("impossible to copy: destination is not a file: " + dest);
            }
            if (overwrite) {
                if (Files.isSymbolicLink(dest.toPath()) && unlinkSymlinkIfOverwrite) {
                    // unlink (a.k.a delete the symlink path)
                    dest.delete();
                } else if (!dest.canWrite()) {
                    // if the file *isn't* "writable" (see javadoc of File.canWrite() on what
                    // that means) we delete it.
                    dest.delete();
                } // if dest is writable, the copy will overwrite it without requiring a delete
            } else {
                Message.verbose(dest + " already exists, nothing done");
                return false;
            }
        }
        if (dest.getParentFile() != null) {
            dest.getParentFile().mkdirs();
        }
        return true;
    }

    public static boolean copy(File src, File dest, CopyProgressListener l, boolean overwrite)
            throws IOException {
        if (!prepareCopy(src, dest, overwrite)) {
            return false;
        }
        if (src.isDirectory()) {
            return deepCopy(src, dest, l, overwrite);
        }
        // else it is a file copy
        // check if it's the same file (the src and the dest). if they are the same, skip the copy
        try {
            if (Files.isSameFile(src.toPath(), dest.toPath())) {
                Message.verbose("Skipping copy of file " + src + " to " + dest + " since they are the same file");
                // we consider the file as copied if overwrite is true
                return overwrite;
            }
        } catch (NoSuchFileException nsfe) {
            // ignore and move on and attempt the copy
        } catch (IOException ioe) {
            // log and move on and attempt the copy
            Message.verbose("Could not determine if " + src + " and dest " + dest + " are the same file", ioe);
        }
        copy(new FileInputStream(src), dest, l);
        long srcLen = src.length();
        long destLen = dest.length();
        if (srcLen != destLen) {
            dest.delete();
            throw new IOException("size of source file " + src.toString() + "(" + srcLen
                    + ") differs from size of dest file " + dest.toString() + "(" + destLen
                    + ") - please retry");
        }
        dest.setLastModified(src.lastModified());
        return true;
    }

    public static boolean deepCopy(File src, File dest, CopyProgressListener l, boolean overwrite)
            throws IOException {
        // the list of files which already exist in the destination folder
        List<File> existingChild = Collections.emptyList();
        if (dest.exists()) {
            if (!dest.isDirectory()) {
                // not expected type, remove
                dest.delete();
                // and create a folder
                dest.mkdirs();
                dest.setLastModified(src.lastModified());
            } else {
                // existing folder, gather existing children
                File[] children = dest.listFiles();
                if (children != null) {
                    existingChild = new ArrayList<>(Arrays.asList(children));
                }
            }
        } else {
            dest.mkdirs();
            dest.setLastModified(src.lastModified());
        }
        // copy files one by one
        File[] toCopy = src.listFiles();
        if (toCopy != null) {
            for (File cf : toCopy) {
                // compute the destination file
                File childDest = new File(dest, cf.getName());
                // if file existing, 'mark' it as taken care of
                if (!existingChild.isEmpty()) {
                    existingChild.remove(childDest);
                }
                if (cf.isDirectory()) {
                    deepCopy(cf, childDest, l, overwrite);
                } else {
                    copy(cf, childDest, l, overwrite);
                }
            }
        }
        // some file exist in the destination but not in the source: delete them
        for (File child : existingChild) {
            forceDelete(child);
        }
        return true;
    }

    @SuppressWarnings("deprecation")
    public static void copy(final URL src, final File dest, final CopyProgressListener listener,
                            final TimeoutConstraint timeoutConstraint) throws IOException {
        final URLHandler handler = URLHandlerRegistry.getDefault();
        if (handler instanceof TimeoutConstrainedURLHandler) {
            ((TimeoutConstrainedURLHandler) handler).download(src, dest, listener, timeoutConstraint);
            return;
        }
        handler.download(src, dest, listener);
    }

    @SuppressWarnings("deprecation")
    public static void copy(final File src, final URL dest, final CopyProgressListener listener,
                            final TimeoutConstraint timeoutConstraint) throws IOException {
        final URLHandler handler = URLHandlerRegistry.getDefault();
        if (handler instanceof TimeoutConstrainedURLHandler) {
            ((TimeoutConstrainedURLHandler) handler).upload(src, dest, listener, timeoutConstraint);
            return;
        }
        handler.upload(src, dest, listener);
    }

    public static void copy(InputStream src, File dest, CopyProgressListener l) throws IOException {
        if (dest.getParentFile() != null) {
            dest.getParentFile().mkdirs();
        }
        copy(src, new FileOutputStream(dest), l);
    }

    public static void copy(InputStream src, OutputStream dest, CopyProgressListener l)
            throws IOException {
        copy(src, dest, l, true);
    }

    public static void copy(InputStream src, OutputStream dest, CopyProgressListener l,
            boolean autoClose) throws IOException {
        CopyProgressEvent evt = null;
        if (l != null) {
            evt = new CopyProgressEvent();
        }
        try {
            byte[] buffer = new byte[BUFFER_SIZE];
            int c;
            long total = 0;

            if (l != null) {
                l.start(evt);
            }
            while ((c = src.read(buffer)) != -1) {
                if (Thread.currentThread().isInterrupted()) {
                    throw new IOException("transfer interrupted");
                }
                dest.write(buffer, 0, c);
                total += c;
                if (l != null) {
                    l.progress(evt.update(buffer, c, total));
                }
            }

            if (l != null) {
                evt.update(EMPTY_BUFFER, 0, total);
            }

            try {
                dest.flush();
            } catch (IOException ex) {
                // ignore
            }

            // close the streams
            if (autoClose) {
                src.close();
                dest.close();
            }
        } finally {
            if (autoClose) {
                try {
                    src.close();
                } catch (IOException ex) {
                    // ignore
                }
                try {
                    dest.close();
                } catch (IOException ex) {
                    // ignore
                }
            }
        }

        if (l != null) {
            l.end(evt);
        }
    }

    /**
     * Reads the whole BufferedReader line by line, using \n as line separator for each line.
     * <p>
     * Note that this method will add a final \n to the last line even though there is no new line
     * character at the end of last line in the original reader.
     * </p>
     * <p>
     * The BufferedReader is closed when this method returns.
     * </p>
     *
     * @param in
     *            the {@link BufferedReader} to read from
     * @return a String with the whole content read from the {@link BufferedReader}
     * @throws IOException
     *             if an IO problems occur during reading
     */
    public static String readEntirely(BufferedReader in) throws IOException {
        try {
            StringBuilder buf = new StringBuilder();

            String line = in.readLine();
            while (line != null) {
                buf.append(line).append("\n");
                line = in.readLine();
            }
            return buf.toString();
        } finally {
            in.close();
        }
    }

    /**
     * Reads the entire content of the file and returns it as a String.
     *
     * @param f
     *            the file to read from
     * @return a String with the file content
     * @throws IOException
     *             if an IO problems occurs during reading
     */
    public static String readEntirely(File f) throws IOException {
        return readEntirely(new FileInputStream(f));
    }

    /**
     * Reads the entire content of the {@link InputStream} and returns it as a String.
     * <p>
     * The input stream is closed when this method returns.
     * </p>
     *
     * @param is
     *            the {@link InputStream} to read from
     * @return a String with the input stream content
     * @throws IOException
     *             if an IO problems occurs during reading
     */
    public static String readEntirely(InputStream is) throws IOException {
        try {
            StringBuilder sb = new StringBuilder();
            byte[] buffer = new byte[BUFFER_SIZE];
            int c;

            while ((c = is.read(buffer)) != -1) {
                sb.append(new String(buffer, 0, c));
            }
            return sb.toString();
        } finally {
            is.close();
        }
    }

    public static String concat(String dir, String file) {
        return dir + "/" + file;
    }

    /**
     * Recursively delete file
     *
     * @param file
     *            the file to delete
     * @return true if the deletion completed successfully (ie if the file does not exist on the
     *         filesystem after this call), false if a deletion was not performed successfully.
     */
    public static boolean forceDelete(File file) {
        if (!file.exists()) {
            return true;
        }
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files != null) {
                for (File df : files) {
                    if (!forceDelete(df)) {
                        return false;
                    }
                }
            }
        }
        return file.delete();
    }

    /**
     * Returns a list of Files composed of all directories being parent of file and child of root +
     * file and root themselves. Example: <code>getPathFiles(new File("test"), new
     * File("test/dir1/dir2/file.txt")) =&gt; {new File("test/dir1"), new File("test/dir1/dir2"),
     * new File("test/dir1/dir2/file.txt") }</code> Note that if root is not an ancestor of file, or
     * if root is null, all directories from the file system root will be returned.
     *
     * @param root File
     * @param file File
     * @return List&lt;File&gt;
     */
    public static List<File> getPathFiles(File root, File file) {
        List<File> ret = new ArrayList<>();
        while (file != null && !file.getAbsolutePath().equals(root.getAbsolutePath())) {
            ret.add(file);
            file = file.getParentFile();
        }
        if (root != null) {
            ret.add(root);
        }
        Collections.reverse(ret);
        return ret;
    }

    /**
     * @param dir
     *            The directory from which all files, including files in subdirectory) are
     *            extracted.
     * @param ignore
     *            a Collection of filenames which must be excluded from listing
     * @return a collection containing all the files of the given directory and it's subdirectories,
     *         recursively.
     */
    public static Collection<File> listAll(File dir, Collection<String> ignore) {
        return listAll(dir, new ArrayList<File>(), ignore);
    }

    private static Collection<File> listAll(File file, Collection<File> list,
            Collection<String> ignore) {
        if (ignore.contains(file.getName())) {
            return list;
        }

        if (file.exists()) {
            list.add(file);
        }
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File lf : files) {
                listAll(lf, list, ignore);
            }
        }
        return list;
    }

    public static File resolveFile(File file, String filename) {
        File result = new File(filename);
        if (!result.isAbsolute()) {
            result = new File(file, filename);
        }

        return normalize(result.getPath());
    }

    // ////////////////////////////////////////////
    // The following code comes from Ant FileUtils
    // ////////////////////////////////////////////

    /**
     * &quot;Normalize&quot; the given absolute path.
     *
     * <p>
     * This includes:
     * <ul>
     * <li>Uppercase the drive letter if there is one.</li>
     * <li>Remove redundant slashes after the drive spec.</li>
     * <li>Resolve all ./, .\, ../ and ..\ sequences.</li>
     * <li>DOS style paths that start with a drive letter will have \ as the separator.</li>
     * </ul>
     * Unlike {@link File#getCanonicalPath()} this method specifically does not resolve symbolic
     * links.
     *
     * @param path the path to be normalized.
     * @return the normalized version of the path.
     * @throws NullPointerException if path is null.
     */
    public static File normalize(final String path) {
        final Stack<String> s = new Stack<>();
        final DissectedPath dissectedPath = dissect(path);
        s.push(dissectedPath.root);

        final StringTokenizer tok = new StringTokenizer(dissectedPath.remainingPath, File.separator);
        while (tok.hasMoreTokens()) {
            String thisToken = tok.nextToken();
            if (".".equals(thisToken)) {
                continue;
            }
            if ("..".equals(thisToken)) {
                if (s.size() < 2) {
                    // Cannot resolve it, so skip it.
                    return new File(path);
                }
                s.pop();
            } else { // plain component
                s.push(thisToken);
            }
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < s.size(); i++) {
            if (i > 1) {
                // not before the filesystem root and not after it, since root
                // already contains one
                sb.append(File.separatorChar);
            }
            sb.append(s.elementAt(i));
        }
        return new File(sb.toString());
    }

    /**
     * Dissect the specified absolute path.
     *
     * @param path
     *            the path to dissect.
     * @return {@link DissectedPath}
     * @throws java.lang.NullPointerException
     *             if path is null.
     * @since Ant 1.7
     */
    private static DissectedPath dissect(final String path) {
        final char sep = File.separatorChar;
        final String pathToDissect = path.replace('/', sep).replace('\\', sep).trim();

        // check if the path starts with a filesystem root
        final File[] filesystemRoots = File.listRoots();
        if (filesystemRoots != null) {
            for (final File filesystemRoot : filesystemRoots) {
                if (pathToDissect.startsWith(filesystemRoot.getPath())) {
                    // filesystem root is the root and the rest of the path is the "remaining path"
                    final String root = filesystemRoot.getPath();
                    final String rest = pathToDissect.substring(root.length());
                    final StringBuilder sbPath = new StringBuilder();
                    // Eliminate consecutive slashes after the drive spec:
                    for (int i = 0; i < rest.length(); i++) {
                        final char currentChar = rest.charAt(i);
                        if (i == 0) {
                            sbPath.append(currentChar);
                            continue;
                        }
                        final char previousChar = rest.charAt(i - 1);
                        if (currentChar != sep || previousChar != sep) {
                            sbPath.append(currentChar);
                        }
                    }
                    return new DissectedPath(root, sbPath.toString());
                }
            }
        }
        // UNC drive
        if (pathToDissect.length() > 1 && pathToDissect.charAt(1) == sep) {
            int nextsep = pathToDissect.indexOf(sep, 2);
            nextsep = pathToDissect.indexOf(sep, nextsep + 1);
            final String root = (nextsep > 2) ? pathToDissect.substring(0, nextsep + 1) : pathToDissect;
            final String rest = pathToDissect.substring(root.length());
            return new DissectedPath(root, rest);
        }

        return new DissectedPath(File.separator, pathToDissect);
    }

    /**
     * Learn whether one path "leads" another.
     *
     * <p>This method uses {@link #normalize} under the covers and
     * does not resolve symbolic links.</p>
     *
     * <p>If either path tries to go beyond the file system root
     * (i.e. it contains more ".." segments than can be travelled up)
     * the method will return false.</p>
     *
     * @param leading The leading path, must not be null, must be absolute.
     * @param path The path to check, must not be null, must be absolute.
     * @return true if path starts with leading; false otherwise.
     * @since Ant 1.7
     */
    public static boolean isLeadingPath(File leading, File path) {
        String l = normalize(leading.getAbsolutePath()).getAbsolutePath();
        String p = normalize(path.getAbsolutePath()).getAbsolutePath();
        if (l.equals(p)) {
            return true;
        }
        // ensure that l ends with a /
        // so we never think /foo was a parent directory of /foobar
        if (!l.endsWith(File.separator)) {
            l += File.separator;
        }
        // ensure "/foo/"  is not considered a parent of "/foo/../../bar"
        String up = File.separator + ".." + File.separator;
        if (l.contains(up) || p.contains(up) || (p + File.separator).contains(up)) {
            return false;
        }
        return p.startsWith(l);
    }

    /**
     * Learn whether one path "leads" another.
     *
     * @param leading The leading path, must not be null, must be absolute.
     * @param path The path to check, must not be null, must be absolute.
     * @param resolveSymlinks whether symbolic links shall be resolved
     * prior to comparing the paths.
     * @return true if path starts with leading; false otherwise.
     * @since Ant 1.9.13
     * @throws IOException if resolveSymlinks is true and invoking
     * getCanonicaPath on either argument throws an exception
     */
    public static boolean isLeadingPath(File leading, File path, boolean resolveSymlinks)
        throws IOException {
        if (!resolveSymlinks) {
            return isLeadingPath(leading, path);
        }
        final File l = leading.getCanonicalFile();
        File p = path.getCanonicalFile();
        do {
            if (l.equals(p)) {
                return true;
            }
            p = p.getParentFile();
        } while (p != null);
        return false;
    }

    /**
     * Get the length of the file, or the sum of the children lengths if it is a directory
     *
     * @param file File
     * @return long
     */
    public static long getFileLength(File file) {
        long l = 0;
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files != null) {
                for (File gf : files) {
                    l += getFileLength(gf);
                }
            }
        } else {
            l = file.length();
        }
        return l;
    }

    public static InputStream unwrapPack200(InputStream packed) throws IOException {
        BufferedInputStream buffered = new BufferedInputStream(packed);
        buffered.mark(4);
        byte[] magic = new byte[4];
        buffered.read(magic, 0, 4);
        buffered.reset();

        InputStream in = buffered;

        if (magic[0] == (byte) 0x1F && magic[1] == (byte) 0x8B && magic[2] == (byte) 0x08) {
            // this is a gziped pack200
            in = new GZIPInputStream(in);
        }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        JarOutputStream jar = new JarOutputStream(baos);
        newUnpacker().unpack(new UncloseInputStream(in), jar);
        jar.close();
        return new ByteArrayInputStream(baos.toByteArray());
    }

    /**
     * Wrap an input stream and do not close the stream on call to close(). Used to avoid closing a
     * {@link ZipInputStream} used with {@link Pack200.Unpacker#unpack(File, JarOutputStream)}
     */
    private static final class UncloseInputStream extends InputStream {

        private InputStream wrapped;

        public UncloseInputStream(InputStream wrapped) {
            this.wrapped = wrapped;
        }

        @Override
        public void close() throws IOException {
            // do not close
        }

        @Override
        public int read() throws IOException {
            return wrapped.read();
        }

        @Override
        public int hashCode() {
            return wrapped.hashCode();
        }

        @Override
        public int read(byte[] b) throws IOException {
            return wrapped.read(b);
        }

        @Override
        public boolean equals(Object obj) {
            return wrapped.equals(obj);
        }

        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            return wrapped.read(b, off, len);
        }

        @Override
        public long skip(long n) throws IOException {
            return wrapped.skip(n);
        }

        @Override
        public String toString() {
            return wrapped.toString();
        }

        @Override
        public int available() throws IOException {
            return wrapped.available();
        }

        @Override
        public void mark(int readlimit) {
            wrapped.mark(readlimit);
        }

        @Override
        public void reset() throws IOException {
            wrapped.reset();
        }

        @Override
        public boolean markSupported() {
            return wrapped.markSupported();
        }

    }

    private static final class DissectedPath {
        private final String root;

        private final String remainingPath;

        private DissectedPath(final String root, final String remainingPath) {
            this.root = root;
            this.remainingPath = remainingPath;
        }

        @Override
        public String toString() {
            return "Dissected Path [root=" + root + ", remainingPath="
                    + remainingPath + "]";
        }
    }
}
