// ************************************
// @package: handleMgr
// @description: 全局操作接口管理
// @author:
// @revision history:
// @create date: 2022-02-21 15:53:59
// ************************************

package handleMgr

import (
	"fmt"
	"Framework/goroutineMgr"
	"goutil/logUtil"
	"runtime/debug"
	"time"
)

var (
	handleData = make(map[string]*HandleObj)
)

// RegisterNewModule
// @description: 注册调用方法
// parameter:
//		@logicalId:逻辑实例Id-同一串行错误类的唯一标识
//		@structObject:模块对象
//		@monitorTime:监控日志超时时间,传入0是用默认值100
// return:
func RegisterNewModule(logicalId string, structObject interface{}, monitorTime int64) {
	// 注册模块,开启线程
	_, isExists := handleData[logicalId]
	if isExists == false {
		newHandleObj := NewHandleObj(logicalId)
		handleData[logicalId] = newHandleObj

		// 设置监控默认值
		if monitorTime == 0 {
			monitorTime = 100
		}

		// 开启监控-channel
		go func() {
			registerName := fmt.Sprintf("handleMgr.RegisterNewModule.logicalId=%s", logicalId)
			goroutineMgr.MonitorZero(registerName)
			defer goroutineMgr.ReleaseMonitor(registerName)
			defer logErrorRecover()

			ret := 0
			for {
				select {
				case c := <-newHandleObj.HandleChannel:
					start := time.Now().UnixMilli()
					responseObject := CallFunction(c)
					end := time.Now().UnixMilli()

					if c.IsHaveResult == true {
						c.ResultChan <- responseObject
					}
					if end-start > monitorTime {
						message := fmt.Sprintf("方法执行时间超长，logicalId:%s,moduleName：%s,MethodName:%s,消耗时间过程,总耗时:%d,需要检查代码！！！！！", logicalId, c.ModuleName, c.MethodName, end-start)
						logUtil.ErrorLog(message)
					}

					ret++
					if ret == 100 {
						num := len(newHandleObj.HandleChannel)
						if num > 500 {
							message := fmt.Sprintf("时间戳:%d,channel监控,内部待执行操作过多，logicalId:%s,当前待执行数量:%d,需要检查代码！！！！！", time.Now().UnixMilli(), logicalId, num)
							logUtil.ErrorLog(message)
						}
					}
				default:
					// 如果找不到数据则休眠5ms
					time.Sleep(5 * time.Millisecond)
				}
			}
		}()
	}

	// 注册对象
	RegisterFunction(structObject)
}

// Done
// @description: 执行访问
// parameter:
//		@logicalId:逻辑实例Id-同一串行错误类的唯一标识
//		@moduleName:模块名
//		@funcName:执行方法名称
//		@parameter:方法参数
//		@isHaveResult:是否处理返回值
// return:
//		@data:返还对象
//		@code:错误码-0未无错误
//		@message:错误说明-空字符串为无错误
func Done(logicalId string, moduleName string, funcName string, parameter []interface{}, isHaveResult bool) (data interface{}, code int, message string) {
	responseObj := NewRequestObject(moduleName, funcName, parameter, isHaveResult)
	handleObj, isExists := handleData[logicalId]
	if isExists == false {
		message := fmt.Sprintf("未注册模块，moduleName：%s", moduleName)
		logUtil.ErrorLog(message)
		return nil, -1, message
	}
	handleObj.HandleChannel <- responseObj
	if responseObj.IsHaveResult == false {
		return nil, 0, ""
	}

	for {
		select {
		case responseObject := <-responseObj.ResultChan:
			// 处理返回值
			return responseObject.Data, 0, responseObject.Message
		default:
			// 如果找不到数据则休眠5ms
			time.Sleep(5 * time.Millisecond)
		}
	}
}

// logErrorRecover
// @description: 打印日志
// parameter:
// return:
func logErrorRecover() {
	if err := recover(); err != nil {
		msg := fmt.Sprintf("err msg:%s  stack:%s", err, debug.Stack())
		logUtil.ErrorLog(msg)
	}
}
