package server

import (
	"fmt"
	"game/common/proto/pb"
	"game/server/client/config"
	"github.com/fox/fox/log"
	"github.com/fox/fox/processor"
	"github.com/fox/fox/ws"
	"github.com/fox/fox/xrand"
	"github.com/golang/protobuf/proto"
	"time"
)

var Clients []*ClientService

type ClientService struct {
	client          *ws.Client
	processor       *processor.Processor
	userId          int64
	username        string
	password        string
	lastServiceName string // 最近使用的服务的节点
}

func Init() {
	for i := 0; i < config.Command.ServiceNum; i++ {
		sid := config.Command.ServiceId + i
		if srv := newClientService(sid); srv != nil {
			Clients = append(Clients, srv)
		}
	}
}

func Stop() {
	for _, s := range Clients {
		s.client.NotifyStop()
	}
	for _, s := range Clients {
		s.client.WaitStop()
	}
}

func newClientService(serviceId int) *ClientService {
	var err error
	s := new(ClientService)

	s.username = fmt.Sprintf("test%04d", serviceId)
	s.password = "123456"
	size := len(config.ClientCfg.Address)
	addr := config.ClientCfg.Address[xrand.RandN(size)]
	wsAddr := fmt.Sprintf("ws://%v", addr)
	if s.client, err = ws.NewClient(wsAddr, s); err != nil {
		log.FatalF("connect url:%v err:%v", wsAddr, err.Error())
		return nil
	}
	s.processor = processor.NewProcessor()
	s.initProcessor()
	s.OnInit()
	return s
}

func (s *ClientService) loopLoginHour() {
	s.reqLogin()
	//time.AfterFunc(5*time.Minute, s.loopLoginHour)
}

func (s *ClientService) OnInit() {
	s.client.Start()
	log.Debug("onInit")
	time.Sleep(100 * time.Millisecond)
	s.loopLoginHour()
}

func (s *ClientService) CanStop() bool {
	return true
}

// 处理其它服发送过来的消息
func (s *ClientService) OnMessage(data []byte) error {
	var cMsg = &pb.ClientMsg{}
	var err error
	if err = proto.Unmarshal(data, cMsg); err != nil {
		log.Error(err.Error())
		return err
	}
	if req, err := s.processor.Unmarshal(cMsg.MsgId, cMsg.Data); err == nil {
		err = s.processor.Dispatch(cMsg.MsgId, cMsg, req)
	}
	//log.Debug(s.Log("on message:%v", string(cMsg)))
	return nil
}

// 向内部服务发送消息
func (s *ClientService) SendData(serviceTypeId pb.ServiceTypeId, msgId int32, data []byte) {
	msg := &pb.ClientMsg{
		ServiceTid:  serviceTypeId,
		ServiceName: s.lastServiceName,
		UserId:      s.userId,
		MsgId:       msgId,
		Data:        data,
	}
	d, _ := proto.Marshal(msg)
	s.client.SendMsg(d)
}

// 向内部服务发送消息
func (s *ClientService) SendMsg(serviceTypeId pb.ServiceTypeId, msgId int32, msg proto.Message) {
	data, _ := proto.Marshal(msg)
	s.SendData(serviceTypeId, msgId, data)
}

func (s *ClientService) Log(format string, a ...any) string {
	head := fmt.Sprintf("user:%v ", s.userId)
	return head + fmt.Sprintf(format, a...)
}
