package id.iptek.utms.agent.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author Jaka Ramdani
 */
public class FileUtil {

    private static Logger log = LoggerFactory.getLogger(FileUtil.class);

    private FileUtil() {
    }

    public static void copy(String srcPath, String dstPath) throws IOException, Exception {
        copy(srcPath, dstPath, false);
    }

    public static void copy(String srcPath, String dstPath, boolean overwrite) throws IOException, Exception {
        log.debug("\"{}\" -> \"{}\"", srcPath, dstPath);
        File srcFile = new File(srcPath);
        File dstFile = new File(dstPath);

        if (srcFile.exists() && !srcFile.isDirectory()) {
            if (dstFile.exists() && dstFile.isDirectory()) {
                String[] _filenames = srcPath.split("[\\/\\\\]");
                dstFile = new File(dstFile, _filenames[_filenames.length - 1]);
            } else if (dstFile.exists() && !overwrite) {
                throw new IOException("Destination file \"" + dstPath + "\" is exists, not overwriting file.");
            } else if (dstFile.exists()) {
                //remove existing file
                if (!dstFile.delete()) {
                    throw new IOException("Can not remove old destination file \"" + dstPath + "\".");
                }
            }
            //create new file
            byte[] srcBytes = StreamUtil.read(new FileInputStream(srcFile));
            StreamUtil.write(new FileOutputStream(dstFile), srcBytes, true);
        } else {
            throw new IOException("Source file \"" + srcFile + "\" is not exists or is a directory.");
        }
    }

    public static void move(String srcPath, String dstPath) throws IOException, Exception {
        move(srcPath, dstPath, false);
    }

    public static void move(String srcPath, String dstPath, boolean overwrite) throws IOException, Exception {
        copy(srcPath, dstPath, overwrite);
        delete(srcPath);
    }

    public static boolean delete(String path) throws IOException, Exception {
        File srcFile = new File(path);
        if (srcFile.exists() && !srcFile.isDirectory()) {
            boolean deleted = new File(path).delete();
            if (deleted) {
                log.debug("\"{}\" removed", path);
            } else {
                log.debug("\"{}\" NOT removed", path);
            }
            return deleted;
        } else {
            throw new IOException("Source file \"" + srcFile + "\" is not exists or is a directory.");
        }
    }

    public static String[] list(String path) throws IOException, Exception {
        log.debug("list: \"{}\"", path);
        return new File(path).list();
    }

    public static String[] list(String path, FilenameFilter fileNameFilter) throws IOException, Exception {
        log.debug("list: \"{}\"", path);
        return new File(path).list(fileNameFilter);
    }

    public static File[] listFiles(File parent, FilenameFilter fileNameFilter) throws IOException, Exception {
        return listFiles(parent, fileNameFilter, false);
    }

    public static File[] listFiles(File parent, FilenameFilter fileNameFilter, boolean nameOrdered) throws IOException, Exception {
        return listFiles(parent.getAbsolutePath(), fileNameFilter, nameOrdered);
    }

    public static File[] listFiles(String path, FilenameFilter fileNameFilter) throws IOException, Exception {
        return listFiles(path, fileNameFilter, false);
    }

    public static File[] listFiles(String path, FilenameFilter fileNameFilter, boolean nameOrdered) throws IOException, Exception {
        log.debug("list: \"{}\"", path);
        File[] files = new File(path).listFiles(fileNameFilter);
        if (nameOrdered) {
            Arrays.sort(files, new Comparator<File>() {

                @Override
                public int compare(File f1, File f2) {
                    return f2.getName().compareTo(f1.getName());
                }
            });
        }
        return files;
    }

    public static boolean mkdirs(String path) throws IOException, Exception {
        return mkdirs(path, false);
    }

    public static boolean mkdirs(String path, boolean silentOnExists) throws IOException, Exception {
        File file = new File(path);
        if (file.exists()) {
            if (silentOnExists) {
                log.debug("\"{}\" is already exists. keep silence ..", path);
                return true;
            }
            throw new IOException("\"" + path + "\" is already exists.");
        }
        boolean created = file.mkdirs();
        if (created) {
            log.debug("\"{}\" created", path);
        } else {
            log.debug("\"{}\" NOT created", path);
        }
        return created;
    }
}
