// Path: core/src/main/java/it/nerdammer/spash/shell/api/fs/SpashFileSystem.java
// public final class SpashFileSystem {
// 
//     private static final FileSystemFacade FACADE_INSTANCE = new FileSystemFacadeImpl(SpashConfig.getInstance().hdfsHost(), SpashConfig.getInstance().hdfsPort());
// 
//     private SpashFileSystem() {
//     }
// 
//     public static FileSystemFacade get() {
//         return FACADE_INSTANCE;
//     }
// 
// }
// 
// Path: core/src/main/java/it/nerdammer/spash/shell/command/CommandFactory.java
// public class CommandFactory {
// 
//     private static final CommandFactory INSTANCE = new CommandFactory();
// 
//     private Map<String, Class<? extends Command>> commands;
// 
//     private CommandFactory() {
//         this.commands = new TreeMap<>();
//         commands.put(">", WriteCommand.class);
//         commands.put("cat", CatCommand.class);
//         commands.put("cd", CdCommand.class);
//         commands.put("echo", EchoCommand.class);
//         commands.put("exit", ExitCommand.class);
//         commands.put("grep", GrepCommand.class);
//         commands.put("head", HeadCommand.class);
//         commands.put("ls", LsCommand.class);
//         commands.put("mkdir", MkDirCommand.class);
//         commands.put("pwd", PwdCommand.class);
//         commands.put("rm", RmCommand.class);
//         commands.put("rmdir", RmDirCommand.class);
//         commands.put("test", NoOpCommand.class);
//     }
// 
//     public static CommandFactory getInstance() {
//         return INSTANCE;
//     }
// 
//     public Set<String> getAvailableCommands() {
//         return this.commands.keySet();
//     }
// 
//     public Command getCommand(String commandStr) {
// 
//         if(commandStr.trim().equals("")) {
//             return new NoOpCommand(commandStr);
//         } else {
//             String[] args = commandStr.split(" "); // TODO parse
// 
//             if(commands.containsKey(args[0])) {
//                 try {
//                     Class<? extends Command> commandClass = commands.get(args[0]);
//                     Command c = commandClass.getConstructor(String.class).newInstance(commandStr);
//                     return c;
//                 } catch(InvocationTargetException e) {
//                     Throwable t = e.getCause();
//                     if(t instanceof RuntimeException) {
//                         throw (RuntimeException)t;
//                     } else if(t instanceof Error) {
//                         throw (Error)t;
//                     } else {
//                         throw new IllegalStateException(t);
//                     }
//                 } catch(RuntimeException e) {
//                     throw e;
//                 } catch(Exception e) {
//                     throw new IllegalStateException("Unable to create command '" + commandStr + "'", e);
//                 }
//             }
//         }
// 
//         return new UnknownCommand(commandStr);
//     }
// 
// }


import ch.lambdaj.Lambda;
import ch.lambdaj.function.convert.DefaultStringConverter;
import ch.lambdaj.function.convert.PropertyExtractor;
import it.nerdammer.spash.shell.api.fs.SpashFileSystem;
import it.nerdammer.spash.shell.command.CommandFactory;
import jline.console.completer.Completer;
import jline.internal.Preconditions;
import org.hamcrest.text.StringStartsWith;
import java.nio.file.Path;
import java.util.List;
import java.util.Set;
package it.nerdammer.spash.shell;



/**
 * @author Nicola Ferraro
 */
public class SpashCommandCompleter implements Completer {

    private Set<String> commands;

    private SpashSession session;

    public SpashCommandCompleter(SpashSession session) {
        this.commands = CommandFactory.getInstance().getAvailableCommands();
        this.session = session;
    }

    @Override
    public int complete(String buffer, int cursor, List<CharSequence> candidates) {
        Preconditions.checkNotNull(candidates);

        String text = contextualBuffer(buffer, cursor);

        List<String> commands = Lambda.filter(StringStartsWith.startsWith(text), this.commands);
        if(commands.size()>0) {
            candidates.addAll(commands);

            if(candidates.size()==1) {
                candidates.set(0, candidates.get(0) + " ");
            }

            return candidates.isEmpty() ? -1 : 0;

        } else if(text.contains(" ")) {
            int insertion = text.lastIndexOf(" ") + 1;
            String tailBuffer = text.substring(insertion);

// Path: core/src/main/java/it/nerdammer/spash/shell/api/fs/SpashFileSystem.java
// public final class SpashFileSystem {
// 
//     private static final FileSystemFacade FACADE_INSTANCE = new FileSystemFacadeImpl(SpashConfig.getInstance().hdfsHost(), SpashConfig.getInstance().hdfsPort());
// 
//     private SpashFileSystem() {
//     }
// 
//     public static FileSystemFacade get() {
//         return FACADE_INSTANCE;
//     }
// 
// }
// 
// Path: core/src/main/java/it/nerdammer/spash/shell/command/CommandFactory.java
// public class CommandFactory {
// 
//     private static final CommandFactory INSTANCE = new CommandFactory();
// 
//     private Map<String, Class<? extends Command>> commands;
// 
//     private CommandFactory() {
//         this.commands = new TreeMap<>();
//         commands.put(">", WriteCommand.class);
//         commands.put("cat", CatCommand.class);
//         commands.put("cd", CdCommand.class);
//         commands.put("echo", EchoCommand.class);
//         commands.put("exit", ExitCommand.class);
//         commands.put("grep", GrepCommand.class);
//         commands.put("head", HeadCommand.class);
//         commands.put("ls", LsCommand.class);
//         commands.put("mkdir", MkDirCommand.class);
//         commands.put("pwd", PwdCommand.class);
//         commands.put("rm", RmCommand.class);
//         commands.put("rmdir", RmDirCommand.class);
//         commands.put("test", NoOpCommand.class);
//     }
// 
//     public static CommandFactory getInstance() {
//         return INSTANCE;
//     }
// 
//     public Set<String> getAvailableCommands() {
//         return this.commands.keySet();
//     }
// 
//     public Command getCommand(String commandStr) {
// 
//         if(commandStr.trim().equals("")) {
//             return new NoOpCommand(commandStr);
//         } else {
//             String[] args = commandStr.split(" "); // TODO parse
// 
//             if(commands.containsKey(args[0])) {
//                 try {
//                     Class<? extends Command> commandClass = commands.get(args[0]);
//                     Command c = commandClass.getConstructor(String.class).newInstance(commandStr);
//                     return c;
//                 } catch(InvocationTargetException e) {
//                     Throwable t = e.getCause();
//                     if(t instanceof RuntimeException) {
//                         throw (RuntimeException)t;
//                     } else if(t instanceof Error) {
//                         throw (Error)t;
//                     } else {
//                         throw new IllegalStateException(t);
//                     }
//                 } catch(RuntimeException e) {
//                     throw e;
//                 } catch(Exception e) {
//                     throw new IllegalStateException("Unable to create command '" + commandStr + "'", e);
//                 }
//             }
//         }
// 
//         return new UnknownCommand(commandStr);
//     }
// 
// }


// Path: core/src/main/java/it/nerdammer/spash/shell/SpashCommandCompleter.java
import ch.lambdaj.Lambda;
import ch.lambdaj.function.convert.DefaultStringConverter;
import ch.lambdaj.function.convert.PropertyExtractor;
import it.nerdammer.spash.shell.api.fs.SpashFileSystem;
import it.nerdammer.spash.shell.command.CommandFactory;
import jline.console.completer.Completer;
import jline.internal.Preconditions;
import org.hamcrest.text.StringStartsWith;
import java.nio.file.Path;
import java.util.List;
import java.util.Set;

package it.nerdammer.spash.shell;



/**
 * @author Nicola Ferraro
 */
public class SpashCommandCompleter implements Completer {

    private Set<String> commands;

    private SpashSession session;

    public SpashCommandCompleter(SpashSession session) {
        this.commands = CommandFactory.getInstance().getAvailableCommands();
        this.session = session;
    }

    @Override
    public int complete(String buffer, int cursor, List<CharSequence> candidates) {
        Preconditions.checkNotNull(candidates);

        String text = contextualBuffer(buffer, cursor);

        List<String> commands = Lambda.filter(StringStartsWith.startsWith(text), this.commands);
        if(commands.size()>0) {
            candidates.addAll(commands);

            if(candidates.size()==1) {
                candidates.set(0, candidates.get(0) + " ");
            }

            return candidates.isEmpty() ? -1 : 0;

        } else if(text.contains(" ")) {
            int insertion = text.lastIndexOf(" ") + 1;
            String tailBuffer = text.substring(insertion);

            List<String> files = Lambda.convert(Lambda.convert(SpashFileSystem.get().ls(this.session.getWorkingDir()).collect(), new PropertyExtractor<Object, Path>("fileName")), new DefaultStringConverter());