/*
 * 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.jclouds.cli.runner;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.TimeoutException;
import jline.Terminal;
import org.apache.felix.gogo.commands.Action;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.gogo.commands.CommandException;
import org.apache.felix.gogo.commands.basic.AbstractCommand;
import org.apache.felix.gogo.runtime.CommandNotFoundException;
import org.apache.felix.gogo.runtime.CommandProcessorImpl;
import org.apache.felix.gogo.runtime.threadio.ThreadIOImpl;
import org.apache.felix.service.command.CommandSession;
import org.apache.felix.service.command.Function;
import org.apache.karaf.shell.console.NameScoping;
import org.apache.karaf.shell.console.jline.Console;
import org.apache.karaf.shell.console.jline.TerminalFactory;
import org.fusesource.jansi.Ansi;
import org.fusesource.jansi.AnsiConsole;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.InsufficientResourcesException;
import org.jclouds.util.Throwables2;

/**
 * This is forked from Apache Karaf and aligned to the needs of jclouds cli.
 */
public class Main {
    private static final String KARAF_HOME = "karaf.home";
    private static final Class[] parameters = new Class[] {URL.class};

    private String application = System.getProperty("karaf.name", "root");
    private String user = "karaf";

    private static enum Errno {
        ENOENT(2),
        EIO(5),
        EACCES(13),
        ETIMEDOUT(110),
        EDQUOT(122),
        UNKNOWN(255);

        private final int errno;

        Errno(int errno) {
            this.errno = errno;
        }

        int getErrno() {
            return errno;
        }
    }

    /**
     * Exit if klass has the same type or sub-type as throwable or one of its
     * causes.  If exiting, emit message.
     */
    private static void exitIfThrowableMatches(Throwable throwable,
            Class klass, Errno errno, String message) {
        Throwable cause = Throwables2.getFirstThrowableOfType(throwable, klass);
        if (cause == null) {
            return;
        }
        System.err.format("%s: %s\n", message, cause.getMessage());
        System.exit(errno.getErrno());
    }

    public static void main(String args[]) throws Exception {
        Main main = new Main();
        try {
            main.run(args);
        } catch (CommandNotFoundException cnfe) {
            String str = Ansi.ansi()
                    .fg(Ansi.Color.RED)
                    .a("Command not found: ")
                    .a(Ansi.Attribute.INTENSITY_BOLD)
                    .a(cnfe.getCommand())
                    .a(Ansi.Attribute.INTENSITY_BOLD_OFF)
                    .fg(Ansi.Color.DEFAULT).toString();
            System.err.println(str);
            System.exit(Errno.UNKNOWN.getErrno());
        } catch (CommandException ce) {
            System.err.println(ce.getNiceHelp());
            System.exit(Errno.UNKNOWN.getErrno());
        } catch (Throwable t) {
            exitIfThrowableMatches(t, AuthorizationException.class, Errno.EACCES, "Authorization error");
            exitIfThrowableMatches(t, ContainerNotFoundException.class, Errno.ENOENT, "Container not found");
            // FileNotFoundException must precede IOException due to inheritance
            exitIfThrowableMatches(t, FileNotFoundException.class, Errno.ENOENT, "File not found");
            exitIfThrowableMatches(t, IOException.class, Errno.EIO, "IO error");
            exitIfThrowableMatches(t, InsufficientResourcesException.class, Errno.EDQUOT, "Insufficient resources");
            exitIfThrowableMatches(t, KeyNotFoundException.class, Errno.ENOENT, "Blob not found");
            exitIfThrowableMatches(t, TimeoutException.class, Errno.ETIMEDOUT, "Timeout");
            t.printStackTrace();
            System.exit(Errno.UNKNOWN.getErrno());
        }
        // We must explicitly exit on success since we do not close
        // BlobStoreContext and ComputeServiceContext.
        System.exit(0);
    }

    /**
     * Use this method when the shell is being executed as a top level shell.
     *
     * @param args
     * @throws Exception
     */
    public void run(String args[]) throws Exception {

        ThreadIOImpl threadio = new ThreadIOImpl();
        threadio.start();

        ClassLoader cl = Main.class.getClassLoader();
        //This is a workaround for windows machines struggling with long class paths.
        loadJarsFromPath(new File(System.getProperty(KARAF_HOME), "system"));
        loadJarsFromPath(new File(System.getProperty(KARAF_HOME), "deploy"));
        CommandProcessorImpl commandProcessor = new CommandProcessorImpl(threadio);

        discoverCommands(commandProcessor, cl);

        InputStream in = unwrap(System.in);
        PrintStream out = wrap(unwrap(System.out));
        PrintStream err = wrap(unwrap(System.err));
        run(commandProcessor, args, in, out, err);
    }


    /**
     * Loads Jars found under the specified path.
     * @throws IOException
     */
    public void loadJarsFromPath(File path) throws IOException {
        Queue<File> dirs = new LinkedList<File>();
        dirs.add(path);
        while (!dirs.isEmpty()) {
            for (File f : dirs.poll().listFiles()) {
                if (f.isDirectory()) {
                    dirs.add(f);
                } else if (f.isFile() && f.getAbsolutePath().endsWith(".jar") && !f.getAbsolutePath().contains("pax-logging")) {
                    //We make sure to exclude pax logging jars when running outside of OSGi, since we use external logging jars in that case.
                    addURL(f.toURI().toURL());
                }
            }
        }
    }
    public static void addURL(URL u) throws IOException
    {
        URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
        Class sysclass = URLClassLoader.class;

        try {
            Method method = sysclass.getDeclaredMethod("addURL", parameters);
            method.setAccessible(true);
            method.invoke(sysloader, new Object[] {u});
        } catch (Throwable t) {
            t.printStackTrace();
            throw new IOException("Error, could not add URL to system classloader");
        }

    }

    private void run(final CommandProcessorImpl commandProcessor, String[] args, final InputStream in, final PrintStream out, final PrintStream err) throws Exception {

        if (args.length > 0) {
            // Commands have the form: jclouds:category-action.
            List<String> commands = new ArrayList<String>(
                commandProcessor.getCommands());
            Collections.sort(commands);
            if (!commands.contains(args[0])) {
                final String INDENT = "    ";
                StringBuffer sb = new StringBuffer(
                    "Usage: jclouds {category} {action} {options/arguments}");

                // list commands
                sb.append("\n\nValid commands:");
                for (String command : commands) {
                    if (command.startsWith("jclouds:")) {
                        command = command.substring("jclouds:".length());
                        int index = command.indexOf('-');
                        String category = command.substring(0, index);
                        String action = command.substring(index + 1);
                        sb.append('\n').append(INDENT).append(category)
                            .append(' ').append(action);
                        // TODO: expose command descriptions
                    }
                }

                // list options
                sb.append("\n\nOptions:")
                    .append('\n').append(INDENT)
                    .append("--provider:   The id of the provider")
                    .append('\n').append(INDENT)
                    .append("--api:        The id of the api")
                    .append('\n').append(INDENT)
                    .append("--endpoint:   The endpoint")
                    .append('\n').append(INDENT)
                    .append("--identity:   The identity")
                    .append('\n').append(INDENT)
                    .append("--credential: The credential");

                throw new CommandNotFoundException(sb.toString());
            }

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < args.length; i++) {
                if (i > 0) {
                    sb.append(" ");
                }
                sb.append(args[i]);
            }

            // Shell is directly executing a sub/command, we don't setup a terminal and console
            // in this case, this avoids us reading from stdin un-necessarily.
            CommandSession session = commandProcessor.createSession(in, out, err);
            session.put("USER", user);
            session.put("APPLICATION", application);
            session.put(NameScoping.MULTI_SCOPE_MODE_KEY, Boolean.toString(isMultiScopeMode()));
            session.execute(sb);
        } else {
            // We are going into full blown interactive shell mode.

            final TerminalFactory terminalFactory = new TerminalFactory();
            final Terminal terminal = terminalFactory.getTerminal();
            Console console = createConsole(commandProcessor, in, out, err, terminal);
            CommandSession session = console.getSession();
            session.put("USER", user);
            session.put("APPLICATION", application);
            session.put(NameScoping.MULTI_SCOPE_MODE_KEY, Boolean.toString(isMultiScopeMode()));
            session.put("#LINES", new Function() {
                public Object execute(CommandSession session, List<Object> arguments) throws Exception {
                    return Integer.toString(terminal.getHeight());
                }
            });
            session.put("#COLUMNS", new Function() {
                public Object execute(CommandSession session, List<Object> arguments) throws Exception {
                    return Integer.toString(terminal.getWidth());
                }
            });
            session.put(".jline.terminal", terminal);

            console.run();

            terminalFactory.destroy();
        }

    }

    /**
     * Allow sub classes of main to change the Console implementation used.
     *
     * @param commandProcessor
     * @param in
     * @param out
     * @param err
     * @param terminal
     * @return
     * @throws Exception
     */
    protected Console createConsole(CommandProcessorImpl commandProcessor, InputStream in, PrintStream out, PrintStream err, Terminal terminal) throws Exception {
        return new Console(commandProcessor, in, out, err, terminal, null);
    }

    /**
     * Sub classes can override so that their registered commands do not conflict with the default shell
     * implementation.
     *
     * @return
     */
    public String getDiscoveryResource() {
        return "META-INF/services/org/apache/karaf/shell/commands";
    }

    private void discoverCommands(CommandProcessorImpl commandProcessor, ClassLoader cl) throws IOException, ClassNotFoundException {
        Enumeration<URL> urls = cl.getResources(getDiscoveryResource());
        while (urls.hasMoreElements()) {
            URL url = urls.nextElement();
            BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
            try {
                while (true) {
                    String line = reader.readLine();
                    if (line == null) {
                        break;
                    }
                    line = line.trim();
                    if (line.isEmpty() || line.charAt(0) == '#') {
                        continue;
                    }
                    final Class<Action> actionClass = (Class<Action>) cl.loadClass(line);
                    Command cmd = actionClass.getAnnotation(Command.class);
                    Function function = new AbstractCommand() {
                        @Override
                        public Action createNewAction() {
                            try {
                                return ((Class<? extends Action>) actionClass).newInstance();
                            } catch (InstantiationException e) {
                                throw new RuntimeException(e);
                            } catch (IllegalAccessException e) {
                                throw new RuntimeException(e);
                            }
                        }
                    };
                    addCommand(cmd, function, commandProcessor);
                }
            } finally {
                reader.close();
            }
        }
    }

    protected void addCommand(Command cmd, Function function, CommandProcessorImpl commandProcessor) {
        try {
            commandProcessor.addCommand(cmd.scope(), function, cmd.name());
        } catch (Exception e) {
        }
    }


    public String getApplication() {
        return application;
    }

    public void setApplication(String application) {
        this.application = application;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    /**
     * Returns whether or not we are in multi-scope mode.
     * <p/>
     * The default mode is multi-scoped where we prefix commands by their scope. If we are in single
     * scoped mode then we don't use scope prefixes when registering or tab completing commands.
     */
    public boolean isMultiScopeMode() {
        return true;
    }

    private static PrintStream wrap(PrintStream stream) {
        OutputStream o = AnsiConsole.wrapOutputStream(stream);
        if (o instanceof PrintStream) {
            return ((PrintStream) o);
        } else {
            return new PrintStream(o);
        }
    }

    private static <T> T unwrap(T stream) {
        try {
            Method mth = stream.getClass().getMethod("getRoot");
            return (T) mth.invoke(stream);
        } catch (Throwable t) {
            return stream;
        }
    }

    private static List<URL> getFiles(File base) throws MalformedURLException {
        List<URL> urls = new ArrayList<URL>();
        getFiles(base, urls);
        return urls;
    }

    private static void getFiles(File base, List<URL> urls) throws MalformedURLException {
        for (File f : base.listFiles()) {
            if (f.isDirectory()) {
                getFiles(f, urls);
            } else if (f.getName().endsWith(".jar")) {
                urls.add(f.toURI().toURL());
            }
        }
    }
}
