package gjson

import (
	glua "github.com/yuin/gopher-lua"
)

// nullMarker is a sentinel type to identify gjson.null values.
type nullMarker struct{}

// GJSON represents a gjson instance with its own configuration.
type GJSON struct {
	config *Config
	null   *glua.LUserData
}

// createNull creates the gjson.null lightuserdata for the given LState.
func createNull(L *glua.LState) *glua.LUserData {
	ud := L.NewUserData()
	ud.Value = nullMarker{}
	return ud
}

// isNull checks if a Lua value is gjson.null.
func isNull(value glua.LValue) bool {
	if ud, ok := value.(*glua.LUserData); ok {
		_, isNullMarker := ud.Value.(nullMarker)
		return isNullMarker
	}
	return false
}

// gjsonNew creates a new GJSON instance with independent configuration.
// Lua: gjson.new() -> new_instance
func gjsonNew(L *glua.LState) int {
	// Create new instance with default config
	instance := &GJSON{
		config: defaultConfig(),
	}
	instance.null = createNull(L)

	// Create instance table
	tbl := L.NewTable()

	// Register methods (bound to this instance)
	L.SetField(tbl, "encode", L.NewFunction(instance.encode))
	L.SetField(tbl, "decode", L.NewFunction(instance.decode))
	L.SetField(tbl, "encode_sparse_array", L.NewFunction(instance.cfgEncodeSparseArray))
	L.SetField(tbl, "encode_max_depth", L.NewFunction(instance.cfgEncodeMaxDepth))
	L.SetField(tbl, "decode_max_depth", L.NewFunction(instance.cfgDecodeMaxDepth))
	L.SetField(tbl, "encode_number_precision", L.NewFunction(instance.cfgEncodeNumberPrecision))
	L.SetField(tbl, "encode_keep_buffer", L.NewFunction(instance.cfgEncodeKeepBuffer))
	L.SetField(tbl, "encode_sort_keys", L.NewFunction(instance.cfgEncodeSortKeys))
	L.SetField(tbl, "new", L.NewFunction(gjsonNew))

	// Set null
	L.SetField(tbl, "null", instance.null)

	// Set metadata
	L.SetField(tbl, "_NAME", glua.LString(ModuleName))
	L.SetField(tbl, "_VERSION", glua.LString(Version))

	L.Push(tbl)
	return 1
}
