package com.yizhi.application.course.util;

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 文件操作 https://www.cnblogs.com/IcanFixIt/p/4838375.html 过滤文件
 *
 * 参考https://howtodoinjava.com/java8/java-8-list-all-files-example/ 和 https://www.cnblogs.com/shihaiming/p/11237193.html
 */
public class PathUtils {

    /**
     *
     * @param path src/test/resources
     * @return
     */
    public static List<String> getPathsByDirectory(String path) throws IOException {

        Path folder = Paths.get(path);
        // Apache Commons IO 获取目录的大小
        /*File folder = new File("src/test/resources");
        long size = FileUtils.sizeOfDirectory(folder);*/
        //if(Files.exists(folder, LinkOption.NOFOLLOW_LINKS) && Files.isDirectory(folder)){// LinkOption.NOFOLLOW_LINKS 表示检测时不包含符号链接文件
        if(Files.notExists(folder)){
            //Path newDir = Files.createDirectory(folder);
            //Files.createDirectories()
            return null;
        }
        if(!Files.isDirectory(folder)){
            //Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING); 覆盖存在的文件
            //Files.move(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);
            //Files.delete(path);
            return null;
        }
        List<String> data = Files.walk(folder).filter(p-> !p.toFile().isHidden() && p.toFile().isFile() ).map(Path::toString).collect(Collectors.toList());

        return data;
    }

    /**
     * 大于等于文件大小进行获取目录下的文件列表
     * @param path
     * @param filesize 1024为1kb，204800L为200kb
     * @return
     * @throws IOException
     */
    public static List<String> getPathsByDirectoryGe(String path, final long filesize) throws IOException {
        Path folder = Paths.get(path);
        if(Files.notExists(folder)){
            return null;
        }
        if(!Files.isDirectory(folder)){
            return null;
        }
        // 可以使用过滤出文件，然后对文件进行.mapToLong(p -> p.toFile().length()).sum();
        List<String> data = Files.walk(folder).filter(p-> !p.toFile().isHidden() && p.toFile().isFile() && p.toFile().length()>=filesize).map(Path::toString).collect(Collectors.toList());

        return data;
    }

    /**
     * 小于文件大小进行获取目录下的文件列表
     * @param path
     * @param filesize 1024为1kb，204800L为200kb
     * @return
     * @throws IOException
     */
    public static List<String> getPathsByDirectoryLt(String path, final long filesize) throws IOException {
        Path folder = Paths.get(path);
        if(Files.notExists(folder)){
            return null;
        }
        if(!Files.isDirectory(folder)){
            return null;
        }
        // 可以使用过滤出文件，然后对文件进行.mapToLong(p -> p.toFile().length()).sum();
        List<String> data = Files.walk(folder).filter(p-> !p.toFile().isHidden() && p.toFile().isFile() && p.toFile().length()<filesize).map(Path::toString).collect(Collectors.toList());

        return data;
    }

/*    public static void main(String[] args) {
        try {
            List<String> data = getPathsByDirectory("/Users/xiehaijun/Downloads");
            for(String str : data){
                System.out.println(str);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }*/

    // FileVisitor的方法会在不同时机被调用： preVisitDirectory()在访问目录前被调用。postVisitDirectory()在访问后调用。
    // visitFile()会在整个遍历过程中的每次访问文件都被调用。他不是针对目录的，而是针对文件的。visitFileFailed()调用则是在文件访问失败的时候。例如，当缺少合适的权限或者其他错误。
    public static boolean deleteDirectory(String directory){
        Path rootPath = Paths.get(directory);

        try {
            Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    System.out.println("delete file: " + file.toString());
                    Files.delete(file);
                    return FileVisitResult.CONTINUE;
                    // CONTINE表示文件遍历和正常情况下一样继续。
                    // TERMINATE表示文件访问需要终止。
                    // SKIP_SIBLINGS表示文件访问继续，但是不需要访问其他同级文件或目录。
                    // SKIP_SUBTREE表示继续访问，但是不需要访问该目录下的子目录。这个枚举值仅在preVisitDirectory()中返回才有效。如果在另外几个方法中返回，那么会被理解为CONTINE。
                }

                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    Files.delete(dir);
                    System.out.println("delete dir: " + dir.toString());
                    return FileVisitResult.CONTINUE;
                }
            });
        } catch(IOException e){
            e.printStackTrace();
            return false;
        }
        return true;
    }
}
