// Copyright (c) Shenyang Leading Edge Intelligent Technology Co., Ltd. All rights reserved.

package container

import (
	"errors"
	"fmt"
)

// 服务组件信息
// @Implement LAPP_ACURA_MOM_BACKEND/container/ComponentInformation
type ServiceInformation struct {
	// @Inherit LAPP_ACURA_MOM_BACKEND/container/ElementInformation
	ElementInformation
	// 方法信息映射: map[方法名]方法信息
	methodMapping map[string]*ServiceMethodInformation
}

// 创建服务组件信息
// 参数
// 1.工厂方法
// 返回值:
// 1.服务组件信息
// 2.错误
func NewServiceInformation(factory interface{}) *ServiceInformation {

	valueOfFactory, interfaceType := parseFactory(factory)
	return &ServiceInformation{ElementInformation{valueOfFactory, interfaceType}, make(map[string]*ServiceMethodInformation, 10)}
}

// @Reference LAPP_ACURA_MOM_BACKEND/container/ComponentInformation.BuildHandler
// @Override LAPP_ACURA_MOM_BACKEND/container/ElementInformation.BuildHandler
func (info *ServiceInformation) BuildHandler(sessionContext *SessionContext) (ComponentHandler, error) {

	if sessionContext == nil {
		return nil, errors.New(fmt.Sprintf("会话上下文不能为空!"))
	}
	instance, err := info.factory.Create(sessionContext)
	if err != nil {
		return nil, err
	}
	methodHandlers := make(map[string]*ServiceMethodHandler, len(info.methodMapping))
	for methodName, methodInformation := range info.methodMapping {
		methodHandler, err := methodInformation.BuildHandler(sessionContext, instance)
		if err != nil {
			return nil, err
		}
		methodHandlers[methodName] = methodHandler
	}
	serviceHandler, err := NewServiceHandler(instance, methodHandlers)
	if err != nil {
		return nil, err
	}
	return serviceHandler, nil
}

// 注册服务方法
// 参数
// 1.方法
// 返回值:
// 1.注册的服务方法信息
// 2.错误
// 异常
// 1.方法名不能为空
// 2.方法已经注册
// 3.找不到方法
// 4.方法类型不能为空
// 5.返回值数量错误
// 6.最后一个返回值类型错误
func (info *ServiceInformation) RegisterMethod(methodName string) *ServiceMethodInformation {

	if methodName == "" {
		panic(fmt.Sprintf("方法名不能为空!"))
	}
	if _, ok := info.methodMapping[methodName]; ok {
		panic(fmt.Sprintf("方法%s已经注册!", methodName))
	}
	method, ok := info.interfaceType.MethodByName(methodName)
	if !ok {
		panic(fmt.Sprintf("找不到方法%s!", methodName))
	}
	methodInformation := NewServiceMethodInformation(&method)
	info.methodMapping[methodName] = methodInformation
	return methodInformation
}

// 获取指定名称的服务方法信息
// 参数:
// 1.方法名
// 返回值:
// 1.方法信息
func (info *ServiceInformation) Method(methodName string) *ServiceMethodInformation {

	method, ok := info.methodMapping[methodName]
	if ok {
		return method
	}
	return nil
}

// 获取注册的服务方法信息列表
// 返回值:
// 1.服务方法信息列表
func (info *ServiceInformation) Methods() []*ServiceMethodInformation {

	methods := make([]*ServiceMethodInformation, len(info.methodMapping))
	index := 0
	for _, method := range info.methodMapping {
		methods[index] = method
		index++
	}
	return methods
}
