using Shogi.Api.Managers; using Shogi.Api.Repositories; using Shogi.Contracts.Api; using Shogi.Contracts.Socket; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.Data.SqlClient; using Shogi.Contracts.Types; using Shogi.Api.Extensions; namespace Shogi.Api.Controllers; [ApiController] [Route("[controller]")] [Authorize] public class SessionController : ControllerBase { private readonly ISocketConnectionManager communicationManager; private readonly IModelMapper mapper; private readonly ISessionRepository sessionRepository; private readonly IQueryRespository queryRespository; private readonly ILogger logger; public SessionController( 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(); if (string.IsNullOrWhiteSpace(userId)) return this.Unauthorized(); var session = new Domain.Aggregates.Session( request.Name, userId, new Domain.ValueObjects.ShogiBoard(Domain.BoardState.StandardStarting)); try { await sessionRepository.CreateShogiBoard(board, request.Name, userId); } 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); } //[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] public async Task> GetSessions() { var sessions = await this.queryRespository.ReadAllSessionsMetadata(); return Ok(new ReadAllSessionsResponse { PlayerHasJoinedSessions = Array.Empty(), AllOtherSessions = sessions.ToList() }); } [HttpGet("{name}")] public async Task> GetSession(string name) { await Task.CompletedTask; return new ReadSessionResponse(); } //[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; //} }