/*
 * 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.
 */

import org.apache.tinkerpop.gremlin.language.translator.GremlinTranslator
import org.apache.tinkerpop.gremlin.language.translator.Translator
import org.apache.tinkerpop.gremlin.language.corpus.FeatureReader

import java.nio.file.Paths

// file is overwritten on each generation
radishGremlinFile = new File("${projectBaseDir}/gremlin-go/driver/cucumber/gremlin.go")

// assumes globally unique scenario names for keys with list of Gremlin traversals as they appear
gremlins = FeatureReader.parseGrouped(Paths.get("${projectBaseDir}", "gremlin-test", "src", "main", "resources", "org", "apache", "tinkerpop", "gremlin", "test", "features").toString())

radishGremlinFile.withWriter('UTF-8') { Writer writer ->
    writer.writeLine('/*\n' +
            'Licensed to the Apache Software Foundation (ASF) under one\n' +
            'or more contributor license agreements.  See the NOTICE file\n' +
            'distributed with this work for additional information\n' +
            'regarding copyright ownership.  The ASF licenses this file\n' +
            'to you under the Apache License, Version 2.0 (the\n' +
            '"License"); you may not use this file except in compliance\n' +
            'with the License.  You may obtain a copy of the License at\n' +
            '\n' +
            '  http://www.apache.org/licenses/LICENSE-2.0\n' +
            '\n' +
            'Unless required by applicable law or agreed to in writing,\n' +
            'software distributed under the License is distributed on an\n' +
            '"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n' +
            'KIND, either express or implied.  See the License for the\n' +
            'specific language governing permissions and limitations\n' +
            'under the License.\n' +
            '*/\n')

    writer.writeLine("\n//********************************************************************************")
    writer.writeLine("//* Do NOT edit this file directly - generated by build/generate.groovy")
    writer.writeLine("//********************************************************************************\n")

    writer.writeLine(
        'package gremlingo\n' +
        '\n' +
        'import (\n' +
        '\t \"errors\"\n' +
        '\t \"github.com/apache/tinkerpop/gremlin-go/v3/driver\"\n' +
        '\t \"github.com/google/uuid\"\n' +
        '\t \"math\"\n' +
        '\t \"time\"\n' +
        ')\n'
    )

    // We might need a function to copy all the translations

    writer.writeLine(
        'var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal{'
    )

    def staticTranslate = [
    "g_withSackX2147483647iX_injectX0_5fX_sackXdivX_sack":"    \"g_withSackX2147483647iX_injectX0_5fX_sackXdivX_sack\": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithSack(int32(2147483647)).Inject(0.5).Sack(gremlingo.Operator.Div).Sack()}}, ", //Scenario fails due to floating point rounding error in Go if this is allowed to correctly translate to float32(0.5)
    ]

    gremlins.each { k,v ->
        if (staticTranslate.containsKey(k)) {
            writer.writeLine(staticTranslate[k])
        } else {
            writer.write("    ")
            writer.write("\"")
            writer.write(k)
            writer.write("\": {")
            def collected = v.collect { GremlinTranslator.translate(it, Translator.GO) }
            def uniqueBindings = collected.collect { it.getParameters() }.flatten().unique()
            def gremlinItty = collected.iterator()
            while (gremlinItty.hasNext()) {
                def t = gremlinItty.next()
                writer.write("func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return ")
                try {
                    writer.write(t.getTranslated().
                            replaceAll("xx([0-9]+)", "p[\"xx\$1\"]").
                            replaceAll("v([0-9]+)", "p[\"v\$1\"]").
                            replaceAll("vid([0-9]+)", "p[\"vid\$1\"]").
                            replaceAll("e([0-9]+)", "p[\"e\$1\"]").
                            replaceAll("eid([0-9]+)", "p[\"eid\$1\"]").
                            replace("l1", "p[\"l1\"]").
                            replace("l2", "p[\"l2\"]").
                            replace("pred1", "p[\"pred1\"]").
                            replace("c1", "p[\"c1\"]").
                            replace("c2", "p[\"c2\"]"))
                } catch (ignored) {
                    // Putting these in place of not implemented functions
                    // TODO make sure all is supported
                    writer.write("nil")
                }
                writer.write("}")
                if (gremlinItty.hasNext())
                    writer.write(', ')
            }
            writer.writeLine('}, ')
        }
    }
    writer.writeLine('}\n')

    writer.writeLine(
    '   func GetTraversal(scenarioName string, g *gremlingo.GraphTraversalSource, parameters map[string]interface{}, sideEffects map[string]interface{}) (*gremlingo.GraphTraversal, error) {\n' +
    '       if traversalFns, ok := translationMap[scenarioName]; ok {\n' +
    '           traversalFn := traversalFns[0]\n' +
    '           translationMap[scenarioName] = traversalFns[1:]\n' +
    '           traversal := traversalFn(g, parameters)\n' +
    '           for key, value := range sideEffects {\n' +
    '               traversal.Bytecode.AddSource("withSideEffect", key, value)\n' +
    '           }\n' +
    '           return traversal, nil\n' +
    '       } else {\n' +
    '           return nil, errors.New("scenario for traversal not recognized")\n' +
    '       }\n' +
    '   }\n'
    )
}

