package notify_util

import (
	"fmt"

	"Framework/goroutineMgr"
	"goutil/logUtil"
	"goutil/syncUtil"
)

const (
	deathLockTime = 0
)

// notifyCenter
// @description: 玩家信息务逻辑类
type notifyCenter struct {
	// key:初始化成功的标志名称   val:占位符
	registerMap map[string]func()
	mutex       *syncUtil.RWLocker
}

// newNotifyCenter
// @description: 构造对象
// parameter:
// return:
//		@*notifyCenter:
func newNotifyCenter() *notifyCenter {
	return &notifyCenter{
		registerMap: make(map[string]func()),
		mutex:       syncUtil.NewRWLocker(),
	}
}

// register
// @description: 注册需要被通知的对象
// parameter:
//		@receiver nc:
//		@chanName:唯一标识
//		@cf:回调方法
// return:
func (nc *notifyCenter) register(chanName string, cf func()) {
	if isOk, prevStack, currStack := nc.mutex.Lock(deathLockTime); isOk == false {
		//记日志
		errMsg := fmt.Sprintf("Lock timeout! \n上一个堆栈:\n%s  \n当前堆栈:\n%s", prevStack, currStack)
		panic(errMsg)
	}
	defer nc.mutex.Unlock()
	if _, exists := nc.registerMap[chanName]; exists {
		panic(fmt.Errorf("registerMap.Register-%s已经存在，请检查", chanName))
	}

	nc.registerMap[chanName] = cf
}

// @description: 取消启动成功通知注册
// parameter:
//		@receiver nc:
//		@name:唯一标识
// return:
func (nc *notifyCenter) unregister(name string) {
	if isOk, prevStack, currStack := nc.mutex.Lock(deathLockTime); isOk == false {
		//记日志
		errMsg := fmt.Sprintf("Lock timeout! \n上一个堆栈:\n%s  \n当前堆栈:\n%s", prevStack, currStack)
		panic(errMsg)
	}
	defer nc.mutex.Unlock()

	delete(nc.registerMap, name)
}

// notify
// @description: 通知所有已注册的对象
// parameter:
//		@receiver nc:
// return:
func (nc *notifyCenter) notify() {
	// 处理goroutine数量
	goroutineName := "notifyCenter.Notify"
	goroutineMgr.MonitorZero(goroutineName)
	defer goroutineMgr.ReleaseMonitor(goroutineName)

	if isOk, prevStack, currStack := nc.mutex.RLock(deathLockTime); isOk == false {
		//记日志
		errMsg := fmt.Sprintf("Lock timeout! \n上一个堆栈:\n%s  \n当前堆栈:\n%s", prevStack, currStack)
		panic(errMsg)
	}
	defer nc.mutex.RUnlock()

	for name, cf := range nc.registerMap {
		cf()
		msg := fmt.Sprintf("通知:%s初始化成功", name)
		logUtil.DebugLog(msg)
	}
}

// notify2
// @description: 通知所有已注册的对象，该方法会在捕获第一个err的时候停止后续的通知。多用于系统启动的判定
// parameter:
//		@receiver nc:
// return:
//		@error:
func (nc *notifyCenter) notify2() (err error) {
	// 处理goroutine数量
	goroutineName := "notifyCenter.Notify"
	goroutineMgr.MonitorZero(goroutineName)
	defer goroutineMgr.ReleaseMonitor(goroutineName)

	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("notify2 err:%s", r)
			logUtil.ErrorLog(err.Error())
		}
	}()

	if isOk, prevStack, currStack := nc.mutex.RLock(deathLockTime); isOk == false {
		//记日志
		errMsg := fmt.Sprintf("Lock timeout! \n上一个堆栈:\n%s  \n当前堆栈:\n%s", prevStack, currStack)
		panic(errMsg)
	}
	defer nc.mutex.RUnlock()

	for name, cf := range nc.registerMap {
		cf()
		msg := fmt.Sprintf("通知:%s初始化成功", name)
		logUtil.DebugLog(msg)
	}

	return
}
