using Gameboard.ShogiUI.Sockets.Managers; using Gameboard.ShogiUI.Sockets.Repositories; using Gameboard.ShogiUI.Sockets.ServiceModels.Api; using Gameboard.ShogiUI.Sockets.ServiceModels.Socket; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System; using System.Linq; using System.Threading.Tasks; namespace Gameboard.ShogiUI.Sockets.Controllers { [Authorize] [ApiController] [Route("[controller]")] public class GameController : ControllerBase { private static readonly string UsernameClaim = "preferred_username"; private readonly IGameboardManager gameboardManager; private readonly IGameboardRepository gameboardRepository; private readonly ISocketConnectionManager communicationManager; private string? JwtUserName => HttpContext.User.Claims.FirstOrDefault(c => c.Type == UsernameClaim)?.Value; public GameController( IGameboardRepository repository, IGameboardManager manager, ISocketConnectionManager communicationManager) { gameboardManager = manager; gameboardRepository = repository; this.communicationManager = communicationManager; } [HttpPost("JoinCode")] public async Task PostGameInvitation([FromBody] PostGameInvitation request) { //var isPlayer1 = await gameboardManager.IsPlayer1(request.SessionName, userName); //if (isPlayer1) //{ // var code = await gameboardRepository.PostJoinCode(request.SessionName, userName); // return new CreatedResult("", new PostGameInvitationResponse(code)); //} //else //{ return new UnauthorizedResult(); //} } [AllowAnonymous] [HttpPost("GuestJoinCode")] public async Task PostGuestGameInvitation([FromBody] PostGuestGameInvitation request) { //var isGuest = gameboardManager.IsGuest(request.GuestId); //var isPlayer1 = gameboardManager.IsPlayer1(request.SessionName, request.GuestId); //if (isGuest && await isPlayer1) //{ // var code = await gameboardRepository.PostJoinCode(request.SessionName, request.GuestId); // return new CreatedResult("", new PostGameInvitationResponse(code)); //} //else //{ return new UnauthorizedResult(); //} } [HttpPost("{gameName}/Move")] public async Task PostMove([FromRoute] string gameName, [FromBody] PostMove request) { Models.User? user = null; if (Request.Cookies.ContainsKey(SocketController.WebSessionKey)) { var webSessionId = Guid.Parse(Request.Cookies[SocketController.WebSessionKey]!); user = await gameboardManager.ReadUser(webSessionId); } else if (!string.IsNullOrEmpty(JwtUserName)) { user = await gameboardManager.ReadUser(JwtUserName); } var session = await gameboardManager.ReadSession(gameName); if (session == null || user == null || (session.Player1 != user.Name && session.Player2 != user.Name)) { throw new UnauthorizedAccessException("You are not seated at this game."); } var move = request.Move; var moveModel = move.PieceFromCaptured.HasValue ? new Models.Move(move.PieceFromCaptured.Value, move.To, move.IsPromotion) : new Models.Move(move.From!, move.To, move.IsPromotion); var moveSuccess = session.Shogi.Move(moveModel); if (moveSuccess) { await communicationManager.BroadcastToPlayers(new MoveResponse { GameName = session.Name, PlayerName = user.Name, Move = moveModel.ToServiceModel() }, session.Player1, session.Player2); return Created(string.Empty, null); } throw new InvalidOperationException("Illegal move."); } // TODO: Use JWT tokens for guests so they can authenticate and use API routes, too. //[Route("")] //public async Task PostSession([FromBody] PostSession request) //{ // var model = new Models.Session(request.Name, request.IsPrivate, request.Player1, request.Player2); // var success = await repository.CreateSession(model); // if (success) // { // var message = new ServiceModels.Socket.Messages.CreateGameResponse(ServiceModels.Types.ClientAction.CreateGame) // { // Game = model.ToServiceModel(), // PlayerName = // } // var task = request.IsPrivate // ? communicationManager.BroadcastToPlayers(response, userName) // : communicationManager.BroadcastToAll(response); // return new CreatedResult("", null); // } // return new ConflictResult(); //} } }