// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package templates

import (
	"fmt"
	"reflect"
)

func dictMerge(base map[string]any, arg any) bool {
	if arg == nil {
		return true
	}
	rv := reflect.ValueOf(arg)
	if rv.Kind() == reflect.Map {
		for _, k := range rv.MapKeys() {
			base[k.String()] = rv.MapIndex(k).Interface()
		}
		return true
	}
	return false
}

// dict is a helper function for creating a map[string]any from a list of key-value pairs.
// If the key is dot ".", the value is merged into the base map, just like Golang template's dot syntax: dot means current
// The dot syntax is highly discouraged because it might cause unclear key conflicts. It's always good to use explicit keys.
func dict(args ...any) (map[string]any, error) {
	if len(args)%2 != 0 {
		return nil, fmt.Errorf("invalid dict constructor syntax: must have key-value pairs")
	}
	m := make(map[string]any, len(args)/2)
	for i := 0; i < len(args); i += 2 {
		key, ok := args[i].(string)
		if !ok {
			return nil, fmt.Errorf("invalid dict constructor syntax: unable to merge args[%d]", i)
		}
		if key == "." {
			if ok = dictMerge(m, args[i+1]); !ok {
				return nil, fmt.Errorf("invalid dict constructor syntax: dot arg[%d] must be followed by a dict", i)
			}
		} else {
			m[key] = args[i+1]
		}
	}
	return m, nil
}