package parser

import (
	"io/fs"

	"github.com/hashicorp/hcl/v2/ext/tryfunc"
	ctyyaml "github.com/zclconf/go-cty-yaml"
	"github.com/zclconf/go-cty/cty"
	"github.com/zclconf/go-cty/cty/function"
	"github.com/zclconf/go-cty/cty/function/stdlib"

	funcs2 "github.com/aquasecurity/trivy/pkg/iac/scanners/terraform/parser/funcs"
)

// Functions returns the set of functions that should be used to when evaluating
// expressions in the receiving scope.
func Functions(target fs.FS, baseDir string) map[string]function.Function {
	return map[string]function.Function{
		"abs":              stdlib.AbsoluteFunc,
		"abspath":          funcs2.AbsPathFunc,
		"basename":         funcs2.BasenameFunc,
		"base64decode":     funcs2.Base64DecodeFunc,
		"base64encode":     funcs2.Base64EncodeFunc,
		"base64gzip":       funcs2.Base64GzipFunc,
		"base64sha256":     funcs2.Base64Sha256Func,
		"base64sha512":     funcs2.Base64Sha512Func,
		"bcrypt":           funcs2.BcryptFunc,
		"can":              tryfunc.CanFunc,
		"ceil":             stdlib.CeilFunc,
		"chomp":            stdlib.ChompFunc,
		"cidrhost":         funcs2.CidrHostFunc,
		"cidrnetmask":      funcs2.CidrNetmaskFunc,
		"cidrsubnet":       funcs2.CidrSubnetFunc,
		"cidrsubnets":      funcs2.CidrSubnetsFunc,
		"coalesce":         funcs2.CoalesceFunc,
		"coalescelist":     stdlib.CoalesceListFunc,
		"compact":          stdlib.CompactFunc,
		"concat":           stdlib.ConcatFunc,
		"contains":         stdlib.ContainsFunc,
		"csvdecode":        stdlib.CSVDecodeFunc,
		"dirname":          funcs2.DirnameFunc,
		"distinct":         stdlib.DistinctFunc,
		"element":          stdlib.ElementFunc,
		"chunklist":        stdlib.ChunklistFunc,
		"file":             funcs2.MakeFileFunc(target, baseDir, false),
		"fileexists":       funcs2.MakeFileExistsFunc(baseDir),
		"fileset":          funcs2.MakeFileSetFunc(baseDir),
		"filebase64":       funcs2.MakeFileFunc(target, baseDir, true),
		"filebase64sha256": funcs2.MakeFileBase64Sha256Func(target, baseDir),
		"filebase64sha512": funcs2.MakeFileBase64Sha512Func(target, baseDir),
		"filemd5":          funcs2.MakeFileMd5Func(target, baseDir),
		"filesha1":         funcs2.MakeFileSha1Func(target, baseDir),
		"filesha256":       funcs2.MakeFileSha256Func(target, baseDir),
		"filesha512":       funcs2.MakeFileSha512Func(target, baseDir),
		"flatten":          stdlib.FlattenFunc,
		"floor":            stdlib.FloorFunc,
		"format":           stdlib.FormatFunc,
		"formatdate":       stdlib.FormatDateFunc,
		"formatlist":       stdlib.FormatListFunc,
		"indent":           stdlib.IndentFunc,
		"index":            funcs2.IndexFunc, // stdlib.IndexFunc is not compatible
		"join":             stdlib.JoinFunc,
		"jsondecode":       stdlib.JSONDecodeFunc,
		"jsonencode":       stdlib.JSONEncodeFunc,
		"keys":             stdlib.KeysFunc,
		"length":           funcs2.LengthFunc,
		"list":             funcs2.ListFunc,
		"log":              stdlib.LogFunc,
		"lookup":           funcs2.LookupFunc,
		"lower":            stdlib.LowerFunc,
		"map":              funcs2.MapFunc,
		"matchkeys":        funcs2.MatchkeysFunc,
		"max":              stdlib.MaxFunc,
		"md5":              funcs2.Md5Func,
		"merge":            stdlib.MergeFunc,
		"min":              stdlib.MinFunc,
		"parseint":         stdlib.ParseIntFunc,
		"pathexpand":       funcs2.PathExpandFunc,
		"pow":              stdlib.PowFunc,
		"range":            stdlib.RangeFunc,
		"regex":            stdlib.RegexFunc,
		"regexall":         stdlib.RegexAllFunc,
		"replace":          funcs2.ReplaceFunc,
		"reverse":          stdlib.ReverseListFunc,
		"rsadecrypt":       funcs2.RsaDecryptFunc,
		"setintersection":  stdlib.SetIntersectionFunc,
		"setproduct":       stdlib.SetProductFunc,
		"setsubtract":      stdlib.SetSubtractFunc,
		"setunion":         stdlib.SetUnionFunc,
		"sha1":             funcs2.Sha1Func,
		"sha256":           funcs2.Sha256Func,
		"sha512":           funcs2.Sha512Func,
		"signum":           stdlib.SignumFunc,
		"slice":            stdlib.SliceFunc,
		"sort":             stdlib.SortFunc,
		"split":            stdlib.SplitFunc,
		"strrev":           stdlib.ReverseFunc,
		"substr":           stdlib.SubstrFunc,
		"timestamp":        funcs2.TimestampFunc,
		"timeadd":          stdlib.TimeAddFunc,
		"title":            stdlib.TitleFunc,
		"tostring":         funcs2.MakeToFunc(cty.String),
		"tonumber":         funcs2.MakeToFunc(cty.Number),
		"tobool":           funcs2.MakeToFunc(cty.Bool),
		"toset":            funcs2.MakeToFunc(cty.Set(cty.DynamicPseudoType)),
		"tolist":           funcs2.MakeToFunc(cty.List(cty.DynamicPseudoType)),
		"tomap":            funcs2.MakeToFunc(cty.Map(cty.DynamicPseudoType)),
		"transpose":        funcs2.TransposeFunc,
		"trim":             stdlib.TrimFunc,
		"trimprefix":       stdlib.TrimPrefixFunc,
		"trimspace":        stdlib.TrimSpaceFunc,
		"trimsuffix":       stdlib.TrimSuffixFunc,
		"try":              tryfunc.TryFunc,
		"upper":            stdlib.UpperFunc,
		"urlencode":        funcs2.URLEncodeFunc,
		"uuid":             funcs2.UUIDFunc,
		"uuidv5":           funcs2.UUIDV5Func,
		"values":           stdlib.ValuesFunc,
		"yamldecode":       ctyyaml.YAMLDecodeFunc,
		"yamlencode":       ctyyaml.YAMLEncodeFunc,
		"zipmap":           stdlib.ZipmapFunc,
	}

}
