package cypher

import (
	"fmt"

	"git.science.uu.nl/graphpolaris/query-conversion/entity"
)

/* createConstraintStatements generates the appropriate amount of constraint lines calling createConstraingBoolExpression
Parameters: constraints is a list of constraintStructs that specify the constraints of a node or relation,
name is the id of the corresponding relation/node,
isRelation is a boolean specifying if this constraint comes from a node or relation

Return: a string containing a FILTER-statement with all the constraints
*/
func createConstraintStatements(constraints *[]entity.QueryConstraintStruct, name string) *string {
	s := ""
	if len(*constraints) == 0 {
		return &s
	}

	newLineStatement := "\tWHERE"

	for _, v := range *constraints {
		s += fmt.Sprintf("%v%v \n", newLineStatement, *createConstraintBoolExpression(&v, name))
		newLineStatement = "\tAND"
	}

	return &s
}

/* createConstraintBoolExpression generates a single boolean expression,
e.g. {name}.city == "New York".

Parameters: constraint is a single constraint of a node or relation,
name is the id of the corresponding relation/node,
isRelation is a boolean specifying if this constraint comes from a node or relation, that changes the structure of the expression

Return: a string containing an boolean expression of a single constraint
*/
func createConstraintBoolExpression(constraint *entity.QueryConstraintStruct, name string) *string {
	var (
		match string
		value string
		line  string
		neq   string
	)

	// Constraint datatypes back end
	// string		  MatchTypes: EQ/NEQ/contains/excludes
	// int     MatchTypes: EQ/NEQ/GT/LT/GET/LET
	// bool       MatchTypes: EQ/NEQ

	neq = ""

	switch constraint.DataType {
	case "string":
		value = fmt.Sprintf("\"%s\"", constraint.Value)
		switch constraint.MatchType {
		case "NEQ":
			match = "<>"
		case "contains":
			match = "CONTAINS"
			value = fmt.Sprintf("\"%%%s%%\"", constraint.Value)
		case "excludes":
			match = "CONTAINS"
			value = fmt.Sprintf("\"%%%s%%\"", constraint.Value)
			neq = "NOT"
		default: //EQ
			match = "="
		}
	case "int":
		value = constraint.Value
		switch constraint.MatchType {
		case "NEQ":
			match = "<>"
		case "GT":
			match = ">"
		case "LT":
			match = "<"
		case "GET":
			match = ">="
		case "LET":
			match = "<="
		default: //EQ
			match = "="
		}
	default: /*bool*/
		value = constraint.Value
		switch constraint.MatchType {
		case "NEQ":
			match = "<>"
		default: //EQ
			match = "="
		}
	}

	line = fmt.Sprintf("%s %s.%s %s %s", neq, name, constraint.Attribute, match, value)

	return &line
}