package player

import (
	cconst "github.com/mhaya/const"
	cstring "github.com/mhaya/extend/string"
	cfacade "github.com/mhaya/facade"
	"github.com/mhaya/game/game_cluster/internal/event"
	"github.com/mhaya/game/game_cluster/internal/mdb/models"
	"github.com/mhaya/game/game_cluster/nodes/game/module/online"
	clog "github.com/mhaya/logger"
	"github.com/mhaya/net/parser/pomelo"
	"time"
)

type (
	// ActorPlayers 玩家总管理actor
	ActorPlayers struct {
		pomelo.ActorBase
		childExitTime time.Duration
	}
)

func (p *ActorPlayers) AliasID() string {
	return "player"
}

func (p *ActorPlayers) OnInit() {
	p.childExitTime = time.Minute * 30
	// 注册角色登陆事件
	p.Event().Register(event.PlayerLoginKey, p.onLoginEvent)
	p.Event().Register(event.PlayerLogoutKey, p.onLogoutEvent)
	p.Event().Register(event.PlayerCreateKey, p.onPlayerCreateEvent)
	p.Remote().Register("checkChild", p.checkChild)

	p.Timer().AddOnce(20*time.Second, p.loadServer)
}

func (p *ActorPlayers) loadServer() {
	//初始节点
	models.SetServerRecord(p.App().NodeId(), 0)
}

func (p *ActorPlayers) OnFindChild(msg *cfacade.Message) (cfacade.IActor, bool) {
	// 动态创建 player child actor
	childID := msg.TargetPath().ChildID
	childActor, err := p.Child().Create(childID, &actorPlayer{
		isOnline: false,
	})

	if err != nil {
		return nil, false
	}

	return childActor, true
}

// cron
func (p *ActorPlayers) everySecondTimer() {
	p.Call(p.PathString(), "checkChild", nil)
}

func (p *ActorPlayers) checkChild() {
	// 扫描所有玩家actor
	p.Child().Each(func(iActor cfacade.IActor) {
		child, ok := iActor.(*actorPlayer)
		if !ok {
			return
		}

		if child.isOnline {
			return
		}

		// 玩家下线，并且超过childExitTime时间没有收发消息，则退出actor
		deadline := time.Now().Add(-p.childExitTime).Unix()
		if child.LastAt() < deadline {
			child.Exit() //actor退出
		}
	})
}

// onLoginEvent 玩家登陆事件处理
func (p *ActorPlayers) onLoginEvent(e cfacade.IEventData) {
	evt, ok := e.(*event.PlayerLogin)
	if ok == false {
		return
	}

	node, ok := cstring.SplitIndex(evt.TargetPath, cconst.DOT, 0)
	if ok && len(node) > 0 {
		models.SetServerRecord(node, online.Count())
	}

	clog.Infof("[PlayerLoginEvent] [playerId = %v,openid = %v,TargetPath=%v,onlineCount = %v]",
		evt.PlayerId,
		evt.OpenID,
		evt.TargetPath,
		online.Count(),
	)
}

// onLoginEvent 玩家登出事件处理
func (p *ActorPlayers) onLogoutEvent(e cfacade.IEventData) {
	evt, ok := e.(*event.PlayerLogout)
	if !ok {
		return
	}

	node, ok := cstring.SplitIndex(evt.TargetPath, cconst.DOT, 0)
	if ok && len(node) > 0 {
		models.SetServerRecord(node, online.Count())
	}

	clog.Infof("[PlayerLogoutEvent] [playerId = %v,TargetPath=%v, onlineCount = %v]",
		evt.PlayerId,
		evt.TargetPath,
		online.Count(),
	)
}

// onPlayerCreateEvent 玩家创建事件
func (p *ActorPlayers) onPlayerCreateEvent(e cfacade.IEventData) {
	evt, ok := e.(*event.PlayerCreate)
	if !ok {
		return
	}

	clog.Infof("[PlayerCreateEvent] [%+v]", evt)
}

func (p *ActorPlayers) OnStop() {
	clog.Infof("onlineCount = %d", online.Count())
}
