/**
 * FileList.java
 *
 * Copyright (c) 2006 Ying-Chun Liu (PaulLiu)
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are 
 * met:
 *
 *  1. Redistributions of source code must retain the copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND
 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

package org.jlhafrontend;
import java.io.*;
import java.util.*;
import java.util.logging.*;

/**
 *   Maintaining a file list by given file/directory
 */
public class FileList {

    private LinkedHashSet filenameList=null;
    private Hashtable fileMark=null;

    private Logger mylogger=null;

    /**
     * Create empty FileList
     */
    public FileList() {
	mylogger = Logger.getLogger("org.jlhafrontend");
	
	filenameList = new LinkedHashSet();
    }

    /**
     * Create FileList with a file/directory
     *
     * @param filename the name of the file/directory
     */
    public FileList(String filename) {
	mylogger = Logger.getLogger("org.jlhafrontend");
	
	filenameList = new LinkedHashSet();
	addFile(filename);
    }

    /**
     * Create FileList with a set of files
     *
     * @param filename the given files/directories
     */
    public FileList(String[] filename) {
	mylogger = Logger.getLogger("org.jlhafrontend");
	
	filenameList = new LinkedHashSet();
	addFile(filename);
    }

	
    /**
     * add a file separator after a string if it is not 
     * ended with the file separator 
     *
     * @param a original string
     * @return new string with separator in the end
     */
    public static String addFileSeparator(String a) {
        String ret;
        if (a==null) {
            return a;
        }
        if (a.length()==0) {
            return File.separator;
        }
        if (a.charAt(a.length()-1)!=File.separatorChar) {
            ret = new String(a + File.separator);
        } else {
            ret = new String(a);
        }
        return ret;
    }


    /** 
     * Add an entry into FileList, without checking it's really a file or not
     *
     * @param filename the string to add into FileList
     * @return 0 if it was already in FileList. 1 if it is added correctly.
     */
    public int addFilenameList(String filename) {
	int ret=0;
	if (!filenameList.contains(filename)) {
	    filenameList.add(filename);
	    ret++;
	}
	return ret;
    }

    /**
     * Mark a filename in FileList
     *
     * @param filename the filename to be marked
     * @return false if the filename is not in FileList, true with success
     */
    public boolean setFileMark(String filename) {
	if (!filenameList.contains(filename)) {
	    return false;
	}
	if (fileMark == null) {
	    fileMark = new Hashtable();
	}
	fileMark.put(filename,new Boolean(true));
	return true;
    }

    /**
     * Unmark a filename in FileList
     *
     * @param filename the filename to be unmarked
     * @return false if the filename is not in FileList, true with success
     */
    public void clearFileMark(String filename) {
	if (fileMark != null) {
	    fileMark.remove(filename);
	}
    }

    /**
     * Unmark all files in FileList
     *
     */
    public void clearAllFileMark() {
	fileMark = null;
    }

    /**
     * check if a file is marked
     *
     * @param filename the filename needed to be checked
     * @return true - marked, false - not marked
     */
    public boolean isFileMarked(String filename) {
	if (fileMark == null) {
	    return false;
	}
	if (fileMark.containsKey(filename)) {
	  return true;
        }
        return false;
    }

    /**
     * return the String array which contains the FileList.
     * the order is the added order.
     *
     * @return the string array contains all the filenames
     */
    public String[] getFiles() {
	String[] ret = null;
	Iterator i;
	int n,j;
	n = filenameList.size();
 	if (n>0) {
	    ret = new String[n];
	    for (i=filenameList.iterator(),j=0; i.hasNext() && j<n; j++) {
	      String filename;
	      filename = (String)(i.next());
              ret[j] = filename;
            }
        }
	return ret;
    }

    /**
     * return the String array only if the file is marked.
     *
     * @return the string array contains the marked filenames
     */
    public String[] getMarkedFiles() {
	Vector data = new Vector();
	String[] ret = null;
	Iterator i;
	int n,j;
	for (i=filenameList.iterator(); i.hasNext(); ) {
	    String filename;
	    filename = (String)i.next();
	    if (isFileMarked(filename)) {
		data.add(filename);
	    }
	}
	n = data.size();
	if (n>0) {
	    ret = new String[n];
	    for (j=0; j<n ; j++) {
		ret[j] = (String)data.elementAt(j);
	    }
	}
	return ret;
    }

    /**
     * return the String array only if the file is not marked.
     *
     * @return the string array contains the not marked filenames
     */
    public String[] getUnmarkedFiles() {
	Vector data = new Vector();
	String[] ret = null;
	Iterator i;
	int n,j;
	for (i=filenameList.iterator(); i.hasNext(); ) {
	    String filename;
	    filename = (String)i.next();
	    if (!isFileMarked(filename)) {
		data.add(filename);
	    }
	}
	n = data.size();
	if (n>0) {
	    ret = new String[n];
	    for (j=0; j<n ; j++) {
		ret[j] = (String)data.elementAt(j);
	    }
	}
	return ret;
    }

    /**
     * add a file into FileList
     *
     * @return the number of files really added into
     */
    public int addFile (String filename) {
	File fl=null;
	File[] childs=null;
	int i,ret=0;
        String dirname=null;

	try {
	    fl = new File(filename);
	} catch (Exception e) {
	    mylogger.info("open file error");
	    return ret;
	}

	try {
	    if (fl.isFile()) {
		ret += addFilenameList(filename);
	    } else if (fl.isDirectory()) {
		dirname = FileList.addFileSeparator(filename);
		ret += addFilenameList(dirname);
		childs = fl.listFiles();
		for (i=0 ; i<childs.length; i++) {
		    addFile(dirname+childs[i].getName());
		}
	    } else {
		mylogger.severe("file "+filename+" type is unknown, maybe it's not exist?");
	    }
	} catch (SecurityException e) {
	    mylogger.severe("operation error "+e.toString());
	}
	return ret;
    }

    /**
     * add some files into FileList
     *
     * @return the number of files really added into
     */
    public int addFile(String[] filenames) {
	int i,ret=0;
	for (i=0; i<filenames.length; i++) {
	    ret += addFile(filenames[i]);
	}
	return ret;
    }


}
