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

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/apache/tinkerpop/gremlin-go/v3/driver"
	"github.com/cucumber/godog"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"testing"
)

type tinkerPopGraph struct {
	*CucumberWorld
	sync.Mutex
}

var parsers map[*regexp.Regexp]func(string, string) interface{}
var toListLock sync.Mutex

func init() {
	parsers = map[*regexp.Regexp]func(string, string) interface{}{
		regexp.MustCompile(`^d\[(.*)]\.[lfdm]$`): toNumeric,
		regexp.MustCompile(`^d\[(.*)]\.[i]$`):    toInt32,
		regexp.MustCompile(`^v\[(.+)]$`):         toVertex,
		regexp.MustCompile(`^v\[(.+)]\.id$`):     toVertexId,
		regexp.MustCompile(`^e\[(.+)]$`):         toEdge,
		regexp.MustCompile(`^v\[(.+)]\.sid$`):    toVertexIdString,
		regexp.MustCompile(`^e\[(.+)]\.id$`):     toEdgeId,
		regexp.MustCompile(`^e\[(.+)]\.sid$`):    toEdgeIdString,
		regexp.MustCompile(`^p\[(.+)]$`):         toPath,
		regexp.MustCompile(`^l\[(.*)]$`):         toList,
		regexp.MustCompile(`^s\[(.*)]$`):         toSet,
		regexp.MustCompile(`^m\[(.+)]$`):         toMap,
		regexp.MustCompile(`^c\[(.+)]$`):         toLambda,
		regexp.MustCompile(`^t\[(.+)]$`):         toT,
		regexp.MustCompile(`^D\[(.+)]$`):         toDirection,
	}
}

func parseValue(value string, graphName string) interface{} {
	if regexp.MustCompile(`^null$`).MatchString(value) {
		return nil
	}
	var extractedValue string
	var parser func(string, string) interface{}
	for key, element := range parsers {
		var match = key.FindAllStringSubmatch(value, -1)
		if len(match) > 0 {
			parser = element
			extractedValue = match[0][1]
			break
		}
	}
	if parser == nil {
		return value
	} else {
		return parser(extractedValue, graphName)
	}
}

// Parse numeric.
func toNumeric(stringVal, graphName string) interface{} {
	if strings.Contains(stringVal, ".") {
		val, err := strconv.ParseFloat(stringVal, 64)
		if err != nil {
			return nil
		}
		return val
	}
	val, err := strconv.ParseInt(stringVal, 10, 64)
	if err != nil {
		return nil
	}
	return val
}

// Parse int32.
func toInt32(stringVal, graphName string) interface{} {
	val, err := strconv.ParseInt(stringVal, 10, 32)
	if err != nil {
		return nil
	}
	return int32(val)
}

// Parse vertex.
func toVertex(name, graphName string) interface{} {
	return tg.getDataGraphFromMap(graphName).vertices[name]
}

// Parse vertex id.
func toVertexId(name, graphName string) interface{} {
	if tg.getDataGraphFromMap(graphName).vertices[name] == nil {
		return nil
	}
	return tg.getDataGraphFromMap(graphName).vertices[name].Id
}

// Parse vertex id as string.
func toVertexIdString(name, graphName string) interface{} {
	if tg.getDataGraphFromMap(graphName).vertices[name] == nil {
		return nil
	}
	return fmt.Sprint(tg.getDataGraphFromMap(graphName).vertices[name].Id)
}

// Parse edge.
func toEdge(name, graphName string) interface{} {
	return tg.getDataGraphFromMap(graphName).edges[name]
}

// Parse edge id.
func toEdgeId(name, graphName string) interface{} {
	if tg.getDataGraphFromMap(graphName).edges[name] == nil {
		return nil
	}
	return tg.getDataGraphFromMap(graphName).edges[name].Id
}

// Parse edge id as string.
func toEdgeIdString(name, graphName string) interface{} {
	if tg.getDataGraphFromMap(graphName).edges[name] == nil {
		return nil
	}
	return fmt.Sprint(tg.getDataGraphFromMap(graphName).edges[name].Id)
}

// Parse path.
func toPath(stringObjects, graphName string) interface{} {
	objects := make([]interface{}, 0)
	for _, str := range strings.Split(stringObjects, ",") {
		objects = append(objects, parseValue(str, graphName))
	}
	return &gremlingo.Path{
		Labels:  []gremlingo.Set{},
		Objects: objects,
	}
}

// Parse list.
func toList(stringList, graphName string) interface{} {
	listVal := make([]interface{}, 0)
	if len(stringList) == 0 {
		return listVal
	}

	for _, str := range strings.Split(stringList, ",") {
		listVal = append(listVal, parseValue(str, graphName))
	}
	return listVal
}

// Parse set to simple set.
func toSet(stringSet, graphName string) interface{} {
	setVal := gremlingo.NewSimpleSet()
	if len(stringSet) == 0 {
		return setVal
	}
	for _, str := range strings.Split(stringSet, ",") {
		setVal.Add(parseValue(str, graphName))
	}
	return setVal
}

// Parse json as a map.
func toMap(name, graphName string) interface{} {
	var jsonMap interface{}
	err := json.Unmarshal([]byte(name), &jsonMap)
	if err != nil {
		return nil
	}
	return parseMapValue(jsonMap, graphName)
}

func parseMapValue(mapVal interface{}, graphName string) interface{} {
	if mapVal == nil {
		return nil
	}
	switch reflect.TypeOf(mapVal).Kind() {
	case reflect.String:
		return parseValue(mapVal.(string), graphName)
	case reflect.Float64, reflect.Int64:
		return mapVal
	case reflect.Array, reflect.Slice:
		var valSlice []interface{}
		oriSlice := reflect.ValueOf(mapVal)
		for i := 0; i < oriSlice.Len(); i++ {
			valSlice = append(valSlice, parseMapValue(oriSlice.Index(i).Interface(), graphName))
		}
		return valSlice
	case reflect.Map:
		valMap := make(map[interface{}]interface{})
		v := reflect.ValueOf(mapVal)
		keys := v.MapKeys()
		for _, k := range keys {
			convKey := k.Convert(v.Type().Key())
			val := v.MapIndex(convKey)
			keyVal := parseMapValue(k.Interface(), graphName)
			if reflect.ValueOf(keyVal).Kind() == reflect.Slice {
				// Turning map keys of slice type into string type for comparison purposes
				// string slices should also be converted into slices more easily
				valMap[fmt.Sprint(keyVal)] = parseMapValue(val.Interface(), graphName)
			} else {
				valMap[keyVal] = parseMapValue(val.Interface(), graphName)
			}
		}
		return valMap
	default:
		// Not supported types.
		return nil
	}
}

// Parse lambda.
func toLambda(name, graphName string) interface{} {
	return &gremlingo.Lambda{Script: name}
}

func toT(name, graphName string) interface{} {
	// Return as is, since t values are just strings.
	return name
}

func toDirection(name, graphName string) interface{} {
	// Return as is, since direction values are just strings.
	return name
}

func (tg *tinkerPopGraph) anUnsupportedTest() error {
	return nil
}

func (tg *tinkerPopGraph) iteratedNext() error {
	if tg.traversal == nil {
		// Return pending because this is not currently implemented.
		return godog.ErrPending
	}
	result, err := tg.traversal.Next()
	if err != nil {
		return err
	}
	var nextResults []interface{}
	switch result.GetType().Kind() {
	case reflect.Array, reflect.Slice:
		resSlice := reflect.ValueOf(result.GetInterface())
		for i := 0; i < resSlice.Len(); i++ {
			nextResults = append(nextResults, resSlice.Index(i).Interface())
		}
	default:
		simpleSet, ok := result.GetInterface().(*gremlingo.SimpleSet)
		if ok {
			nextResults = simpleSet.ToSlice()
		} else {
			nextResults = append(nextResults, result)
		}
	}

	tg.result = nextResults
	return nil
}

func (tg *tinkerPopGraph) iteratedToList() error {
	if tg.traversal == nil {
		// Return pending because this is not currently implemented.
		return godog.ErrPending
	}
	results, err := tg.traversal.ToList()
	if err != nil {
		return err
	}
	var listResults []interface{}
	for _, res := range results {
		listResults = append(listResults, res)
	}
	tg.result = listResults
	return nil
}

func (tg *tinkerPopGraph) nothingShouldHappenBecause(arg1 *godog.DocString) error {
	return nil
}

// Choose the graph.
func (tg *tinkerPopGraph) chooseGraph(graphName string) error {
	tg.graphName = graphName
	data := tg.graphDataMap[graphName]
	tg.g = gremlingo.Traversal_().WithRemote(data.connection)
	if graphName == "empty" {
		err := tg.cleanEmptyDataGraph(tg.g)
		if err != nil {
			return err
		}
	}
	return nil
}

func (tg *tinkerPopGraph) theGraphInitializerOf(arg1 *godog.DocString) error {
	traversal, err := GetTraversal(tg.scenario.Name, tg.g, tg.parameters)
	if err != nil {
		return err
	}
	future := traversal.Iterate()
	return <-future
}

func (tg *tinkerPopGraph) theResultShouldHaveACountOf(expectedCount int) error {
	actualCount := len(tg.result)
	if actualCount != expectedCount {
		if actualCount == 1 {
			switch reflect.TypeOf(tg.result).Kind() {
			case reflect.Slice, reflect.Array:
				result := tg.result[0].(*gremlingo.Result).GetInterface()
				switch reflect.TypeOf(result).Kind() {
				case reflect.Map:
					actualCount = len(result.(map[interface{}]interface{}))
				}
			}
			if actualCount != expectedCount {
				return fmt.Errorf("result should return %d for count, but returned %d", expectedCount, actualCount)
			}
		} else {
			return fmt.Errorf("result should return %d for count, but returned %d", expectedCount, actualCount)
		}
	}
	return nil
}

func (tg *tinkerPopGraph) theGraphShouldReturnForCountOf(expectedCount int, traversalText string) error {
	traversal, err := GetTraversal(tg.scenario.Name, tg.g, tg.parameters)
	if err != nil {
		return err
	}
	results, err := traversal.ToList()
	if err != nil {
		return err
	}
	if len(results) != expectedCount {
		return fmt.Errorf("graph returned count of %d when %d was expected", len(results), expectedCount)
	}
	return nil
}

func (tg *tinkerPopGraph) theResultShouldBeEmpty() error {
	if len(tg.result) != 0 {
		return errors.New("actual result is not empty as expected")
	}
	return nil
}

func (tg *tinkerPopGraph) theResultShouldBe(characterizedAs string, table *godog.Table) error {
	ordered := characterizedAs == "ordered"
	// For comparing ordered gremlingo.SimpleSet case.
	var expectSet bool
	var expectPath bool
	switch characterizedAs {
	case "ordered", "unordered", "of":
		var expectedResult []interface{}
		for idx, row := range table.Rows {
			if idx == 0 {
				// Skip the header line.
				continue
			}
			val := parseValue(row.Cells[0].Value, tg.graphName)
			v, ok := val.(*gremlingo.Path)
			expectPath = ok
			if ok {
				// Clear the labels since we don't define them in feature files.
				v.Labels = []gremlingo.Set{}
				val = v
			}
			_, expectSet = val.(*gremlingo.SimpleSet)
			expectedResult = append(expectedResult, val)
		}
		var actualResult []interface{}
		if len(tg.result) == 1 {
			switch r := tg.result[0].(type) {
			case *gremlingo.Result:
				val, ok := r.GetInterface().(*gremlingo.Path)
				if !expectPath && ok {
					actualResult = val.Objects
				} else {
					actualResult = append(actualResult, r.GetInterface())
				}
			default:
				actualResult = append(actualResult, r)
			}
		} else {
			for _, res := range tg.result {
				switch r := res.(type) {
				case *gremlingo.Result:
					actualResult = append(actualResult, r.GetInterface())
				default:
					actualResult = append(actualResult, r)
				}
			}
		}
		if characterizedAs != "of" && (len(actualResult) != len(expectedResult)) {
			err := fmt.Sprintf("actual result length does not equal expected (%d!=%d).", len(actualResult), len(expectedResult))
			return errors.New(err)
		}
		if ordered {
			if expectSet {
				for i, a := range actualResult {
					if fmt.Sprint(a.(*gremlingo.SimpleSet).ToSlice()) != fmt.Sprint(expectedResult[i].(*gremlingo.SimpleSet).ToSlice()) {
						return fmt.Errorf("actual result does not match expected (order expected)\nActual: %v\nExpected: %v", actualResult, expectedResult)
					}
				}
			} else if len(actualResult) == 1 && len(expectedResult) == 1 && reflect.TypeOf(actualResult[0]).Kind() == reflect.Map &&
				reflect.TypeOf(expectedResult[0]).Kind() == reflect.Map {
				if !compareMapEquals(actualResult[0].(map[interface{}]interface{}), expectedResult[0].(map[interface{}]interface{})) {
					return fmt.Errorf("actual result does not match expected (order expected)\nActual: %v\nExpected: %v", actualResult, expectedResult)
				}
			} else if fmt.Sprint(actualResult) != fmt.Sprint(expectedResult) {
				return fmt.Errorf("actual result does not match expected (order expected)\nActual: %v\nExpected: %v", actualResult, expectedResult)
			}
		} else {
			if characterizedAs == "of" {
				if !compareListEqualsWithOf(expectedResult, actualResult) {
					return fmt.Errorf("actual result does not match expected (order not expected)\nActual: %v\nExpected: %v", actualResult, expectedResult)
				}
			} else {
				if !compareListEqualsWithoutOrder(expectedResult, actualResult) {
					return fmt.Errorf("actual result does not match expected (order not expected)\nActual: %v\nExpected: %v", actualResult, expectedResult)
				}
			}
		}
		return nil
	default:
		return errors.New("scenario not supported")
	}
}

func compareMapEquals(expected map[interface{}]interface{}, actual map[interface{}]interface{}) bool {
	for k, a := range actual {
		var e interface{}
		containsKey := false
		for ke, ee := range expected {
			if fmt.Sprint(k) == fmt.Sprint(ke) {
				containsKey = true
				e = ee
				break
			} else {
				if reflect.ValueOf(k).Kind() == reflect.Ptr &&
					reflect.ValueOf(ke).Kind() == reflect.Ptr {
					switch k.(type) {
					case *gremlingo.Vertex:
						switch ke.(type) {
						case *gremlingo.Vertex:
							if fmt.Sprint(*k.(*gremlingo.Vertex)) == fmt.Sprint(*ke.(*gremlingo.Vertex)) {
								containsKey = true
							}
						default:
							// Not equal.
						}
					default:
						// If we are here we probably need to implement an additional type like the Vertex above.
						if fmt.Sprint(*k.(*interface{})) == fmt.Sprint(*ke.(*interface{})) {
							fmt.Println("WARNING: Encountered unknown pointer type as map key.")
							containsKey = true
						}
					}
					if containsKey {
						e = ee
						break
					}
				}
			}
		}
		if !containsKey {
			fmt.Printf("Map comparison error: Failed to find key %s in %v\n", k, expected)
			return false
		}

		if a == nil && e == nil {
			continue
		} else if a == nil || e == nil {
			// One value is nil, other is not. They are not equal.
			fmt.Printf("Map comparison error: One map has a nil key, other does not.\n")
			return false
		} else {
			switch reflect.TypeOf(a).Kind() {
			case reflect.Array, reflect.Slice:
				switch reflect.TypeOf(e).Kind() {
				case reflect.Array, reflect.Slice:
					// Compare arrays
					if !compareListEqualsWithoutOrder(e.([]interface{}), a.([]interface{})) {
						return false
					}
				default:
					fmt.Printf("Map comparison error: Expected type is Array/Slice, actual is %s.\n", reflect.TypeOf(a).Kind())
					return false
				}
			case reflect.Map:
				switch reflect.TypeOf(a).Kind() {
				case reflect.Map:
					// Compare maps
					if !compareMapEquals(e.(map[interface{}]interface{}), a.(map[interface{}]interface{})) {
						return false
					}
				default:
					fmt.Printf("Map comparison error: Expected type is Map, actual is %s.\n", reflect.TypeOf(a).Kind())
					return false
				}
			default:
				if fmt.Sprint(a) != fmt.Sprint(e) {
					fmt.Printf("Map comparison error: Expected != Actual (%s!=%s)\n", fmt.Sprint(a), fmt.Sprint(e))
					return false
				}
			}
		}
	}
	return true
}

func compareListEqualsWithoutOrder(expected []interface{}, actual []interface{}) bool {
	// This is a little weird, but there isn't a good solution to either of these problems:
	// 		1. Comparison of types in Go. No deep equals which actually works properly. Needs to be done manually.
	// 		2. In place deletion in a loop.
	// So to do in place deletion in a loop we can do the following:
	// 		1. Loop from back to wrong (don't need to worry about deleted indices that way.
	//		2. Create a new slice with the index removed when we fix the item we want to delete.
	// To do an orderless copy, a copy of the expected result is created. Results are removed as they are found. This stops
	// the following from returning equal [1 2 2 2] and [1 1 1 2]
	expectedCopy := make([]interface{}, len(expected))
	copy(expectedCopy, expected)
	for _, a := range actual {
		found := false
		if a == nil {
			for i := len(expectedCopy) - 1; i >= 0; i-- {
				if expectedCopy[i] == nil {
					expectedCopy = append(expectedCopy[:i], expectedCopy[i+1:]...)
					found = true
					break
				}
			}
		} else {
			switch reflect.TypeOf(a).Kind() {
			case reflect.Array, reflect.Slice:
				for i := len(expectedCopy) - 1; i >= 0; i-- {
					if expectedCopy[i] != nil {
						switch reflect.TypeOf(expectedCopy[i]).Kind() {
						case reflect.Array, reflect.Slice:
							if compareListEqualsWithoutOrder(expectedCopy[i].([]interface{}), a.([]interface{})) {
								expectedCopy = append(expectedCopy[:i], expectedCopy[i+1:]...)
								found = true
							}
						}
						if found {
							break
						}
					}
				}
			case reflect.Map:
				for i := len(expectedCopy) - 1; i >= 0; i-- {
					if expectedCopy[i] != nil {
						switch reflect.TypeOf(expectedCopy[i]).Kind() {
						case reflect.Map:
							if compareMapEquals(expectedCopy[i].(map[interface{}]interface{}), a.(map[interface{}]interface{})) {
								expectedCopy = append(expectedCopy[:i], expectedCopy[i+1:]...)
								found = true
							}
						}
						if found {
							break
						}
					}
				}
			default:
				for i := len(expectedCopy) - 1; i >= 0; i-- {
					if fmt.Sprint(a) == fmt.Sprint(expectedCopy[i]) {
						expectedCopy = append(expectedCopy[:i], expectedCopy[i+1:]...)
						found = true
						break
					}
				}
			}
		}
		if !found {
			fmt.Printf("Failed to find %v in %v\n", a, expected)
			return false
		}
	}
	return true
}

func compareListEqualsWithOf(expected []interface{}, actual []interface{}) bool {
	// When comparing with "of", we expect cases like [1 2] (expected) and [1 1 1 2] (actual) , or
	// [1 1 1 2] (expected) and [1 2] (actual) to return equal.
	for _, a := range actual {
		found := false
		if a == nil {
			for i := len(expected) - 1; i >= 0; i-- {
				if expected[i] == nil {
					found = true
					break
				}
			}
		} else {
			switch reflect.TypeOf(a).Kind() {
			case reflect.Array, reflect.Slice:
				for i := len(expected) - 1; i >= 0; i-- {
					if expected[i] != nil {
						switch reflect.TypeOf(expected[i]).Kind() {
						case reflect.Array, reflect.Slice:
							if compareListEqualsWithoutOrder(expected[i].([]interface{}), a.([]interface{})) {
								found = true
							}
						}
						if found {
							break
						}
					}
				}
			case reflect.Map:
				for i := len(expected) - 1; i >= 0; i-- {
					if expected[i] != nil {
						switch reflect.TypeOf(expected[i]).Kind() {
						case reflect.Map:
							if compareMapEquals(expected[i].(map[interface{}]interface{}), a.(map[interface{}]interface{})) {
								found = true
							}
						}
						if found {
							break
						}
					}
				}
			default:
				for i := len(expected) - 1; i >= 0; i-- {
					if fmt.Sprint(a) == fmt.Sprint(expected[i]) {
						found = true
						break
					}
				}
			}
		}
		if !found {
			fmt.Printf("Failed to find %v in %v\n", a, expected)
			return false
		}
	}
	return true
}

func (tg *tinkerPopGraph) theTraversalOf(arg1 *godog.DocString) error {
	traversal, err := GetTraversal(tg.scenario.Name, tg.g, tg.parameters)
	if err != nil {
		return err
	}
	tg.traversal = traversal
	return nil
}

func (tg *tinkerPopGraph) usingTheParameterDefined(name string, params string) error {
	if tg.graphName == "empty" {
		tg.reloadEmptyData()
	}
	tg.parameters[name] = parseValue(strings.Replace(params, "\\\"", "\"", -1), tg.graphName)
	return nil
}

func (tg *tinkerPopGraph) usingTheParameterOfP(paramName, pVal, stringVal string) error {
	predicate := reflect.ValueOf(gremlingo.P).MethodByName(strings.Title(pVal)).Interface().(func(...interface{}) gremlingo.Predicate)
	values := parseValue(stringVal, tg.graphName)
	switch reflect.TypeOf(values).Kind() {
	case reflect.Array, reflect.Slice:
		tg.parameters[paramName] = predicate(values.([]interface{})...)
	default:
		tg.parameters[paramName] = predicate(values)
	}
	return nil
}

var tg = &tinkerPopGraph{
	NewCucumberWorld(),
	sync.Mutex{},
}

func InitializeTestSuite(ctx *godog.TestSuiteContext) {
	ctx.BeforeSuite(func() {
		tg.loadAllDataGraph()
	})
	ctx.AfterSuite(func() {
		err := tg.closeAllDataGraphConnection()
		if err != nil {
			return
		}
	})
}

func InitializeScenario(ctx *godog.ScenarioContext) {
	ctx.Before(func(ctx context.Context, sc *godog.Scenario) (context.Context, error) {
		tg.scenario = sc
		// Add tg.recreateAllDataGraphConnection() here and tg.closeAllDataGraphConnection() in an After scenario
		// hook if necessary to isolate failing tests that closes the shared connection.
		tg.Lock()
		return ctx, nil
	})

	ctx.After(func(ctx context.Context, sc *godog.Scenario, err error) (context.Context, error) {
		tg.Unlock()
		return ctx, nil
	})

	ctx.Step(`^an unsupported test$`, tg.anUnsupportedTest)
	ctx.Step(`^iterated next$`, tg.iteratedNext)
	ctx.Step(`^iterated to list$`, tg.iteratedToList)
	ctx.Step(`^nothing should happen because$`, tg.nothingShouldHappenBecause)
	ctx.Step(`^the (.+) graph$`, tg.chooseGraph)
	ctx.Step(`^the graph initializer of$`, tg.theGraphInitializerOf)
	ctx.Step(`^the graph should return (\d+) for count of "(.+)"$`, tg.theGraphShouldReturnForCountOf)
	ctx.Step(`^the result should be empty$`, tg.theResultShouldBeEmpty)
	ctx.Step(`^the result should be (o\w+)$`, tg.theResultShouldBe)
	ctx.Step(`^the result should be (u\w+)$`, tg.theResultShouldBe)
	ctx.Step(`^the result should have a count of (\d+)$`, tg.theResultShouldHaveACountOf)
	ctx.Step(`^the traversal of$`, tg.theTraversalOf)
	ctx.Step(`^using the parameter (.+) defined as "(.+)"$`, tg.usingTheParameterDefined)
	ctx.Step(`^using the parameter (.+) of P\.(.+)\("(.+)"\)$`, tg.usingTheParameterOfP)
}

func skipTestsIfNotEnabled(t *testing.T, testSuiteName string, testSuiteEnabled bool) {
	if !testSuiteEnabled {
		t.Skip(fmt.Sprintf("Skipping %s because %s tests are not enabled.", t.Name(), testSuiteName))
	}
}

func getEnvOrDefaultBool(key string, defaultValue bool) bool {
	value := getEnvOrDefaultString(key, "")
	if len(value) != 0 {
		boolValue, err := strconv.ParseBool(value)
		if err == nil {
			return boolValue
		}
	}
	return defaultValue
}

func TestCucumberFeatures(t *testing.T) {
	skipTestsIfNotEnabled(t, "cucumber godog tests",
		getEnvOrDefaultBool("RUN_INTEGRATION_WITH_ALIAS_TESTS", true))
	suite := godog.TestSuite{
		TestSuiteInitializer: InitializeTestSuite,
		ScenarioInitializer:  InitializeScenario,
		Options: &godog.Options{
			Format:   "pretty",
			Paths:    []string{getEnvOrDefaultString("CUCUMBER_FEATURE_FOLDER", "../../../gremlin-test/features")},
			TestingT: t, // Testing instance that will run subtests.
		},
	}

	if suite.Run() != 0 {
		t.Fatal("non-zero status returned, failed to run feature tests")
	}
}
