/*
 * 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.karaf.shell.impl.console;

import java.io.InputStream;
import java.io.PrintStream;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import org.apache.felix.gogo.jline.Builtin;
import org.apache.felix.gogo.jline.Posix;
import org.apache.felix.gogo.jline.Procedural;
import org.apache.felix.gogo.runtime.CommandProcessorImpl;
import org.apache.felix.gogo.runtime.CommandSessionImpl;
import org.apache.felix.gogo.runtime.Reflective;
import org.apache.felix.service.command.CommandSession;
import org.apache.felix.service.command.Function;
import org.apache.felix.service.threadio.ThreadIO;
import org.apache.karaf.shell.api.console.Command;
import org.apache.karaf.shell.api.console.Completer;
import org.apache.karaf.shell.api.console.Parser;
import org.apache.karaf.shell.api.console.Registry;
import org.apache.karaf.shell.api.console.Session;
import org.apache.karaf.shell.api.console.SessionFactory;
import org.apache.karaf.shell.api.console.Terminal;
import org.apache.karaf.shell.impl.console.commands.ExitCommand;
import org.apache.karaf.shell.impl.console.commands.SubShellCommand;
import org.apache.karaf.shell.impl.console.commands.help.HelpCommand;

public class SessionFactoryImpl extends RegistryImpl implements SessionFactory, Registry {

    final CommandProcessorImpl commandProcessor;
    final ThreadIO threadIO;
    final Map<String, SubShellCommand> subshells = new HashMap<>();
    boolean closed;

    public SessionFactoryImpl(ThreadIO threadIO) {
        super(null);
        this.threadIO = threadIO;
        commandProcessor = new CommandProcessorImpl(threadIO) {
            @Override
            public Object invoke(CommandSessionImpl session, Object target, String name, List<Object> args) throws Exception {
                return SessionFactoryImpl.this.invoke(session, target, name, args);
            }

            @Override
            public Path redirect(CommandSessionImpl session, Path path, int mode) {
                return SessionFactoryImpl.this.redirect(session, path, mode);
            }
        };
        register(new ExitCommand());
        new HelpCommand(this);
        register(new ShellCommand("addCommand", "Add a command", commandProcessor, "addCommand"));
        register(new ShellCommand("removeCommand", "Remove a command", commandProcessor, "removeCommand"));
        register(new ShellCommand("eval", "Evaluate", commandProcessor, "eval"));

        Builtin builtin = new Builtin();
        for (String name : new String[]{"format", "getopt", "new", "set", "tac", "type", "jobs", "fg", "bg", "keymap", "setopt", "unsetopt", "complete", "history", "widget", "__files", "__directories", "__usage_completion"}) {
            register(new ShellCommand(name, null, builtin, name));
        }

        Procedural procedural = new Procedural();
        for (String name : new String[]{"each", "if", "not", "throw", "try", "until", "while", "break", "continue"}) {
            register(new ShellCommand(name, null, procedural, name));
        }

        Posix posix = new Posix(commandProcessor);
        for (String name : new String[]{"cat", "echo", "grep", "sort", "sleep", "cd", "pwd", "ls", "less", "nano", "head", "tail", "clear", "wc", "date", "tmux", "ttop"}) {
            register(new ShellCommand(name, null, posix, name));
        }
    }

    protected Object invoke(CommandSessionImpl session, Object target, String name, List<Object> args) throws Exception {
        return Reflective.invoke(session, target, name, args);
    }

    protected Path redirect(CommandSessionImpl session, Path path, int mode) {
        return session.currentDir().resolve(path);
    }

    public CommandProcessorImpl getCommandProcessor() {
        return commandProcessor;
    }

    @Override
    public Registry getRegistry() {
        return this;
    }

    @Override
    public void register(Object service) {
        synchronized (services) {
            if (service instanceof Command) {
                Command command = (Command) service;
                String scope = command.getScope();
                String name = command.getName();
                if (!Session.SCOPE_GLOBAL.equals(scope)) {
                    if (!subshells.containsKey(scope)) {
                        SubShellCommand subShell = new SubShellCommand(scope);
                        subshells.put(scope, subShell);
                        register(subShell);
                    }
                    subshells.get(scope).increment();
                }
                commandProcessor.addCommand(scope, wrap(command), name);
            }
            super.register(service);
        }
    }

    protected Function wrap(Command command) {
        return new CommandWrapper(command);
    }

    @Override
    public void unregister(Object service) {
        synchronized (services) {
            super.unregister(service);
            if (service instanceof Command) {
                Command command = (Command) service;
                String scope = command.getScope();
                String name = command.getName();
                commandProcessor.removeCommand(scope, name);
                if (!Session.SCOPE_GLOBAL.equals(scope)) {
                    if (subshells.get(scope).decrement() == 0) {
                        SubShellCommand subShell = subshells.remove(scope);
                        unregister(subShell);
                    }
                }
            }
        }
    }

    @Override
    public Session create(InputStream in, PrintStream out, PrintStream err, Terminal term, String encoding, Runnable closeCallback) {
        synchronized (commandProcessor) {
            if (closed) {
                throw new IllegalStateException("SessionFactory has been closed");
            }
            final Session session = new ConsoleSessionImpl(this, commandProcessor, threadIO, in, out, err, term, encoding, closeCallback);
            return session;
        }
    }

    @Override
    public Session create(InputStream in, PrintStream out, PrintStream err) {
        return create(in, out, err, null);
    }

    @Override
    public Session create(InputStream in, PrintStream out, PrintStream err, Session parent) {
        synchronized (commandProcessor) {
            if (closed) {
                throw new IllegalStateException("SessionFactory has been closed");
            }
            final Session session = new HeadlessSessionImpl(this, commandProcessor, in, out, err, parent);
            return session;
        }
    }

    public void stop() {
        synchronized (commandProcessor) {
            closed = true;
            commandProcessor.stop();
        }
    }

    private static class ShellCommand implements Command {
        private final String name;
        private final String desc;
        private final Executable consumer;

        interface Executable {
            Object execute(CommandSession session, List<Object> args) throws Exception;
        }

        interface ExecutableStr {
            void execute(CommandSession session, String[] args) throws Exception;
        }

        public ShellCommand(String name, String desc, Executable consumer) {
            this.name = name;
            this.desc = desc;
            this.consumer = consumer;
        }

        public ShellCommand(String name, String desc, ExecutableStr consumer) {
            this(name, desc, wrap(consumer));
        }

        public ShellCommand(String name, String desc, Object target, String method) {
            this(name, desc, wrap(target, method));
        }

        private static Executable wrap(Object target, String name) {
            return (session, args) -> Reflective.invoke(session, target, name, args);
        }

        private static Executable wrap(ExecutableStr command) {
            return (session, args) -> {
                command.execute(session, asStringArray(args));
                return null;
            };
        }

        private static String[] asStringArray(List<Object> args) {
            String[] argv = new String[args.size()];
            for (int i = 0; i < argv.length; i++) {
                argv[i] = Objects.toString(args.get(i));
            }
            return argv;
        }

        @Override
        public String getScope() {
            return "shell";
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public String getDescription() {
            return desc;
        }

        @Override
        public Completer getCompleter(boolean scoped) {
            return null;
        }

        @Override
        public Parser getParser() {
            return null;
        }

        @Override
        public Object execute(Session session, List<Object> arguments) throws Exception {
            CommandSession cmdSession = (CommandSession) session.get(".commandSession");
            return consumer.execute(cmdSession, arguments);
        }
    }

}
