/*
 * 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.tinkerpop.gremlin.console

import org.apache.tinkerpop.gremlin.console.commands.GremlinSetCommand
import org.codehaus.groovy.tools.shell.Command
import org.codehaus.groovy.tools.shell.Groovysh
import org.codehaus.groovy.tools.shell.ParseCode
import org.codehaus.groovy.tools.shell.Parser
import org.codehaus.groovy.tools.shell.util.CommandArgumentParser

/**
 * Overrides the posix style parsing of Groovysh allowing for commands to parse prior to Groovy 2.4.x.
 *
 * @author Stephen Mallette (http://stephen.genoprime.com)
 */
class GremlinGroovysh extends Groovysh {

    private final Mediator mediator

    public GremlinGroovysh(final Mediator mediator) {
        this.mediator = mediator
    }

    protected List parseLine(final String line) {
        assert line != null
        return line.trim().tokenize()
    }

    @Override
    Command findCommand(final String line, final List<String> parsedArgs = null) {
        def l = line ?: ""

        final List<String> linetokens = parseLine(l)
        if (linetokens.size() == 0) return null

        def cmd = registry.find(linetokens[0])

        if (cmd != null && linetokens.size() > 1 && parsedArgs != null) {
            if (cmd instanceof GremlinSetCommand) {
                // the following line doesn't play well with :remote scripts because it tokenizes quoted args as single args
                // but at this point only the set command had trouble with quoted params/args with spaces
                List<String> args = CommandArgumentParser.parseLine(line, parsedArgs == null ? 1 : -1)
                parsedArgs.addAll(args[1..-1])
            } else {
                parsedArgs.addAll(linetokens[1..-1])
            }
        }

        return cmd
    }

    @Override
    Object execute(final String line) {
        mediator.evaluating.set(true)

        try {
            if (mediator.localEvaluation)
                return super.execute(line)
            else {
                assert line != null
                if (line.trim().size() == 0) {
                    return null
                }

                maybeRecordInput(line)

                Object result

                if (isExecutable(line)) {
                    result = executeCommand(line)
                    if (result != null) setLastResult(result)
                    return result
                }

                List<String> current = new ArrayList<String>(buffers.current())
                current << line

                // determine if this script is complete or not - if not it's a multiline script
                def status = parser.parse(current)

                switch (status.code) {
                    case ParseCode.COMPLETE:
                        // concat script here because commands don't support multi-line
                        def script = String.join(Parser.getNEWLINE(), current)
                        setLastResult(mediator.currentRemote().submit([script]))
                        buffers.clearSelected()
                        break
                    case ParseCode.INCOMPLETE:
                        buffers.updateSelected(current)
                        break
                    case ParseCode.ERROR:
                        throw status.cause
                    default:
                        // Should never happen
                        throw new Error("Invalid parse status: $status.code")
                }

                return result
            }
        } finally {
            mediator.evaluating.set(false)
        }
    }

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

        resultHook.call((Object)result)

        interp.context['_'] = result

        maybeRecordResult(result)
    }
}
