package server

import (
	"fmt"
	"game/common/baseroom"
	"game/common/gameService"
	"game/common/proto/pb"
	"game/common/serviceName"
	"game/common/topicName"
	"game/server/colorgame/config"
	"game/server/colorgame/room"
	"github.com/fox/fox/ipb"
	"github.com/fox/fox/log"
	"github.com/fox/fox/service"
	"github.com/golang/protobuf/proto"
)

var Color []service.IService

type ColorService struct {
	*gameService.GameService

	//roomMgr   *baseroom.RoomMgr
	playerMgr *baseroom.PlayerMgr
	room      baseroom.IRoom
	status    baseroom.ServiceStatus
}

func Init() {
	log.DebugF("init service begin id:%v, num:%v", config.Command.ServiceId, config.Command.ServiceNum)
	for i := 0; i < config.Command.ServiceNum; i++ {
		sid := config.Command.ServiceId + i
		if srv := newColorService(sid); srv != nil {
			Color = append(Color, srv)
		}
	}
}

func Stop() {
	for _, srv := range Color {
		log.DebugF("notify stop service %v", srv.Name())
		srv.NotifyStop()
	}
	for _, srv := range Color {
		srv.WaitStop()
	}
}

func newColorService(serviceId int) service.IService {
	s := new(ColorService)
	sName := fmt.Sprintf("%v-%d", serviceName.ColorGame, serviceId)
	s.GameService = gameService.NewGameService(&service.InitNatsServiceParams{
		EtcdAddress:  config.Cfg.Etcd.Address,
		EtcdUsername: "",
		EtcdPassword: "",
		NatsAddress:  config.Cfg.Nats.Address,
		ServiceType:  serviceName.ColorGame,
		ServiceName:  sName,
		OnFunc:       s,
		TypeId:       int(pb.ServiceTypeId_STI_ColorGame),
		Version:      config.Cfg.BuildDate,
	}, &config.Cfg.Redis)
	_ = s.GameService.Subscribe(topicName.UserOffline)
	s.initProcessor()

	s.playerMgr = baseroom.NewPlayerMgr(nil)
	factory := &room.RoomFactory{}
	s.room, _ = factory.CreateRoom(int(pb.ServiceTypeId_STI_ColorGame), 0, s, s.playerMgr, s.BindService())
	s.status = baseroom.SsWorking
	//s.roomMgr = baseroom.NewRoomMgr(&room.RoomFactory{})

	s.OnInit()
	return s
}

func (s *ColorService) OnInit() {
	// if err := s.NatsService.QueueSubscribe(service.GroupTopic(s), service.GroupQueue(s)); err != nil {
	// 	log.Error(err.Error())
	// }
	s.NatsService.Run()
	log.Debug("onInit")
}

func (s *ColorService) NotifyStop() {
	//s.roomMgr.SetStatus(baseroom.SsWaitStop)
	s.status = baseroom.SsWaitStop
	s.BaseService.NotifyStop()
}

func (s *ColorService) CanStop() bool {
	switch s.status {
	case baseroom.SsWorking:
		return false
	case baseroom.SsWaitStop, baseroom.SsStopped:
		// 没有玩家
		if s.playerMgr.Count() == 0 {
			return true
		}
		return false
	}
	return true
}

func (s *ColorService) OnStop() {
	s.status = baseroom.SsStopped
	s.NatsService.OnStop()
	log.Debug("OnStop")
}

func (s *ColorService) findRoom(uid int64) (*room.ColorPlayer, baseroom.IRoom, error) {
	if user := s.playerMgr.Find(uid); user != nil {
		return room.GetPlayer(user), s.room, nil
		//if rm := s.roomMgr.Find(user.RoomId()); rm != nil {
		//	return user, rm, nil
		//} else {
		//	return nil, nil, fmt.Errorf("user:%v not found room %d", uid, user.RoomId())
		//}
	} else {
		return nil, nil, fmt.Errorf("user:%v not exist", uid)
	}
}

// 处理其它服发送过来的消息
func (s *ColorService) OnMessage(data []byte) error {
	var iMsg = &ipb.InternalMsg{}
	var err error
	if err = proto.Unmarshal(data, iMsg); err != nil {
		log.Error(err.Error())
		return err
	}
	if req, err := s.Processor().Unmarshal(iMsg.MsgId, iMsg.Msg); err == nil {
		err = s.Processor().Dispatch(iMsg.MsgId, iMsg, req)
	} else {
		var user baseroom.IPlayer
		var rm baseroom.IRoom
		if user, rm, err = s.findRoom(iMsg.UserId); err == nil {
			if req, err = rm.Unmarshal(iMsg.MsgId, iMsg.Msg); err == nil {
				err = rm.Dispatch(user, iMsg.MsgId, iMsg, req)
			}
		}
		if err != nil {
			log.Error(err.Error())
		}
	}
	log.Debug(s.Log("received message:%v", pb.MsgId(iMsg.MsgId)))
	return nil
}
