package com.teefun.controller.queue;
import javax.annotation.Resource;
import javax.validation.Valid;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.google.common.eventbus.EventBus;
import com.teefun.bean.matchmaking.Matchmaking;
import com.teefun.bean.usercontext.UserContext;
import com.teefun.controller.AbstractController;
import com.teefun.controller.queue.bean.AskPasswordResponse;
import com.teefun.controller.queue.bean.CreateQueueRequest;
import com.teefun.controller.queue.bean.PlayerReadyRequest;
import com.teefun.exception.JsonErrorException;
import com.teefun.events.event.QueueModifiedEvent;
import com.teefun.model.Player;
import com.teefun.model.Queue;
import com.teefun.model.QueueState;
import com.teefun.model.teeworlds.TeeworldsConfig;
/**
* Queue controller.
*
* @author Rajh
*
*/
@Controller
@RequestMapping("/queue")
public class QueueController extends AbstractController {
/**
* Matchmaking system.
*/
@Resource
private Matchmaking matchmaking;
/**
* The user context.
*/
@Resource
private UserContext userContext;
/**
* Event bus.
*/
@Resource
private EventBus eventBus;
/**
* Queue modification home page.
*
* @param model the model
* @return the view
*/
// @PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value = { "/home", "/" }, method = RequestMethod.GET)
public ModelAndView home(final Model model) {
model.addAttribute("queues", this.matchmaking.getQueues());
return new ModelAndView("queue");
}
/**
* Join a queue.
*
* @param queueId the queue id
* @param bindingResult the binding result
* @return an empty json
*/
@RequestMapping(value = "/joinQueue", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String joinQueue(@RequestBody @Valid final Integer queueId, final BindingResult bindingResult) {
this.userContext.getPlayer().keepAlive();
if (bindingResult.hasErrors()) {
throw new JsonErrorException("Request validation failed", bindingResult);
}
final Player player = this.userContext.getPlayer();
final Queue queue = this.matchmaking.getQueueById(queueId);
if (queue == null) {
throw new JsonErrorException("Queue does not exist", bindingResult);
}
if (queue.isFull()) {
throw new JsonErrorException("Queue is full", bindingResult);
}
if (queue.containsPlayer(player)) {
throw new JsonErrorException("Player already in queue", bindingResult);
}
if (queue.getState() != QueueState.WAITING_PLAYERS) {
throw new JsonErrorException("Incorrect queue state", bindingResult);
}
this.matchmaking.joinQueue(player, queue);
return EMPTY_JSON;
}
/**
* Quit a queue.
*
* @param queueId the queue id
* @param bindingResult the binding result
* @return an empty json
*/
@RequestMapping(value = "/quitQueue", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String quitQueue(@RequestBody @Valid final Integer queueId, final BindingResult bindingResult) {
this.userContext.getPlayer().keepAlive();
if (bindingResult.hasErrors()) {
throw new JsonErrorException("Request validation failed", bindingResult);
}
final Player player = this.userContext.getPlayer();
final Queue queue = this.matchmaking.getQueueById(queueId);
if (queue == null) {
throw new JsonErrorException("Queue does not exist", bindingResult);
}
if (!queue.containsPlayer(player)) {
throw new JsonErrorException("Player is not in this queue", bindingResult);
}
if (queue.getState() != QueueState.WAITING_PLAYERS) {
throw new JsonErrorException("Incorrect queue state", bindingResult);
}
this.matchmaking.quitQueue(player, queue);
return EMPTY_JSON;
}
/**
* Quit all queues.
*
* @return an empty json
*/
@RequestMapping(value = "/quitAllQueues", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String quitAllQueues() {
this.userContext.getPlayer().keepAlive();
final Player player = this.userContext.getPlayer();
this.matchmaking.quitAllQueues(player);
return EMPTY_JSON;
}
/**
* Create a queue.
*
* @param createQueueRequest the request
* @param bindingResult the binding result
* @return an empty json
*/
// @PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value = "/createQueue", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String createQueue(@RequestBody @Valid final CreateQueueRequest createQueueRequest, final BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
throw new JsonErrorException("Request validation failed", bindingResult);
}
final Integer queueId = createQueueRequest.getId();
final Queue queue;
final boolean isNewQueue = (queueId == null || queueId == -1);
if(isNewQueue) {
final Queue existQueue = this.matchmaking.getQueueByName(createQueueRequest.getName());
if (existQueue != null) {
throw new JsonErrorException("A queue with that name already exist", bindingResult);
}
queue = new Queue();
}
else {
queue = this.matchmaking.getQueueById(queueId);
if(queue == null)
throw new JsonErrorException("There is no queue with this id", bindingResult);
}
queue.setName(createQueueRequest.getName());
queue.setMaxSize(createQueueRequest.getMaxSize());
queue.setMap(createQueueRequest.getMap());
queue.setGametype(createQueueRequest.getGametype());
queue.setScoreLimit(createQueueRequest.getScoreLimit());
queue.setTimeLimit(createQueueRequest.getTimeLimit());
if(isNewQueue)
this.matchmaking.addQueue(queue);
else
this.eventBus.post(new QueueModifiedEvent(queue));
return EMPTY_JSON;
}
/**
* Delete a queue.
*
* @param queueId the queue id
* @param bindingResult the binding result
* @return an empty json
*/
// @PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value = "/deleteQueue", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String deleteQueue(@RequestBody @Valid final Integer queueId, final BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
throw new JsonErrorException("Request validation failed", bindingResult);
}
final Queue queue = this.matchmaking.getQueueById(queueId);
if (queue == null) {
throw new JsonErrorException("Queue does not exist", bindingResult);
}
this.matchmaking.removeQueue(queue);
return EMPTY_JSON;
}
/**
* Player is ready/notready.
*
* @param queueId the queue id
* @param bindingResult the binding result
* @return the password
*/
@RequestMapping(value = "/askPassword", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public AskPasswordResponse askPassword(@RequestBody @Valid final Integer queueId, final BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
throw new JsonErrorException("Request validation failed", bindingResult);
}
final Queue queue = this.matchmaking.getQueueById(queueId);
if (queue == null) {
throw new JsonErrorException("Queue does not exist", bindingResult);
}
if (!queue.containsPlayer(this.userContext.getPlayer())) {
throw new JsonErrorException("Player is not in this queue", bindingResult);
}
if (queue.getState() != QueueState.IN_GAME) {
throw new JsonErrorException("Game not ready", bindingResult);
}
final TeeworldsConfig config = queue.getServer().getConfig();
return new AskPasswordResponse(config.getVariableAsString("sv_name"), config.getVariableAsString("password"));
}
/**
* Player is ready/notready.
*
* @param playerReadyRequest the request
* @param bindingResult the binding result
* @return an empty json
*/
@RequestMapping(value = "/playerReady", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String playerReady(@RequestBody @Valid final PlayerReadyRequest playerReadyRequest, final BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
throw new JsonErrorException("Request validation failed", bindingResult);
}
final Queue queue = this.matchmaking.getQueueById(playerReadyRequest.getQueueId());
if (queue == null) {
throw new JsonErrorException("Queue does not exist", bindingResult);
}
if (!queue.containsPlayer(this.userContext.getPlayer())) {
throw new JsonErrorException("Player is not in this queue", bindingResult);
}
if (queue.getState() != QueueState.WAITING_READY) {
throw new JsonErrorException("Incorrect queue state", bindingResult);
}
this.matchmaking.setPlayerReady(this.userContext.getPlayer(), queue, playerReadyRequest.getIsReady());
return EMPTY_JSON;
}
}