/*
 * 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.UnknownHostException;
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),
        ENXIO(6),
        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");
            // UnknownHostException must precede IOException due to inheritance
            exitIfThrowableMatches(t, UnknownHostException.class, Errno.ENXIO, "Unknown host");
            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("--properties: File containing properties")
                    .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());
            }
        }
    }
}
