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

package container

import (
	"LAPP_ACURA_MOM_BACKEND/global"
	"errors"
	"fmt"
	"sync"
)

// 默认会话管理器
// @Implement LAPP_ACURA_MOM_BACKEND/container/InformationManager
type DefaultSessionManager struct {
	// 组件信息管理器
	informationManager InformationManager
	// 事务句柄工厂
	transactionHandlerFactory TransactionHandlerFactory
	// 同步锁
	locker sync.RWMutex
	// 用户会话映射: map[用户标识]会话
	user2SessionMapping map[string]*Session
	// 会话映射: map[会话标识]会话
	sessionMapping map[string]*Session
}

// 创建默认会话管理器
// 参数:
// 1.组件信息管理器
// 2.事务句柄工厂
// 返回值:
// 1.默认会话管理器
// 异常:
// 1.组件信息管理器不能为空
// 2.事务句柄工厂不能为空
func NewDefaultSessionManager(informationManager InformationManager, transactionHandlerFactory TransactionHandlerFactory) *DefaultSessionManager {
	if informationManager == nil {
		panic(fmt.Sprintf("组件信息管理器不能为空!"))
	}
	if transactionHandlerFactory == nil {
		panic(fmt.Sprintf("事务句柄工厂不能为空!"))
	}
	return &DefaultSessionManager{informationManager, transactionHandlerFactory, sync.RWMutex{}, make(map[string]*Session, 100), make(map[string]*Session, 100)}
}

// @Reference LAPP_ACURA_MOM_BACKEND/container/SessionManager.ClearSession
func (manager *DefaultSessionManager) ClearSession(sessionId string) {
	manager.locker.Lock()
	defer manager.locker.Unlock()
	session, ok := manager.sessionMapping[sessionId]
	if !ok {
		return
	}
	delete(manager.sessionMapping, sessionId)
	delete(manager.user2SessionMapping, session.user.UserId)
}

// @Reference LAPP_ACURA_MOM_BACKEND/container/SessionManager.GetSession
func (manager *DefaultSessionManager) GetSession(sessionId string, user *global.User) (*Session, error) {
	if sessionId == "" {
		return nil, errors.New(fmt.Sprintf("会话标识不能为空!"))
	}
	if user == nil {
		return nil, errors.New(fmt.Sprintf("用户信息不能为空!"))
	}
	userId := user.UserId
	if userId == "" {
		return nil, errors.New(fmt.Sprintf("用户标识不能为空!"))
	}
	manager.locker.Lock()
	defer manager.locker.Unlock()
	session, ok := manager.sessionMapping[sessionId]
	if !ok {
		existingSession, ok := manager.user2SessionMapping[userId]
		if ok {
			delete(manager.user2SessionMapping, userId)
			delete(manager.sessionMapping, existingSession.SessionId())
		}
		sessionContext, err := NewSessionContext(user, manager.transactionHandlerFactory)
		if err != nil {
			return nil, err
		}
		handlerManager, err := manager.buildHandlerManager(sessionContext)
		if err != nil {
			return nil, err
		}
		session, err = NewSession(sessionContext, sessionId, handlerManager)
		if err != nil {
			return nil, err
		}
		manager.user2SessionMapping[userId] = session
		manager.sessionMapping[sessionId] = session
	}
	return session, nil
}

// 创建组件句柄管理器
// 参数:
// 1.会话上下文
// 返回值:
// 1.组件句柄管理器
// 2.错误
func (manager *DefaultSessionManager) buildHandlerManager(sessionContext *SessionContext) (*HandlerManager, error) {
	items := manager.informationManager.Items()
	handlerMapping := make(map[Interface]ComponentHandler, len(items))
	for _, component := range items {
		handler, err := component.BuildHandler(sessionContext)
		if err != nil {
			return nil, err
		}
		handlerMapping[component.Interface()] = handler
	}
	return NewHandlerManager(handlerMapping)
}
