package notify_util

import (
	"fmt"

	"goutil/syncUtil"
)

var (
	// key:初始化成功的标志名称   val:占位符
	registerNC = make(map[string]*notifyCenter)
	mutex      = syncUtil.NewRWLocker()
)

// getItemOrAdd
// @description: 获取注册的通知对象
// parameter:
//		@chanGroup:
// return:
//		@*notifyCenter:
func getItemOrAdd(chanGroup string) *notifyCenter {
	if isOk, prevStack, currStack := mutex.Lock(deathLockTime); isOk == false {
		//记日志
		errMsg := fmt.Sprintf("Lock timeout! \n上一个堆栈:\n%s  \n当前堆栈:\n%s", prevStack, currStack)
		panic(errMsg)
	}
	defer mutex.Unlock()

	nc, exists := registerNC[chanGroup]
	if exists {
		return nc
	}

	nc = newNotifyCenter()
	registerNC[chanGroup] = nc

	return nc
}

// Register
// @description: 注册需要被通知的对象
// parameter:
//		@chanGroup:通知的分组标识
//		@chanName:唯一标识
//		@cf:回调方法
// return:
func Register(chanGroup string, chanName string, cf func()) {
	nc := getItemOrAdd(chanGroup)
	nc.register(chanName, cf)
}

// Unregister
// @description: 取消启动成功通知注册
// parameter:
//		@chanGroup:分组标识
//		@name:唯一标识
// return:
func Unregister(chanGroup string, name string) {
	nc := getItemOrAdd(chanGroup)
	nc.unregister(name)
}

// Notify
// @description: 通知分组所有已注册的对象
// parameter:
//		@chanGroup:分组标识
// return:
func Notify(chanGroup string) {
	nc := getItemOrAdd(chanGroup)
	nc.notify()
}

// Notify2
// @description: 通知所有已注册的对象，该方法会在捕获第一个err的时候停止后续的通知。多用于系统启动的判定
// parameter:
//		@chanGroup:分组标识
// return:
//		@err:
func Notify2(chanGroup string) (err error) {
	nc := getItemOrAdd(chanGroup)
	err = nc.notify2()
	return
}
