// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.

// global-context.go
package expr

import (
	"path/filepath"
	"strings"
)

var globalCtx *SimpleStore

func ImportInContext(name string) (exists bool) {
	var mod *builtinModule
	if mod, exists = builtinModuleRegister[name]; exists {
		mod.importFunc(globalCtx)
		mod.imported = true
	}
	return
}

func ImportInContextByGlobPattern(pattern string) (count int, err error) {
	var matched bool
	for name, mod := range builtinModuleRegister {
		if matched, err = filepath.Match(pattern, name); err == nil {
			if matched {
				count++
				mod.importFunc(globalCtx)
				mod.imported = true
			}
		} else {
			break
		}
	}
	return
}

func GetVar(ctx ExprContext, name string) (value any, exists bool) {
	if value, exists = ctx.GetVar(name); !exists {
		value, exists = globalCtx.GetVar(name)
	}
	return
}

func GetLocalFuncInfo(ctx ExprContext, name string) (item ExprFunc, exists bool) {
	var v any
	if len(name) > 0 {
		if v, exists = ctx.GetVar(name); exists && isFunctor(v) {
			f, _ := v.(Functor)
			item = f.GetFunc()
		} else {
			item, exists = ctx.GetFuncInfo(name)
		}
	}
	return
}
func GetFuncInfo(ctx ExprContext, name string) (item ExprFunc, exists bool, ownerCtx ExprContext) {
	if len(name) > 0 {
		if item, exists = GetLocalFuncInfo(ctx, name); exists {
			ownerCtx = ctx
		} else if item, exists = globalCtx.GetFuncInfo(name); exists {
			ownerCtx = globalCtx
		}
	}
	return
}

func GlobalCtrlSet(name string, newValue any) (currentValue any) {
	if !strings.HasPrefix(name, "_") {
		name = "_" + name
	}
	currentValue, _ = globalCtx.GetVar(name)

	globalCtx.SetVar(name, newValue)
	return currentValue
}

func GlobalCtrlGet(name string) (currentValue any) {
	if !strings.HasPrefix(name, "_") {
		name = "_" + name
	}
	currentValue, _ = globalCtx.GetVar(name)
	return currentValue
}

func CtrlEnable(ctx ExprContext, name string) (currentStatus bool) {
	if !strings.HasPrefix(name, "_") {
		name = "_" + name
	}
	if v, exists := ctx.GetVar(name); exists && IsBool(v) {
		currentStatus, _ = v.(bool)
	}

	ctx.SetVar(name, true)
	return currentStatus
}

func CtrlDisable(ctx ExprContext, name string) (currentStatus bool) {
	if !strings.HasPrefix(name, "_") {
		name = "_" + name
	}
	if v, exists := ctx.GetVar(name); exists && IsBool(v) {
		currentStatus, _ = v.(bool)
	}

	ctx.SetVar(name, false)
	return currentStatus
}

func CtrlIsEnabled(ctx ExprContext, name string) (status bool) {
	var v any
	var exists bool

	if !strings.HasPrefix(name, "_") {
		name = "_" + name
	}

	if v, exists = ctx.GetVar(name); !exists {
		v, exists = globalCtx.GetVar(name)
	}

	if exists {
		if b, ok := v.(bool); ok {
			status = b
		}
	}
	return
}

func getControlString(name string) (s string, exists bool) {
	var v any
	if v, exists = globalCtx.GetVar(name); exists {
		s, exists = v.(string)
	}
	return
}

func init() {
	globalCtx = NewSimpleStore()
	initDefaultVars(globalCtx)
	ImportBuiltinsFuncs(globalCtx)
}