// 
// Decompiled by Procyon v0.6.0
// 

package org.jline.builtins;

import java.util.Arrays;
import java.util.Objects;
import java.util.HashMap;
import java.util.function.Function;
import org.jline.terminal.Terminal;
import java.nio.file.Path;
import java.io.PrintStream;
import java.io.InputStream;
import java.util.Map;

public class PosixCommandsRegistry
{
    private final PosixCommands.Context context;
    private final Map<String, CommandFunction> commands;
    
    public PosixCommandsRegistry(final InputStream in, final PrintStream out, final PrintStream err, final Path currentDir, final Terminal terminal, final Function<String, Object> variables) {
        this.context = new PosixCommands.Context(in, out, err, currentDir, terminal, variables);
        populateDefaultCommands(this.commands = new HashMap<String, CommandFunction>());
    }
    
    public PosixCommandsRegistry(final PosixCommands.Context context) {
        this.context = context;
        populateDefaultCommands(this.commands = new HashMap<String, CommandFunction>());
    }
    
    private static void populateDefaultCommands(final Map<String, CommandFunction> commands) {
        commands.put("cat", PosixCommands::cat);
        commands.put("echo", PosixCommands::echo);
        commands.put("grep", PosixCommands::grep);
        commands.put("ls", PosixCommands::ls);
        commands.put("pwd", PosixCommands::pwd);
        commands.put("head", PosixCommands::head);
        commands.put("tail", PosixCommands::tail);
        commands.put("wc", PosixCommands::wc);
        commands.put("date", PosixCommands::date);
        commands.put("sleep", PosixCommands::sleep);
        commands.put("sort", PosixCommands::sort);
        commands.put("clear", PosixCommands::clear);
    }
    
    public void registerDefaultCommands() {
        populateDefaultCommands(this.commands);
    }
    
    public void register(final String name, final CommandFunction command) {
        this.commands.put(name, command);
    }
    
    public void unregister(final String name) {
        this.commands.remove(name);
    }
    
    public boolean hasCommand(final String name) {
        return this.commands.containsKey(name);
    }
    
    public String[] getCommandNames() {
        return this.commands.keySet().toArray(new String[0]);
    }
    
    public void execute(final String name, final String[] argv) throws Exception {
        final CommandFunction command = this.commands.get(name);
        if (command == null) {
            throw new IllegalArgumentException("Unknown command: " + name);
        }
        command.execute(this.context, argv);
    }
    
    public void execute(final String commandLine) throws Exception {
        if (commandLine == null || commandLine.trim().isEmpty()) {
            return;
        }
        final String[] parts = commandLine.trim().split("\\s+");
        this.execute(parts[0], parts);
    }
    
    public PosixCommands.Context getContext() {
        return this.context;
    }
    
    public PosixCommandsRegistry withCurrentDirectory(final Path newCurrentDir) {
        final InputStream in = this.context.in();
        final PrintStream out = this.context.out();
        final PrintStream err = this.context.err();
        final Terminal terminal = this.context.terminal();
        final PosixCommands.Context context = this.context;
        Objects.requireNonNull(context);
        final PosixCommands.Context newContext = new PosixCommands.Context(in, out, err, newCurrentDir, terminal, context::get);
        return new PosixCommandsRegistry(newContext);
    }
    
    public void printHelp() {
        this.context.out().println("Available POSIX commands:");
        final String[] names = this.getCommandNames();
        Arrays.sort(names);
        for (final String name : names) {
            this.context.out().println("  " + name);
        }
        this.context.out().println();
        this.context.out().println("Use '<command> --help' for detailed help on each command.");
    }
    
    public void printHelp(final String commandName) throws Exception {
        if (!this.hasCommand(commandName)) {
            this.context.err().println("Unknown command: " + commandName);
            return;
        }
        this.execute(commandName, new String[] { commandName, "--help" });
    }
    
    @FunctionalInterface
    public interface CommandFunction
    {
        void execute(final PosixCommands.Context p0, final String[] p1) throws Exception;
    }
}
