package gameserver

import (
	"battlecamp-go-server/flag"
	"battlecamp-go-server/game"
	"battlecamp-go-server/stomp"
	"battlecamp-go-server/events"
	"log"
	"net/http"
	"strconv"
)

type GameServer struct {
	addGameChan   chan addGameChan
	listGamesChan chan gamesChan
	getGameChan   chan getGame
}

type addGameChan struct {
	game *game.Game
	id   chan int64
}

type gamesChan chan []*game.Game

type getGame struct {
	id         int64
	returnChan chan *game.Game
}

func New() GameServer {

	gameServer := GameServer{
		addGameChan:   make(chan addGameChan),
		listGamesChan: make(chan gamesChan),
		getGameChan:   make(chan getGame),
	}

	go serveGames(gameServer)
	return gameServer
}

func (gs *GameServer) Serve() {
	log.Fatal(http.ListenAndServe(":"+strconv.Itoa(*flag.Port), newUrlRouter(gs)))
}

func serveGames(gameServer GameServer) {
	gamesMap := make(map[int64]*game.Game)
	gameCounter := int64(0)

	for {
		select {
		case addGameChan := <-gameServer.addGameChan:
			addGameChan.game.Id = gameCounter
			gameCounter++
			gamesMap[addGameChan.game.Id] = addGameChan.game
			addGameChan.id <- addGameChan.game.Id
		case r := <-gameServer.listGamesChan:
			v := make([]*game.Game, 0, len(gamesMap))
			for _, value := range gamesMap {
				v = append(v, value)
			}
			r <- v
		case r := <-gameServer.getGameChan:
			r.returnChan <- gamesMap[r.id]
		}
	}
}

func (games GameServer) AddGame(x, y int) *game.Game {
	game := game.NewGame(x, y) // TODO
	addGame := addGameChan{
		game: game,
		id:   make(chan int64),
	}

	games.addGameChan <- addGame
	gameId := <-addGame.id

	stompGameStart := events.GameStart{
		Type:   "GAME_START",
		GameId: gameId,
	}

	stomp.SendJson("game", stompGameStart)
	return game
}

func (games GameServer) ListGames() []*game.Game {
	r := make(chan []*game.Game)
	games.listGamesChan <- r
	return <-r
}

func (games GameServer) GetGame(id int64) *game.Game {
	getGame := getGame{
		id:         id,
		returnChan: make(chan *game.Game),
	}
	games.getGameChan <- getGame
	return <-getGame.returnChan
}
