// Package services provides the game service layer for Snake, // handling NATS subscriptions and chat room management. package services import ( "fmt" "github.com/nats-io/nats.go" "github.com/ryanhamamura/games/chat" chatcomponents "github.com/ryanhamamura/games/chat/components" "github.com/ryanhamamura/games/snake" ) func snakeChatColor(slot int) string { if slot >= 0 && slot < len(snake.SnakeColors) { return snake.SnakeColors[slot] } return "#666" } // GameService manages NATS subscriptions and chat for Snake games. type GameService struct { nc *nats.Conn } // NewGameService creates a new game service. func NewGameService(nc *nats.Conn) *GameService { return &GameService{ nc: nc, } } // SubscribeGameUpdates returns a NATS subscription and channel for game state updates. func (s *GameService) SubscribeGameUpdates(gameID string) (*nats.Subscription, <-chan *nats.Msg, error) { ch := make(chan *nats.Msg, 64) sub, err := s.nc.ChanSubscribe(snake.GameSubject(gameID), ch) if err != nil { return nil, nil, fmt.Errorf("subscribing to game updates: %w", err) } return sub, ch, nil } // ChatConfig returns the chat configuration for a game. func (s *GameService) ChatConfig(gameID string) chatcomponents.Config { return chatcomponents.Config{ CSSPrefix: "snake", PostURL: fmt.Sprintf("/snake/%s/chat", gameID), Color: snakeChatColor, StopKeyPropagation: true, } } // ChatRoom returns a chat room for a game (ephemeral, not persisted). func (s *GameService) ChatRoom(gameID string) *chat.Room { return chat.NewRoom(s.nc, snake.ChatSubject(gameID)) } // PublishGameUpdate sends a notification that the game state has changed. func (s *GameService) PublishGameUpdate(gameID string) error { return s.nc.Publish(snake.GameSubject(gameID), nil) }