/*
 * Copyright 2003-2007 the original author or authors.
 *
 * Licensed 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.codehaus.groovy.tools.shell

import java.lang.reflect.Method

import jline.Terminal
import jline.History

import org.codehaus.groovy.runtime.InvokerHelper
import org.codehaus.groovy.runtime.MethodClosure

import org.codehaus.groovy.control.SourceUnit
import org.codehaus.groovy.control.CompilationFailedException

import org.codehaus.groovy.tools.shell.util.MessageSource
import org.codehaus.groovy.tools.shell.util.ANSI.Renderer as AnsiRenderer
import org.codehaus.groovy.tools.shell.util.XmlCommandRegistrar
import org.codehaus.groovy.runtime.StackTraceUtils
import org.codehaus.groovy.tools.shell.util.Preferences

/**
 * An interactive shell for evaluating Groovy code from the command-line (aka. groovysh).
 *
 * @version $Id$
 * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
 */
class Groovysh
    extends Shell
{
    private static final String NEWLINE = System.properties['line.separator']
    
    private static final MessageSource messages = new MessageSource(Groovysh.class)

    private final BufferManager buffers = new BufferManager()

    private final GroovyShell interp
    
    private final List imports = []
    
    private InteractiveShellRunner runner
    
    private History history
    
    Groovysh(final ClassLoader classLoader, final Binding binding, final IO io) {
        super(io)
        
        assert classLoader
        assert binding
        
        interp = new GroovyShell(classLoader, binding)

        //
        // TODO: Change this to be more embed/test friendly
        //
        
        def registrar = new XmlCommandRegistrar(this, classLoader)
        registrar.register(getClass().getResource('commands.xml'))
    }

    Groovysh(final Binding binding, final IO io) {
        this(Thread.currentThread().contextClassLoader, binding, io)
    }

    Groovysh(final IO io) {
        this(new Binding(), io)
    }
    
    Groovysh() {
        this(new IO())
    }

    //
    // Execution
    //

    /**
     * Execute a single line, where the line may be a command or Groovy code (complete or incomplete).
     */
    Object execute(final String line) {
        assert line != null
        
        // Ignore empty lines
        if (line.trim().size() == 0) {
            return null
        }

        maybeRecordInput(line)

        def result
        
        // First try normal command execution
        if (isExecutable(line)) {
            result = executeCommand(line)
            
            // For commands, only set the last result when its non-null/true
            if (result) {
                lastResult = result
            }
            
            return result
        }
        
        // Otherwise treat the line as Groovy
        def current = []
        current += buffers.current()

        // Append the line to the current buffer
        current << line

        // Attempt to parse the current buffer
        def status = parse(current, 1)

        switch (status.code) {
            case ParseCode.COMPLETE:
                // Evaluate the current buffer
                lastResult = result = evaluate(current)
                buffers.clearSelected()
                break

            case ParseCode.INCOMPLETE:
                // Save the current buffer so user can build up complex muli-line code blocks
                buffers.updateSelected(current)
                break

            case ParseCode.ERROR:
                throw status.cause

            default:
                // Should never happen
                throw new Error("Invalid parse status: $status.code")
        }
        
        return result
    }

    protected Object executeCommand(final String line) {
        return super.execute(line)
    }

    /**
     * Attempt to parse the given buffer.
     */
    private ParseStatus parse(final List buffer, final int tolerance) {
        assert buffer

        String source = (imports + buffer).join(NEWLINE)

        log.debug("Parsing: $source")

        SourceUnit parser
        Throwable error

        try {
            parser = SourceUnit.create('groovysh_parse', source, tolerance)
            parser.parse()

            log.debug('Parse complete')

            return new ParseStatus(ParseCode.COMPLETE)
        }
        catch (CompilationFailedException e) {
            //
            // FIXME: Seems like failedWithUnexpectedEOF() is not always set as expected, as in:
            //
            // class a {               <--- is true here
            //    def b() {            <--- is false here :-(
            //
            
            if (parser.errorCollector.errorCount > 1 || !parser.failedWithUnexpectedEOF()) {
                //
                // HACK: Super insane hack... if we detect a syntax error, but the last line of the
                //       buffer ends with a '{' or '[' then ignore... and pretend its okay, cause it might be...
                //
                //       This seems to get around the problem with things like:
                //
                //       class a { def b() {
                //

                if (buffer[-1].trim().endsWith('{')) {
                    // ignore, this blows
                }
                else if (buffer[-1].trim().endsWith('[')) {
                    // ignore, this blows
                }
                else {
                    error = e
                }
            }
        }
        catch (Throwable e) {
            error = e
        }

        if (error) {
            log.debug("Parse error: $error")

            return new ParseStatus(error)
        }
        else {
            log.debug('Parse incomplete')

            return new ParseStatus(ParseCode.INCOMPLETE)
        }
    }

    private static final String EVAL_SCRIPT_FILENAME = 'groovysh_evaluate'

    /**
     * Evaluate the given buffer.  The buffer is assumed to be complete.
     */
    private Object evaluate(final List buffer) {
        assert buffer
        
        log.debug("Evaluating buffer...")

        if (io.verbose) {
            displayBuffer(buffer)
        }

        //
        // HACK: Fix for GROOVY-2213.  Insert a runnable statement (ie. 'true') after imports so that we can
        //       always run the buffer and get any class/enum/whatever defs defined.
        //

        def source = (imports + [ 'true' ] + buffer).join(NEWLINE)
        def result

        Class type
        try {
            Script script = interp.parse(source, EVAL_SCRIPT_FILENAME)
            type = script.getClass()

            log.debug("Compiled script: $script")

            if (type.declaredMethods.any { it.name == 'main' }) {
                result = script.run()
            }

            // Need to use String.valueOf() here to avoid icky exceptions causes by GString coercion
            log.debug("Evaluation result: ${String.valueOf(result)} (${result?.getClass()})")

            // Keep only the methods that have been defined in the script
            type.declaredMethods.each { Method m ->
                if (!(m.name in [ 'main', 'run' ] || m.name.startsWith('super$') || m.name.startsWith('class$'))) {
                    log.debug("Saving method definition: $m")
                    interp.context["${m.name}"] = new MethodClosure(type.newInstance(), m.name)
                }
            }
        }
        finally {
            def cache = interp.classLoader.classCache
            
            // Remove the script class generated
            cache.remove(type?.name)

            // Remove the inline closures from the cache as well
            cache.remove('$_run_closure')
        }
        
        return result
    }

    /**
     * Display the given buffer.
     */
    private void displayBuffer(final List buffer) {
        assert buffer

        buffer.eachWithIndex { line, index ->
            def lineNum = formatLineNumber(index + 1)
            
            io.out.println(" ${lineNum}@|bold >| $line")
        }
    }

    //
    // Prompt
    //

    private AnsiRenderer prompt = new AnsiRenderer()

    private String renderPrompt() {
        def lineNum = formatLineNumber(buffers.current().size())

        return prompt.render("@|bold groovy:|${lineNum}@|bold >| ")
    }

    /**
     * Format the given number suitable for rendering as a line number column.
     */
    private String formatLineNumber(final int num) {
        assert num >= 0

        // Make a %03d-like string for the line number
        return num.toString().padLeft(3, '0')
    }

    //
    // User Profile Scripts
    //

    File getUserStateDirectory() {
        def userHome = new File(System.getProperty('user.home'))
        def dir = new File(userHome, '.groovy')
        return dir.canonicalFile
    }

    private void loadUserScript(final String filename) {
        assert filename
        
        def file = new File(userStateDirectory, filename)
        
        if (file.exists()) {
            def command = registry['load']

            if (command) {
                log.debug("Loading user-script: $file")

                // Disable showLastResult for profile scripts
                boolean tmp = Preferences.showLastResult
                Preferences.showLastResult = false

                try {
                    command.load(file.toURI().toURL())
                }
                finally {
                    Preferences.showLastResult = tmp
                }
            }
            else {
                log.error("Unable to load user-script, missing 'load' command")
            }
        }
    }

    //
    // Recording
    //

    private void maybeRecordInput(final String line) {
        def record = registry['record']

        if (record != null) {
            record.recordInput(line)
        }
    }

    private void maybeRecordResult(final Object result) {
        def record = registry['record']

        if (record != null) {
            record.recordResult(result)
        }
    }

    private void maybeRecordError(Throwable cause) {
        def record = registry['record']

        if (record != null) {
            boolean sanitize = Preferences.sanitizeStackTrace

            if (sanitize) {
                cause = StackTraceUtils.deepSanitize(cause);
            }

            record.recordError(cause)
        }
    }
    
    //
    // Hooks
    //

    final Closure defaultResultHook = { result ->
        boolean showLastResult = !io.quiet && (io.verbose || Preferences.showLastResult)

        if (showLastResult) {
            // Need to use String.valueOf() here to avoid icky exceptions causes by GString coercion
            io.out.println("@|bold ===>| ${String.valueOf(result)}")
        }
    }

    Closure resultHook = defaultResultHook

    private void setLastResult(final Object result) {
        if (resultHook == null) {
            throw new IllegalStateException("Result hook is not set")
        }

        resultHook.call(result)

        interp.context['_'] = result

        maybeRecordResult(result)
    }

    private Object getLastResult() {
        return interp.context['_']
    }

    final Closure defaultErrorHook = { Throwable cause ->
        assert cause != null

        io.err.println("@|bold,red ERROR| ${cause.class.name}: @|bold,red ${cause.message}|")

        maybeRecordError(cause)

        if (log.debug) {
            // If we have debug enabled then skip the fancy bits below
            log.debug(cause)
        }
        else {
            boolean sanitize = Preferences.sanitizeStackTrace

            // Sanitize the stack trace unless we are inverbose mode, or the user has request otherwise
            if (!io.verbose && sanitize) {
                cause = StackTraceUtils.deepSanitize(cause);
            }

            def trace = cause.stackTrace

            def buff = new StringBuffer()

            for (e in trace) {
                buff << "        @|bold at| ${e.className}.${e.methodName} (@|bold "

                buff << (e.nativeMethod ? 'Native Method' :
                            (e.fileName != null && e.lineNumber != -1 ? "${e.fileName}:${e.lineNumber}" :
                                (e.fileName != null ? e.fileName : 'Unknown Source')))

                buff << '|)'

                io.err.println(buff)

                buff.setLength(0) // Reset the buffer

                // Stop the trace once we find the root of the evaluated script
                if (e.className == EVAL_SCRIPT_FILENAME && e.methodName == 'run') {
                    io.err.println('        @|bold ...|')
                    break
                }
            }
        }
    }

    Closure errorHook = defaultErrorHook

    private void displayError(final Throwable cause) {
        if (errorHook == null) {
            throw new IllegalStateException("Error hook is not set")
        }

        errorHook.call(cause)
    }

    //
    // Interactive Shell
    //

    int run(final String[] args) {
        String commandLine = null

        if (args != null && args.length > 0) {
            commandLine = args.join(' ')
        }

        return run(commandLine as String)
    }

    int run(final String commandLine) {
        def term = Terminal.terminal

        if (log.debug) {
            log.debug("Terminal ($term)")
            log.debug("    Supported:  $term.supported")
            log.debug("    ECHO:       $term.echo (enabled: $term.echoEnabled)")
            log.debug("    H x W:      $term.terminalHeight x $term.terminalWidth")
            log.debug("    ANSI:       ${term.isANSISupported()}")

            if (term instanceof jline.WindowsTerminal) {
                log.debug("    Direct:     ${term.directConsole}")
            }
        }

        def code

        try {
            loadUserScript('groovysh.profile')

            if (commandLine != null) {
                // Run the given commands
                execute(commandLine)
            }
            else {
                loadUserScript('groovysh.rc')

                // Setup the interactive runner
                runner = new InteractiveShellRunner(this, this.&renderPrompt as Closure)

                // Setup the history
                runner.history = history = new History()
                runner.historyFile = new File(userStateDirectory, 'groovysh.history')

                // Setup the error handler
                runner.errorHandler = this.&displayError

                //
                // TODO: See if we want to add any more language specific completions, like for println for example?
                //

                // Display the welcome banner
                if (!io.quiet) {
                    def width = term.terminalWidth

                    // If we can't tell, or have something bogus then use a reasonable default
                    if (width < 1) {
                        width = 80
                    }

                    io.out.println(messages.format('startup_banner.0', InvokerHelper.version, System.properties['java.vm.version']))
                    io.out.println(messages['startup_banner.1'])
                    io.out.println('-' * (width - 1))
                }

                // And let 'er rip... :-)
                runner.run()
            }

            code = 0
        }
        catch (ExitNotification n) {
            log.debug("Exiting w/code: ${n.code}")

            code = n.code
        }
        catch (Throwable t) {
            io.err.println(messages.format('info.fatal', t))
            t.printStackTrace(io.err)

            code = 1
        }

        assert code != null // This should never happen

        return code
    }
}

/**
 * Container for the parse code.
 */
class ParseCode {
    static final ParseCode COMPLETE = new ParseCode(code: 0)
    static final ParseCode INCOMPLETE = new ParseCode(code: 1)
    static final ParseCode ERROR = new ParseCode(code: 2)

    int code

    String toString() {
        return code
    }
}

/**
 * Container for parse status details.
 */
class ParseStatus
{
    final ParseCode code

    final Throwable cause

    ParseStatus(final ParseCode code, final Throwable cause) {
        this.code = code
        this.cause = cause
    }

    ParseStatus(final ParseCode code) {
        this(code, null)
    }

    ParseStatus(final Throwable cause) {
        this(ParseCode.ERROR, cause)
    }
}
