/*
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.io;

import lombok.experimental.UtilityClass;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;

/**
 * Utility methods for basic file operations.
 *
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 */
@UtilityClass
public class FileUtils {

    /**
     * Deletes specified file.
     * It works for every path, including non-empty directories.
     *
     * @param file file
     * @throws IOException on error
     */
    public static void delete(Path file) throws IOException {
        delete(file.toFile());
    }

    /**
     * Deletes specified file.
     * It works for every path, including non-empty directories.
     *
     * @param file file
     * @throws IOException on error
     */
    public static void delete(File file) throws IOException {
        if(!file.exists()) { 
			return; 
		}
		if (file.isDirectory()) {
			File[] files = file.listFiles();
			if(null != files) {
				for(File s : files) {
					delete(s);
				}
			}
		}
		Files.delete(file.toPath());
    }

    /**
     * Reads content of provided file
     *
     * @param file file
     * @return array
     * @throws IOException on error
     */
    public static byte[] content(Path file) throws IOException {
        return Files.readAllBytes(file);
    }

    /**
     * Copy "input" file into "output".
     * It creates all intermediate directories, if necessary.
     * It does not support copying directories.
     *
     * @param input input
     * @param output output
     * @throws IOException on error
     */
    public static void copy(File input, File output) throws IOException {
        File parent = output.getParentFile();
        if(!parent.exists() && !parent.mkdirs()) {
            throw new IOException("Can not create output directory: " + parent);
        }
        IOStreams.copy(new FileInputStream(input), new FileOutputStream(output));
    }

    /**
     * Reads content of provided file
     *
     * @param file file
     * @return array
     * @throws IOException on error
     */
    public static byte[] content(File file) throws IOException {
        try (RandomAccessFile istream = new RandomAccessFile(file, "r")) {
            byte[] content = new byte[ (int)istream.length() ];
            istream.readFully(content);
            return content;
        }
    }
    
    /**
     * Compare content of files.
     *
     * @param file1 file1
     * @param file2 file2
     * @return bool
     * @throws IOException on error
     */
    public static boolean equivalent(File file1, File file2) throws IOException {
        if(file1.equals(file2)) {
			return true;
		}
        if(file1.getCanonicalFile().equals(file2.getCanonicalFile())) {
            return true;
        }
		if(file1.length() != file2.length()) {
			return false;
		}
        try(
            InputStream istream1=new FileInputStream(file1);
            InputStream istream2=new FileInputStream(file2)
        ) {
            return IOStreams.equals(istream1, istream2);
        }
    }
    
}
