/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.geronimo.gshell.commands.vfs;

import org.apache.commons.vfs.FileContent;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.FileFilter;
import org.apache.commons.vfs.FileSelectInfo;
import org.apache.commons.vfs.FileFilterSelector;
import org.apache.geronimo.gshell.clp.Argument;
import org.apache.geronimo.gshell.clp.Option;
import org.apache.geronimo.gshell.command.CommandContext;
import org.apache.geronimo.gshell.io.IO;

import java.text.DateFormat;
import java.util.Date;

/**
 * List the contents of a file or directory.
 *
 * @version $Rev$ $Date$
 */
public class ListDirectoryAction
    extends VfsActionSupport
{
    @Argument
    private String path;

    @Option(name="-a")
    private boolean includeHidden = false;

    @Option(name="-r", aliases={"--recursive"})
    private boolean recursive = false;

    public Object execute(final CommandContext context) throws Exception {
        assert context != null;
        IO io = context.getIo();

        FileObject file;
        if (path != null) {
            file = resolveFile(context, path);
        }
        else {
            file = getCurrentDirectory(context);
        }

        if (file.getType() == FileType.FOLDER) {
            listChildren(io, file, recursive, "");
        }
        else {
            io.info("{}", file.getName());

            FileContent content = file.getContent();
            io.verbose("Size: {} bytes", content.getSize());

            DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
            String lastMod = dateFormat.format(new Date(content.getLastModifiedTime()));
            io.verbose("Last modified: {}", lastMod);
        }

        return Result.SUCCESS;
    }

    private void listChildren(final IO io, final FileObject dir, final boolean recursive, final String prefix) throws FileSystemException {
        assert io != null;
        assert dir != null;
        assert prefix != null;

        FileObject[] files;

        if (includeHidden) {
            files = dir.getChildren();
        }
        else {
            FileFilter filter = new FileFilter() {
                public boolean accept(final FileSelectInfo selection) {
                    assert selection != null;

                    try {
                        return !selection.getFile().isHidden();
                    }
                    catch (FileSystemException e) {
                        throw new RuntimeException(e);
                    }
                }
            };

            files = dir.findFiles(new FileFilterSelector(filter));
        }

        for (FileObject file : files) {
            io.out.print(prefix);
            io.out.print(file.getName().getBaseName());

            if (file.getType() == FileType.FOLDER) {
                io.out.println("/");

                if (recursive) {
                    listChildren(io, file, recursive, prefix + "    ");
                }
            }
            else {
                io.out.println();
            }
        }
    }
}
@@ -1410,16 +1410,153 @@
 il.Date;
+%0Aimport java.util.List;%0Aimport java.util.ArrayList;%0Aimport java.util.LinkedList;%0Aimport java.io.PrintWriter;%0A%0Aimport jline.ConsoleReader;
 %0A%0A/**%0A *
@@ -1734,16 +1734,59 @@
  path;%0A%0A
+    //%0A    // TODO: Add -l support%0A    //%0A%0A
     @Opt
@@ -2344,23 +2344,8 @@
 file
-, recursive, %22%22
 );%0A 
@@ -2892,73 +2892,17 @@
  dir
-, final boolean recursive, final String prefix) throws FileSystem
+) throws 
 Exce
@@ -2967,39 +2967,8 @@
 ull;
-%0A        assert prefix != null;
 %0A%0A  
@@ -3622,82 +3622,417 @@
     
-for (FileObject file : files) %7B%0A            io.out.print(prefix
+//%0A        // FIXME: Need to have the framework provide a reader, which is initialized correctly... or make this accessible via IO?%0A        //%0A%0A        ConsoleReader reader = new ConsoleReader(%0A                io.inputStream,%0A                new PrintWriter(io.outputStream, true),%0A                null, // bindings%0A                io.getTerminal());%0A        %0A        reader.setUsePagination(false
 );%0A
+%0A
         
     
@@ -4027,32 +4027,198 @@
         
-    io.out.print
+List%3CString%3E names = new ArrayList%3CString%3E(files.length);%0A        List%3CFileObject%3E dirs = new LinkedList%3CFileObject%3E();%0A%0A        for (FileObject file : files) %7B%0A            names.add
 (file.ge
@@ -4311,31 +4311,57 @@
         
-io.out.println(
+names.add(file.getName().getBaseName() + 
 %22/%22);%0A%0A 
@@ -4416,142 +4416,358 @@
     
-listChildren(io, file, recursive, prefix + %22    %22);%0A                %7D%0A            %7D%0A            else %7B%0A                io.out.println(
+dirs.add(file);%0A                %7D%0A            %7D%0A        %7D%0A%0A        reader.printColumns(names);%0A        %0A        if (!dirs.isEmpty()) %7B%0A            for (FileObject subdir : dirs) %7B%0A                io.out.println();%0A                io.out.print(subdir.getName().getBaseName());%0A                io.out.print(%22:%22);%0A                listChildren(io, subdir
 );%0A 

Set the default ls style to that one might expect, column view.