/*******************************************************************************
* Copyright (c)                                                                *
*           2005   Tristan Allwood,                                            *
*           2005   Daniel Burke,                                               *
*           2005   Marc Hull,                                                  *
*           2005   Ekaterina Itskova,                                          *
*           2005   Steve Zymler                                                *
*                                                                              *
* Permission is hereby granted, free of charge, to any person obtaining a      *
* copy of this software and associated documentation files (the                *
* "Software"), to deal in the Software without restriction, including          *
* without limitation the rights to use, copy, modify, merge, publish,          *
* distribute, sublicense, and/or sell copies of the Software, and to           *
* permit persons to whom the Software is furnished to do so, subject to        *
* the following conditions:                                                    *
*                                                                              *
* The above copyright notice and this permission notice shall be included      *
* in all copies or substantial portions of the Software.                       *
*                                                                              *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS      *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF                   *
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.       *
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY         *
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,         *
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE            *
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                       *
*******************************************************************************/
/*
 * Created on 21-Oct-2004
 *
 */
package uk.ac.ic.doc.kevlar.core.programs.fileUtils;

import java.io.File;
import java.util.Arrays;
import java.util.Map;

import uk.ac.ic.doc.kevlar.api.programs.arguments.IArgumentInstance;
import uk.ac.ic.doc.kevlar.api.programs.arguments.ITextArgumentValue;
import uk.ac.ic.doc.kevlar.core.types.textType.FilenameTypeImpl;
import uk.ac.ic.doc.kevlar.core.types.textType.IFilenameType;
import uk.ac.ic.doc.kevlar.publicInterfaces.AbstractProgram;
import uk.ac.ic.doc.kevlar.publicInterfaces.ICloseEventListener;
import uk.ac.ic.doc.kevlar.publicInterfaces.IInputPipe;
import uk.ac.ic.doc.kevlar.publicInterfaces.IOutputPipe;
import uk.ac.ic.doc.kevlar.publicInterfaces.IPipeEnd;

/**
 * @author Tristan, Daniel Burke
 * 
 */
public class ListFiles extends AbstractProgram {

    private static final boolean DEBUG = false;

    public void run(IArgumentInstance args, Map<String, IInputPipe> inputs,
            Map<String, IOutputPipe> outputs) {

        Boolean val = args.getBool("Directories-Input");
        IInputPipe indir = null;

        if (val != null && val.booleanValue() ) {
            indir = inputs.get("Directories");
        }

        ITextArgumentValue dir = (ITextArgumentValue) args.getAssigmentsMap()
                .get("Paths");

        if (DEBUG) {
            System.err.println(outputs);
            System.err.println(inputs);
        }

        IOutputPipe outList = outputs.get("Filenames");

        if (outList == null) {
            if (DEBUG) {
                System.err.println("[ListFiles] No output pipe Connected");
            }

            exit(2);
            return;
        }

        ICloseEventListener icel = new ICloseEventListener() {
            public void pipeClosed(IPipeEnd source) {
                System.err.println("LISTFILES - CLOSED");
                exit(0);
            }
        };

        outList.addCloseEventListener(icel);

        if (outList.closed()) {
            if (DEBUG) {
                System.err.println("[ListFiles] Output pipe closed");
            }
            exit(0);
            return;
        }
        /*
         * ok : handle the argument directory first, and then do the pipe
         * directories
         */


        String[] dirs = dir == null ? new String[]{ "." } : dir.getValue().split(
                System.getProperty("line.separator"));

        for (String cDir : dirs) {
            handleDirectory(cDir, outList);
        }

        if (indir == null) {
            exit(0);
            return;
        }

        indir.addCloseEventListener(icel);
        
        if (indir.closed()) {
            exit(0);
            return;
        }

        try {
            
            while (true) {
                IFilenameType inFileName = (IFilenameType) indir.read();
                handleDirectory(inFileName.toString(), outList);
            }

        } catch (InterruptedException ie) {
            exit(0);
            return;
        } catch (IllegalStateException ise) {
            exit(0);
            return;
        }
    }

    private void handleDirectory(String cDir, IOutputPipe iop) {
        File f = new File(cDir);

        if (!f.exists()) {
            if (DEBUG) {
                System.err.println("[ListFiles] " + cDir + " does not exist");
            }
            return;
        }

        if (!f.isDirectory()) {
            if (DEBUG) {
                System.err.println("[ListFiles] " + cDir
                        + " is not a directory.");
            }
            return;
        }

        if (!f.canRead()) {
            if (DEBUG) {
                System.err.println("[ListFiles] " + cDir + " is not readable.");
            }
            return;
        }

        File[] children = f.listFiles();

        if( children == null ) {
            return;
        }
        
        if (DEBUG) {
            System.err.println("[ListFiles] Children of " + cDir + ": "
                    + Arrays.toString(children));
        }

        for (File childFile : children) {
            IFilenameType fti = new FilenameTypeImpl(childFile);

            if (DEBUG) {
                System.err.println("[ListFiles] Writing out "
                        + childFile.getName());
            }
            iop.write(fti);
        }
    }

}
