//   Copyright 2012 Georg-August-Universität Göttingen, Germany
//
//   Licensed 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
//
//       http://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 de.ugoe.cs.util;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

/**
 * <p>
 * Helper class that provides methods that simplify working with files.
 * </p>
 * 
 * @author Steffen Herbold
 * @version 1.0
 */
public class FileTools {

    /**
     * <p>
     * Private constructor to prevent initializing of the class.
     * </p>
     */
    private FileTools() {

    }

    /**
     * <p>
     * Returns an array of the lines contained in a file. The line separator is
     * {@link StringTools#ENDLINE}.
     * </p>
     * 
     * @param filename
     *            name of the file
     * @return string array, where each line contains a file
     * @throws IOException
     *             see {@link FileReader#read(char[])}, {@link FileReader#close()}
     * @throws FileNotFoundException
     *             see {@link FileReader#FileReader(File)}
     */
    public static String[] getLinesFromFile(String filename) throws IOException,
        FileNotFoundException
    {
        boolean carriageReturn = true;
        if (StringTools.ENDLINE.equals("\n")) {
            carriageReturn = false;
        }
        return getLinesFromFile(filename, carriageReturn);
    }

    /**
     * <p>
     * Returns an array of the lines contained in a file.
     * </p>
     * 
     * @param filename
     *            name of the file
     * @param carriageReturn
     *            if true, "\r\n", if false "\n" is used as line separator
     * @return string array, where each line contains a file
     * @throws IOException
     *             see {@link FileReader#read(char[])}, {@link FileReader#close()}
     * @throws FileNotFoundException
     *             see {@link FileReader#FileReader(File)}
     */
    public static String[] getLinesFromFile(String filename, boolean carriageReturn)
        throws IOException, FileNotFoundException
    {
        File f = new File(filename);
        FileInputStream fis = new FileInputStream(f);
        InputStreamReader reader = new InputStreamReader(fis, Charset.defaultCharset());
        char[] buffer = new char[(int) f.length()];
        reader.read(buffer);
        reader.close();
        String splitString;
        if (carriageReturn) {
            splitString = "\r\n";
        }
        else {
            splitString = "\n";
        }
        return (new String(buffer)).split(splitString);
    }

    /**
     * <p>
     * Writes an array to a file using the toString function of its object.
     * </p>
     * 
     * @param array
     *            array that is written
     * @param filename
     *            name of the output file
     * @param separator
     *            separator string that is put between the array objects
     * @param lineBreak
     *            if true, a new line is added after each array element and its separator
     * @throws IOException
     *             see {@link BufferedWriter#write(String)}, {@link BufferedWriter#newLine()},
     *             {@link BufferedWriter#flush()}, {@link BufferedWriter#close()},
     *             {@link FileWriter#FileWriter(String)}
     */
    public static <T> void writeArrayToFile(T[] array,
                                            String filename,
                                            String separator,
                                            boolean lineBreak) throws IOException
    {
        BufferedWriter outputWriter = null;
        outputWriter = new BufferedWriter(new FileWriter(filename));
        for (int i = 0; i < array.length; i++) {
            outputWriter.write(array[i].toString());
            if (i < array.length - 1) {
                outputWriter.write(separator);
                if (lineBreak) {
                    outputWriter.newLine();
                }
            }
        }
        outputWriter.flush();
        outputWriter.close();
    }

    /**
     * <p>
     * Autocompletes a given path. The path must be absolute. Otherwise, autocompletion is not
     * possible.
     * </p>
     * 
     * @param prefix
     *            the prefix to be complete
     * @return the auto completed path
     */
    public static String autoCompletePath(String prefix) {
        File prefixFile = new File(prefix);
        File parentDir = prefixFile.getParentFile();

        if (parentDir == null) {
            // the prefix does not denote a path or denotes one of the root directories.
            // this can not be auto completed
            return prefix;
        }

        String[] completions = null;

        if (parentDir.exists()) {
            completions = parentDir.list();
        }

        if (completions == null) {
            completions = new String[0];
        }

        String completedPrefix;

        completedPrefix = StringTools.autocomplete(prefixFile.getName(), completions);

        File completedFile = new File(parentDir, completedPrefix);

        if (completedFile.exists() && completedFile.isDirectory()) {
            return completedFile.getAbsolutePath() + File.separator;
        }
        else {
            return (parentDir.getAbsolutePath() + File.separator + completedPrefix)
                .replaceAll("//", "/");
        }
    }

}
