using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Shogi.Api.Extensions; using Shogi.Api.Managers; using Shogi.Api.Repositories; using Shogi.Contracts.Api; using Shogi.Contracts.Socket; using Shogi.Contracts.Types; using System.Data.SqlClient; namespace Shogi.Api.Controllers; [ApiController] [Route("[controller]")] [Authorize] public class SessionsController : ControllerBase { private readonly ISocketConnectionManager communicationManager; private readonly IModelMapper mapper; private readonly ISessionRepository sessionRepository; private readonly IQueryRespository queryRespository; private readonly ILogger logger; public SessionsController( ISocketConnectionManager communicationManager, IModelMapper mapper, ISessionRepository sessionRepository, IQueryRespository queryRespository, ILogger logger) { this.communicationManager = communicationManager; this.mapper = mapper; this.sessionRepository = sessionRepository; this.queryRespository = queryRespository; this.logger = logger; } [HttpPost] public async Task CreateSession([FromBody] CreateSessionCommand request) { var userId = User.GetShogiUserId(); var session = new Domain.Aggregates.Session(request.Name, userId); try { await sessionRepository.CreateSession(session); } catch (SqlException e) { logger.LogError(exception: e, message: "Uh oh"); return this.Conflict(); } await communicationManager.BroadcastToAll(new SessionCreatedSocketMessage()); return CreatedAtAction(nameof(CreateSession), new { sessionName = request.Name }, null); } [HttpDelete("{name}")] public async Task DeleteSession(string name) { var userId = User.GetShogiUserId(); var session = await sessionRepository.ReadSession(name); if (session == null) return this.NoContent(); if (session.Player1 == userId) { await sessionRepository.DeleteSession(name); return this.NoContent(); } return this.Unauthorized("Cannot delete sessions created by others."); } //[HttpPost("{sessionName}/Move")] //public async Task MovePiece([FromRoute] string sessionName, [FromBody] MovePieceCommand request) //{ // var user = await gameboardManager.ReadUser(User); // var session = await gameboardRepository.ReadSession(sessionName); // if (session == null) // { // return NotFound(); // } // if (user == null || (session.Player1 != user.Id && session.Player2 != user.Id)) // { // return Forbid("User is not seated at this game."); // } // try // { // var move = request.Move; // if (move.PieceFromCaptured.HasValue) // session.Move(mapper.Map(move.PieceFromCaptured.Value), move.To); // else if (!string.IsNullOrWhiteSpace(move.From)) // session.Move(move.From, move.To, move.IsPromotion); // await gameboardRepository.CreateBoardState(session); // await communicationManager.BroadcastToPlayers( // new MoveResponse // { // SessionName = session.Name, // PlayerName = user.Id // }, // session.Player1, // session.Player2); // return Ok(); // } // catch (InvalidOperationException ex) // { // return Conflict(ex.Message); // } //} // 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.SocketAction.CreateGame) // { // Game = model.ToServiceModel(), // PlayerName = // } // var task = request.IsPrivate // ? communicationManager.BroadcastToPlayers(response, userName) // : communicationManager.BroadcastToAll(response); // return new CreatedResult("", null); // } // return new ConflictResult(); //} //[HttpGet("{sessionName}")] //[AllowAnonymous] //public async Task GetSession([FromRoute] string sessionName) //{ // var user = await ReadUserOrThrow(); // var session = await gameboardRepository.ReadSession(sessionName); // if (session == null) // { // return NotFound(); // } // var playerPerspective = session.Player2 == user.Id // ? WhichPlayer.Player2 // : WhichPlayer.Player1; // var response = new ReadSessionResponse // { // Session = new Session // { // BoardState = new BoardState // { // Board = mapper.Map(session.BoardState.State), // Player1Hand = session.BoardState.Player1Hand.Select(mapper.Map).ToList(), // Player2Hand = session.BoardState.Player2Hand.Select(mapper.Map).ToList(), // PlayerInCheck = mapper.Map(session.BoardState.InCheck) // }, // SessionName = session.Name, // Player1 = session.Player1, // Player2 = session.Player2 // } // }; // return Ok(response); //} [HttpGet("PlayerCount")] public async Task> GetSessionsPlayerCount() { var sessions = await this.queryRespository.ReadSessionPlayerCount(); return Ok(new ReadSessionsPlayerCountResponse { PlayerHasJoinedSessions = Array.Empty(), AllOtherSessions = sessions.ToList() }); } [HttpGet("{name}")] public async Task> GetSession(string name) { var session = await sessionRepository.ReadSession(name); if (session == null) return this.NotFound(); return new ReadSessionResponse { Session = new Session { BoardState = new BoardState { Board = session.Board.BoardState.State.ToContract(), Player1Hand = session.Board.BoardState.Player1Hand.ToContract(), Player2Hand = session.Board.BoardState.Player2Hand.ToContract(), PlayerInCheck = session.Board.BoardState.InCheck?.ToContract(), WhoseTurn = session.Board.BoardState.WhoseTurn.ToContract() }, Player1 = session.Player1, Player2 = session.Player2, SessionName = session.Name } }; } //[HttpPut("{sessionName}")] //public async Task PutJoinSession([FromRoute] string sessionName) //{ // var user = await ReadUserOrThrow(); // var session = await gameboardRepository.ReadSessionMetaData(sessionName); // if (session == null) // { // return NotFound(); // } // if (session.Player2 != null) // { // return this.Conflict("This session already has two seated players and is full."); // } // session.SetPlayer2(user.Id); // await gameboardRepository.UpdateSession(session); // var opponentName = user.Id == session.Player1 // ? session.Player2! // : session.Player1; // await communicationManager.BroadcastToPlayers(new JoinSessionResponse // { // SessionName = session.Name, // PlayerName = user.Id // }, opponentName); // return Ok(); //} //[Authorize(Roles = "Admin")] //[HttpDelete("{sessionName}")] //public async Task DeleteSession([FromRoute] string sessionName) //{ // var user = await ReadUserOrThrow(); // if (user.IsAdmin) // { // return Ok(); // } // else // { // return Unauthorized(); // } //} //private async Task ReadUserOrThrow() //{ // var user = await gameboardManager.ReadUser(User); // if (user == null) // { // throw new UnauthorizedAccessException("Unknown user claims."); // } // return user; //} }