/*
 * 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.felix.gogo.jline;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.StringWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.felix.service.command.Job;
import org.apache.felix.service.command.Process;
import org.apache.felix.gogo.runtime.CommandSessionImpl;
import org.apache.felix.service.command.CommandSession;
import org.apache.felix.service.command.Converter;
import org.apache.felix.service.command.Function;
import org.jline.builtins.Commands;
import org.jline.builtins.Completers.DirectoriesCompleter;
import org.jline.builtins.Completers.FilesCompleter;
import org.jline.builtins.Options;
import org.jline.reader.Candidate;
import org.jline.reader.LineReader;
import org.jline.reader.ParsedLine;
import org.jline.reader.Widget;
import org.jline.terminal.Terminal;

import static org.apache.felix.gogo.jline.Shell.getCommands;

/**
 * gosh built-in commands.
 */
public class Builtin {

    static final String[] functions = {
            "format", "getopt", "new", "set", "tac", "type",
            "jobs", "fg", "bg",
            "keymap", "setopt", "unsetopt", "complete", "history", "widget",
            "__files", "__directories", "__usage_completion"
    };

    private static final String[] packages = {"java.lang", "java.io", "java.net", "java.util"};

    private final static Set<String> KEYWORDS = new HashSet<>(
            Arrays.asList("abstract", "continue", "for", "new", "switch",
                    "assert", "default", "goto", "package", "synchronized", "boolean", "do",
                    "if", "private", "this", "break", "double", "implements", "protected",
                    "throw", "byte", "else", "import", "public", "throws", "case", "enum",
                    "instanceof", "return", "transient", "catch", "extends", "int", "short",
                    "try", "char", "final", "interface", "static", "void", "class",
                    "finally", "long", "strictfp", "volatile", "const", "float", "native",
                    "super", "while"));

    public CharSequence format(CommandSession session) {
        return format(session, session.get("_"));    // last result
    }

    public CharSequence format(CommandSession session, Object arg) {
        Process process = Process.Utils.current();
        CharSequence result = session.format(arg, Converter.INSPECT);
        process.out().println(result);
        return result;
    }

    /**
     * script access to Options.
     */
    public Options getopt(List<Object> spec, Object[] args) {
        String[] optSpec = new String[spec.size()];
        for (int i = 0; i < optSpec.length; ++i) {
            optSpec[i] = spec.get(i).toString();
        }
        return Options.compile(optSpec).parse(args);
    }

    // FIXME: the "new" command should be provided by runtime,
    // so it can leverage same argument coercion mechanism, used to invoke methods.
    public Object _new(CommandSession session, Object name, Object[] argv) throws Exception {
        Class<?> clazz;

        if (name instanceof Class<?>) {
            clazz = (Class<?>) name;
        } else {
            clazz = loadClass(session, name.toString());
        }

        for (Constructor<?> c : clazz.getConstructors()) {
            Class<?>[] types = c.getParameterTypes();
            if (types.length != argv.length) {
                continue;
            }

            boolean match = true;

            Object[] transformed = argv.clone();
            for (int i = 0; i < transformed.length; ++i) {
                try {
                    transformed[i] = session.convert(types[i], transformed[i]);
                } catch (IllegalArgumentException e) {
                    match = false;
                    break;
                }
            }

            if (!match) {
                continue;
            }

            try {
                return c.newInstance(transformed);
            } catch (InvocationTargetException ite) {
                Throwable cause = ite.getCause();
                if (cause instanceof Exception) {
                    throw (Exception) cause;
                }
                throw ite;
            }
        }

        throw new IllegalArgumentException("can't coerce " + Arrays.asList(argv)
                + " to any of " + Arrays.asList(clazz.getConstructors()));
    }

    private Class<?> loadClass(CommandSession session, String name) throws ClassNotFoundException {
        if (!name.contains(".")) {
            for (String p : packages) {
                String pkg = p + "." + name;
                try {
                    return Class.forName(pkg, true, session.classLoader());
                } catch (ClassNotFoundException e) {
                }
            }
        }
        return Class.forName(name, true, session.classLoader());
    }

    public void set(CommandSession session, String[] argv) {
        final String[] usage = {
                "set - show session variables",
                "Usage: set [OPTIONS] [PREFIX]",
                "  -? --help                show help",
                "  -a --all                 show all variables, including those starting with .",
                "  -x                       set xtrace option",
                "  +x                       unset xtrace option",
                "If PREFIX given, then only show variable(s) starting with PREFIX"};

        Process process = Process.Utils.current();
        Options opt = Options.compile(usage).parse(argv);

        if (opt.isSet("help")) {
            opt.usage(process.err());
            return;
        }

        List<String> args = opt.args();
        String prefix = (args.isEmpty() ? "" : args.get(0));

        if (opt.isSet("x")) {
            session.put("echo", true);
        } else if ("+x".equals(prefix)) {
            session.put("echo", null);
        } else {
            boolean all = opt.isSet("all");
            for (String key : new TreeSet<>(Shell.getVariables(session))) {
                if (!key.startsWith(prefix))
                    continue;

                if (key.startsWith(".") && !(all || prefix.length() > 0))
                    continue;

                Object target = session.get(key);
                String type = null;
                String value = null;

                if (target != null) {
                    Class<?> clazz = target.getClass();
                    type = clazz.getSimpleName();
                    value = target.toString();
                }

                String trunc = value == null || value.length() < 55 ? "" : "...";
                process.out().println(String.format("%-15.15s %-15s %.45s%s", type, key,
                        value, trunc));
            }
        }
    }

    /*
     * the following methods depend on the internals of the runtime implementation.
     * ideally, they should be available via some API.
     */

    public Object tac(CommandSession session, String[] argv) throws IOException {
        final String[] usage = {
                "tac - capture stdin as String or List and optionally write to file.",
                "Usage: tac [-al] [FILE]",
                "  -a --append              append to FILE",
                "  -l --list                return List<String>",
                "  -? --help                show help"};

        Process process = Process.Utils.current();
        Options opt = Options.compile(usage).parse(argv);

        if (opt.isSet("help")) {
            opt.usage(process.err());
            return null;
        }

        List<String> args = opt.args();
        BufferedWriter fw = null;

        if (args.size() == 1) {
            Path path = session.currentDir().resolve(args.get(0));
            Set<OpenOption> options = new HashSet<>();
            options.add(StandardOpenOption.WRITE);
            options.add(StandardOpenOption.CREATE);
            if (opt.isSet("append")) {
                options.add(StandardOpenOption.APPEND);
            } else {
                options.add(StandardOpenOption.TRUNCATE_EXISTING);
            }
            fw = Files.newBufferedWriter(path, StandardCharsets.UTF_8, options.toArray(new OpenOption[options.size()]));
        }

        StringWriter sw = new StringWriter();
        BufferedReader rdr = new BufferedReader(new InputStreamReader(process.in()));

        ArrayList<String> list = null;

        if (opt.isSet("list")) {
            list = new ArrayList<>();
        }

        boolean first = true;
        String s;

        while ((s = rdr.readLine()) != null) {
            if (list != null) {
                list.add(s);
            } else {
                if (!first) {
                    sw.write(' ');
                }
                first = false;
                sw.write(s);
            }

            if (fw != null) {
                fw.write(s);
                fw.newLine();
            }
        }

        if (fw != null) {
            fw.close();
        }

        return list != null ? list : sw.toString();
    }

    // FIXME: expose API in runtime so type command doesn't have to duplicate the runtime
    // command search strategy.
    public boolean type(CommandSession session, String[] argv) throws Exception {
        final String[] usage = {"type - show command type",
                "Usage: type [OPTIONS] [name[:]]",
                "  -a --all                 show all matches",
                "  -? --help                show help",
                "  -q --quiet               don't print anything, just return status",
                "  -s --scope=NAME          list all commands in named scope",
                "  -t --types               show full java type names"};

        Process process = Process.Utils.current();
        Options opt = Options.compile(usage).parse(argv);
        List<String> args = opt.args();

        if (opt.isSet("help")) {
            opt.usage(process.err());
            return true;
        }

        boolean all = opt.isSet("all");

        String optScope = null;
        if (opt.isSet("scope")) {
            optScope = opt.get("scope");
        }

        if (args.size() == 1) {
            String arg = args.get(0);
            if (arg.endsWith(":")) {
                optScope = args.remove(0);
            }
        }

        if (optScope != null || (args.isEmpty() && all)) {
            Set<String> snames = new TreeSet<>();

            for (String sname : (getCommands(session))) {
                if ((optScope == null) || sname.startsWith(optScope)) {
                    snames.add(sname);
                }
            }

            for (String sname : snames) {
                process.out().println(sname);
            }

            return true;
        }

        if (args.size() == 0) {
            Map<String, Integer> scopes = new TreeMap<>();

            for (String sname : getCommands(session)) {
                int colon = sname.indexOf(':');
                String scope = sname.substring(0, colon);
                Integer count = scopes.get(scope);
                if (count == null) {
                    count = 0;
                }
                scopes.put(scope, ++count);
            }

            for (Entry<String, Integer> entry : scopes.entrySet()) {
                process.out().println(entry.getKey() + ":" + entry.getValue());
            }

            return true;
        }

        final String name = args.get(0).toLowerCase();

        final int colon = name.indexOf(':');
        final String MAIN = "_main"; // FIXME: must match Reflective.java

        StringBuilder buf = new StringBuilder();
        Set<String> cmds = new LinkedHashSet<>();

        // get all commands
        if ((colon != -1) || (session.get(name) != null)) {
            cmds.add(name);
        } else if (session.get(MAIN) != null) {
            cmds.add(MAIN);
        } else {
            String path = session.get("SCOPE") != null ? session.get("SCOPE").toString()
                    : "*";

            for (String s : path.split(":")) {
                if (s.equals("*")) {
                    for (String sname : getCommands(session)) {
                        if (sname.endsWith(":" + name)) {
                            cmds.add(sname);
                            if (!all) {
                                break;
                            }
                        }
                    }
                } else {
                    String sname = s + ":" + name;
                    if (session.get(sname) != null) {
                        cmds.add(sname);
                        if (!all) {
                            break;
                        }
                    }
                }
            }
        }

        for (String key : cmds) {
            Object target = session.get(key);
            if (target == null) {
                continue;
            }

            CharSequence source = getClosureSource(session, key);

            if (source != null) {
                buf.append(name);
                buf.append(" is function {");
                buf.append(source);
                buf.append("}");
                continue;
            }

            for (Method m : getMethods(session, key)) {
                StringBuilder params = new StringBuilder();

                for (Class<?> type : m.getParameterTypes()) {
                    if (params.length() > 0) {
                        params.append(", ");
                    }
                    params.append(type.getSimpleName());
                }

                String rtype = m.getReturnType().getSimpleName();

                if (buf.length() > 0) {
                    buf.append("\n");
                }

                if (opt.isSet("types")) {
                    String cname = m.getDeclaringClass().getName();
                    buf.append(String.format("%s %s.%s(%s)", rtype, cname, m.getName(),
                            params));
                } else {
                    buf.append(String.format("%s is %s %s(%s)", name, rtype, key, params));
                }
            }
        }

        if (buf.length() > 0) {
            if (!opt.isSet("quiet")) {
                process.out().println(buf);
            }
            return true;
        }

        if (!opt.isSet("quiet")) {
            process.err().println("type: " + name + " not found.");
        }

        return false;
    }

    public void jobs(CommandSession session, String[] argv) {
        final String[] usage = {
                "jobs - list jobs",
                "Usage: jobs [OPTIONS]",
                "  -? --help                show help",
        };
        Process process = Process.Utils.current();
        Options opt = Options.compile(usage).parse(argv);
        if (opt.isSet("help")) {
            opt.usage(process.err());
            return;
        }
        if (!opt.args().isEmpty()) {
            process.err().println("usage: jobs");
            process.error(2);
            return;
        }
        List<Job> jobs = session.jobs();
        Job current = Job.Utils.current();
        for (Job job : jobs) {
            if (job != current) {
                process.out().println("[" + job.id() + "] " + job.status().toString().toLowerCase()
                        + " " + job.command());
            }
        }
    }

    public void fg(CommandSession session, String[] argv) {
        final String[] usage = {
                "fg - put job in foreground",
                "Usage: fg [OPTIONS] [jobid]",
                "  -? --help                show help",
        };
        Process process = Process.Utils.current();
        Options opt = Options.compile(usage).parse(argv);
        if (opt.isSet("help")) {
            opt.usage(process.err());
            return;
        }
        if (opt.args().size() > 1) {
            process.err().println("usage: fg [jobid]");
            process.error(2);
            return;
        }
        List<Job> jobs = new ArrayList<>(session.jobs());
        Collections.reverse(jobs);
        Job current = Job.Utils.current();
        if (argv.length == 0) {
            Job job = jobs.stream().filter(j -> j != current)
                    .findFirst().orElse(null);
            if (job != null) {
                job.foreground();
            } else {
                process.err().println("fg: no current job");
                process.error(1);
            }
        } else {
            Job job = jobs.stream().filter(j -> j != current && argv[0].equals(Integer.toString(j.id())))
                    .findFirst().orElse(null);
            if (job != null) {
                job.foreground();
            } else {
                process.err().println("fg: job not found: " + argv[0]);
                process.error(1);
            }
        }
    }

    public void bg(CommandSession session, String[] argv) {
        final String[] usage = {
                "bg - put job in background",
                "Usage: bg [OPTIONS] [jobid]",
                "  -? --help                show help",
        };
        Process process = Process.Utils.current();
        Options opt = Options.compile(usage).parse(argv);
        if (opt.isSet("help")) {
            opt.usage(process.err());
            return;
        }
        if (opt.args().size() > 1) {
            process.err().println("usage: bg [jobid]");
            process.error(2);
            return;
        }
        List<Job> jobs = new ArrayList<>(session.jobs());
        Collections.reverse(jobs);
        Job current = Job.Utils.current();
        if (argv.length == 0) {
            Job job = jobs.stream().filter(j -> j != current)
                    .findFirst().orElse(null);
            if (job != null) {
                job.background();
            } else {
                process.err().println("bg: no current job");
                process.error(1);
            }
        } else {
            Job job = jobs.stream().filter(j -> j != current && argv[0].equals(Integer.toString(j.id())))
                    .findFirst().orElse(null);
            if (job != null) {
                job.background();
            } else {
                process.err().println("bg: job not found: " + argv[0]);
                process.error(1);
            }
        }
    }

    private boolean isClosure(Object target) {
        return target.getClass().getSimpleName().equals("Closure");
    }

    private boolean isCommand(Object target) {
        return target.getClass().getSimpleName().equals("CommandProxy");
    }

    private CharSequence getClosureSource(CommandSession session, String name)
            throws Exception {
        Object target = session.get(name);

        if (target == null) {
            return null;
        }

        if (!isClosure(target)) {
            return null;
        }

        Field sourceField = target.getClass().getDeclaredField("source");
        sourceField.setAccessible(true);
        return (CharSequence) sourceField.get(target);
    }

    private List<Method> getMethods(CommandSession session, String scmd) throws Exception {
        final int colon = scmd.indexOf(':');
        final String function = colon == -1 ? scmd : scmd.substring(colon + 1);
        final String name = KEYWORDS.contains(function) ? ("_" + function) : function;
        final String get = "get" + function;
        final String is = "is" + function;
        final String set = "set" + function;
        final String MAIN = "_main"; // FIXME: must match Reflective.java

        Object target = session.get(scmd);
        if (target == null) {
            return null;
        }

        if (isClosure(target)) {
            return null;
        }

        if (isCommand(target)) {
            Method method = target.getClass().getMethod("getTarget", (Class[]) null);
            method.setAccessible(true);
            target = method.invoke(target, (Object[]) null);
        }

        ArrayList<Method> list = new ArrayList<>();
        Class<?> tc = (target instanceof Class<?>) ? (Class<?>) target
                : target.getClass();
        Method[] methods = tc.getMethods();

        for (Method m : methods) {
            String mname = m.getName().toLowerCase();

            if (mname.equals(name) || mname.equals(get) || mname.equals(set)
                    || mname.equals(is) || mname.equals(MAIN)) {
                list.add(m);
            }
        }

        return list;
    }

    public void history(CommandSession session, String[] argv) throws Exception {
        Process process = Process.Utils.current();
        Commands.history(Shell.getReader(session), process.out(), process.err(), null, argv);
    }

    public void complete(CommandSession session, String[] argv) throws Exception {
        Process process = Process.Utils.current();
        Commands.complete(Shell.getReader(session), process.out(), process.err(), Shell.getCompletions(session), argv);
    }

    public void widget(final CommandSession session, String[] argv) throws Exception {
        java.util.function.Function<String, Widget> creator = func -> () -> {
            try {
                session.execute(func);
            } catch (Exception e) {
                // TODO: log exception ?
                return false;
            }
            return true;
        };
        Process process = Process.Utils.current();
        Commands.widget(Shell.getReader(session), process.out(), process.err(), creator, argv);
    }

    public void keymap(CommandSession session, String[] argv) throws Exception {
        Process process = Process.Utils.current();
        Commands.keymap(Shell.getReader(session), process.out(), process.err(), argv);
    }

    public void setopt(CommandSession session, String[] argv) throws Exception {
        Process process = Process.Utils.current();
        Commands.setopt(Shell.getReader(session), process.out(), process.err(), argv);
    }

    public void unsetopt(CommandSession session, String[] argv) throws Exception {
        Process process = Process.Utils.current();
        Commands.unsetopt(Shell.getReader(session), process.out(), process.err(), argv);
    }

    public List<Candidate> __files(CommandSession session) {
        ParsedLine line = Shell.getParsedLine(session);
        LineReader reader = Shell.getReader(session);
        List<Candidate> candidates = new ArrayList<>();
        new FilesCompleter(session.currentDir()) {
            @Override
            protected String getDisplay(Terminal terminal, Path p) {
                return getFileDisplay(session, p);
            }
        }.complete(reader, line, candidates);
        return candidates;
    }

    public List<Candidate> __directories(CommandSession session) {
        ParsedLine line = Shell.getParsedLine(session);
        LineReader reader = Shell.getReader(session);
        List<Candidate> candidates = new ArrayList<>();
        new DirectoriesCompleter(session.currentDir()) {
            @Override
            protected String getDisplay(Terminal terminal, Path p) {
                return getFileDisplay(session, p);
            }
        }.complete(reader, line, candidates);
        return candidates;
    }

    private String getFileDisplay(CommandSession session, Path path) {
        String type;
        String suffix;
        if (Files.isSymbolicLink(path)) {
            type = "sl";
            suffix = "@";
        } else if (Files.isDirectory(path)) {
            type = "dr";
            suffix = "/";
        } else if (Files.isExecutable(path)) {
            type = "ex";
            suffix = "*";
        } else if (!Files.isRegularFile(path)) {
            type = "ot";
            suffix = "";
        } else {
            type = "";
            suffix = "";
        }
        return Posix.applyStyle(path.getFileName().toString(), Posix.getLsColorMap(session), type) + suffix;

    }

    public void __usage_completion(CommandSession session, String command) throws Exception {
        Object func = session.get(command.contains(":") ? command : "*:" + command);
        if (func instanceof Function) {
            ByteArrayInputStream bais = new ByteArrayInputStream(new byte[0]);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ByteArrayOutputStream baes = new ByteArrayOutputStream();
            CommandSession ts = ((CommandSessionImpl) session).processor().createSession(bais, new PrintStream(baos), new PrintStream(baes));
            ts.execute(command + " --help");

            String regex = "(?x)\\s*" + "(?:-([^-]))?" +  // 1: short-opt-1
                    "(?:,?\\s*-(\\w))?" +                 // 2: short-opt-2
                    "(?:,?\\s*--(\\w[\\w-]*)(=\\w+)?)?" + // 3: long-opt-1 and 4:arg-1
                    "(?:,?\\s*--(\\w[\\w-]*))?" +         // 5: long-opt-2
                    ".*?(?:\\(default=(.*)\\))?\\s*" +    // 6: default
                    "(.*)";                               // 7: description
            Pattern pattern = Pattern.compile(regex);
            for (String l : baes.toString().split("\n")) {
                Matcher matcher = pattern.matcher(l);
                if (matcher.matches()) {
                    List<String> args = new ArrayList<>();
                    if (matcher.group(1) != null) {
                        args.add("--short-option");
                        args.add(matcher.group(1));
                    }
                    if (matcher.group(3) != null) {
                        args.add("--long-option");
                        args.add(matcher.group(1));
                    }
                    if (matcher.group(4) != null) {
                        args.add("--argument");
                        args.add("");
                    }
                    if (matcher.group(7) != null) {
                        args.add("--description");
                        args.add(matcher.group(7));
                    }
                    complete(session, args.toArray(new String[args.size()]));
                }
            }
        }
    }

}
