/*
 * 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.geronimo.gshell.wisdom.shell;

import jline.Completor;
import jline.History;
import org.apache.geronimo.gshell.application.Application;
import org.apache.geronimo.gshell.command.Variables;
import org.apache.geronimo.gshell.commandline.CommandLineExecutor;
import org.apache.geronimo.gshell.console.Console;
import org.apache.geronimo.gshell.console.Console.ErrorHandler;
import org.apache.geronimo.gshell.console.Console.Prompter;
import org.apache.geronimo.gshell.console.JLineConsole;
import org.apache.geronimo.gshell.console.completer.AggregateCompleter;
import org.apache.geronimo.gshell.io.Closer;
import org.apache.geronimo.gshell.io.IO;
import org.apache.geronimo.gshell.notification.ExitNotification;
import org.apache.geronimo.gshell.registry.CommandResolver;
import org.apache.geronimo.gshell.shell.Shell;
import org.apache.geronimo.gshell.shell.ShellContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

/**
 * This is the primary implementation of {@link Shell}.
 *
 * @version $Rev$ $Date$
 */
public class ShellImpl
    implements Shell
{
    private final Logger log = LoggerFactory.getLogger(getClass());

    private final Application application;

    private final CommandLineExecutor executor;

    private History history;

    private List<Completor> completers;

    private ShellContext context;

    private Prompter prompter;

    private ErrorHandler errorHandler;

    private boolean opened;

    public ShellImpl(final Application application, final CommandLineExecutor executor) {
        assert application != null;
        this.application = application;
        assert executor != null;
        this.executor = executor;
    }

    private synchronized void ensureOpened() {
        if (!opened) {
            throw new IllegalStateException("Shell has not been opened or has been closed");
        }
    }

    public synchronized boolean isOpened() {
        return true;
    }

    // @PostConstruct
    public synchronized void init() throws Exception {
        if (opened) {
            throw new IllegalStateException("Shell is already opened");
        }

        log.debug("Initializing");

        assert application != null;

        // Each shell gets its own variables, using application variables for defaults
        final Variables vars = new Variables(application.getVariables());

        context = new ShellContext()
        {
            public Shell getShell() {
                return ShellImpl.this;
            }

            public IO getIo() {
                // Shells inherit the application's IO
                return application.getIo();
            }

            public Variables getVariables() {
                return vars;
            }
        };

        vars.set("gshell.prompt", application.getModel().getBranding().getPrompt());
        vars.set(CommandResolver.GROUP, "/");
        vars.set("gshell.username", application.getUserName());
        vars.set("gshell.hostname", application.getLocalHost());

        // HACK: Add history for the 'history' command, since its not part of the Shell intf it can't really access it
        vars.set("gshell.internal.history", getHistory(), true);

        loadProfileScripts();

        opened = true;
    }

    public synchronized void close() {
        log.debug("Closing");

        opened = false;
    }
    
    public ShellContext getContext() {
        ensureOpened();

        if (context == null) {
            throw new IllegalStateException("Shell context has not been initialized");
        }
        return context;
    }

    public void setCompleters(final List<Completor> completers) {
        assert completers != null;

        this.completers = completers;
    }

    public History getHistory() {
        if (history == null) {
            throw new IllegalStateException("Missing configuration property: history");
        }
        return history;
    }

    public void setHistory(final History history) {
        this.history = history;
    }

    public boolean isInteractive() {
        return true;
    }

    public Object execute(final String line) throws Exception {
        ensureOpened();

        assert executor != null;
        return executor.execute(getContext(), line);
    }

    public Object execute(final String command, final Object[] args) throws Exception {
        ensureOpened();

        assert executor != null;
        return executor.execute(getContext(), command, args);
    }

    public Object execute(final Object... args) throws Exception {
        ensureOpened();

        assert executor != null;
        return executor.execute(getContext(), args);
    }

    public void run(final Object... args) throws Exception {
        assert args != null;

        ensureOpened();

        log.debug("Starting interactive console; args: {}", args);

        loadUserScript(application.getModel().getBranding().getInteractiveScriptName());

        // Setup 2 final refs to allow our executor to pass stuff back to us
        final AtomicReference<ExitNotification> exitNotifHolder = new AtomicReference<ExitNotification>();
        final AtomicReference<Object> lastResultHolder = new AtomicReference<Object>();

        // Whip up a tiny console executor that will execute shell command-lines
        Console.Executor executor = new Console.Executor() {
            public Result execute(final String line) throws Exception {
                assert line != null;

                try {
                    Object result = ShellImpl.this.execute(line);

                    lastResultHolder.set(result);
                }
                catch (ExitNotification n) {
                    exitNotifHolder.set(n);

                    return Result.STOP;
                }

                return Result.CONTINUE;
            }
        };

        IO io = getContext().getIo();

        // Setup the console runner
        JLineConsole console = new JLineConsole(executor, io);
        console.setPrompter(getPrompter());
        console.setErrorHandler(getErrorHandler());
        console.setHistory(getHistory());

        // Attach completers if there are any
        if (completers != null) {
            // Have to use aggregate here to get the completion list to update properly
            console.addCompleter(new AggregateCompleter(completers));
        }

        // Unless the user wants us to shut up, then display a nice welcome banner
        if (!io.isQuiet()) {
            String message = application.getModel().getBranding().getWelcomeMessage();
            if (message != null) {
                io.out.print(message);
                io.out.println(repeat("-", io.getTerminal().getTerminalWidth() - 1));
                io.out.flush();
            }
        }

        // Check if there are args, and run them and then enter interactive
        if (args.length != 0) {
            execute(args);
        }

        // And then spin up the console and go for a jog
        console.run();

        // If any exit notification occured while running, then puke it up
        ExitNotification n = exitNotifHolder.get();
        if (n != null) {
            throw n;
        }
    }

    private static String repeat(final String str, final int repeat) {
        StringBuilder buffer = new StringBuilder(repeat * str.length());
        for (int i = 0; i < repeat; i++) {
            buffer.append(str);
        }
        return buffer.toString();
    }

    public Prompter getPrompter() {
        if (prompter == null) {
            throw new IllegalStateException("Missing configuration property: prompter");
        }
        return prompter;
    }

    public void setPrompter(final Prompter prompter) {
        this.prompter = prompter;
    }
    
    public ErrorHandler getErrorHandler() {
        if (errorHandler == null) {
            throw new IllegalStateException("Missing configuration property: errorHandler");
        }
        return errorHandler;
    }

    public void setErrorHandler(final ErrorHandler handler) {
        this.errorHandler = handler;
    }

    //
    // Script Processing
    //

    private void loadProfileScripts() throws Exception {
        log.debug("Loading profile scripts");
        
        // Load profile scripts if they exist
        loadSharedScript(application.getModel().getBranding().getProfileScriptName());
        loadUserScript(application.getModel().getBranding().getProfileScriptName());
    }

    private void loadScript(final File file) throws Exception {
        assert file != null;

        BufferedReader reader = new BufferedReader(new FileReader(file));

        try {
            String line;

            while ((line = reader.readLine()) != null) {
                execute(line);
            }
        }
        finally {
            Closer.close(reader);
        }
    }

    private void loadUserScript(final String fileName) throws Exception {
        assert fileName != null;

        File file = new File(application.getModel().getBranding().getUserDirectory(), fileName);

        if (file.exists()) {
            log.debug("Loading user-script: {}", file);

            loadScript(file);
        }
        else {
            log.debug("User script is not present: {}", file);
        }
    }

    private void loadSharedScript(final String fileName) throws Exception {
        assert fileName != null;

        File file = new File(application.getModel().getBranding().getUserDirectory(), fileName);

        if (file.exists()) {
            log.debug("Loading shared-script: {}", file);

            loadScript(file);
        }
        else {
            log.debug("Shared script is not present: {}", file);
        }
    }
}