using Gameboard.ShogiUI.Sockets.Repositories.CouchModels; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; namespace Gameboard.ShogiUI.Sockets.Repositories { public interface IGameboardRepository { Task CreateBoardState(string sessionName, Models.BoardState boardState, Models.Move? move); Task CreateGuestUser(string userName); Task CreateSession(Models.Session session); Task> ReadSessions(); Task IsGuestUser(string userName); Task PostJoinCode(string gameName, string userName); Task ReadSession(string name); Task> ReadBoardStates(string name); } public class GameboardRepository : IGameboardRepository { private const string ApplicationJson = "application/json"; private readonly HttpClient client; private readonly ILogger logger; public GameboardRepository(IHttpClientFactory clientFactory, ILogger logger) { client = clientFactory.CreateClient("couchdb"); this.logger = logger; } public async Task> ReadSessions() { var selector = $@"{{ ""{nameof(Session.Type)}"": ""{nameof(Session)}"" }}"; var query = $@"{{ ""selector"": {selector} }}"; var content = new StringContent(query, Encoding.UTF8, ApplicationJson); var response = await client.PostAsync("_find", content); var responseContent = await response.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject>(responseContent); if (result == null) { logger.LogError("Unable to deserialize couchdb result during {0}.", nameof(this.ReadSessions)); return Array.Empty(); } return result.docs .Select(_ => _.ToDomainModel()) .ToList(); } public async Task ReadSession(string name) { var response = await client.GetAsync(name); var responseContent = await response.Content.ReadAsStringAsync(); var couchModel = JsonConvert.DeserializeObject(responseContent); return couchModel.ToDomainModel(); } public async Task> ReadBoardStates(string name) { var selector = $@"{{ ""{nameof(BoardState.Type)}"": ""{nameof(BoardState)}"", ""{nameof(BoardState.Name)}"": ""{name}"" }}"; var sort = $@"{{ ""{nameof(BoardState.CreatedDate)}"" : ""desc"" }}"; var query = $@"{{ ""selector"": {selector}, ""sort"": {sort} }}"; var content = new StringContent(query, Encoding.UTF8, ApplicationJson); var response = await client.PostAsync("_find", content); var responseContent = await response.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject>(responseContent); if (result == null) { logger.LogError("Unable to deserialize couchdb result during {0}.", nameof(this.ReadSessions)); return Array.Empty(); } return result.docs .Select(_ => new Models.BoardState(_)) .ToList(); } //public async Task DeleteGame(string gameName) //{ // //var uri = $"Session/{gameName}"; // //await client.DeleteAsync(Uri.EscapeUriString(uri)); //} public async Task CreateSession(Models.Session session) { var couchModel = new Session(session.Name, session); var content = new StringContent(JsonConvert.SerializeObject(couchModel), Encoding.UTF8, ApplicationJson); var response = await client.PostAsync(string.Empty, content); return response.IsSuccessStatusCode; } public async Task CreateBoardState(string sessionName, Models.BoardState boardState, Models.Move? move) { var couchModel = new BoardState(sessionName, boardState, move); var content = new StringContent(JsonConvert.SerializeObject(couchModel), Encoding.UTF8, ApplicationJson); var response = await client.PostAsync(string.Empty, content); return response.IsSuccessStatusCode; } //public async Task PutJoinPublicSession(PutJoinPublicSession request) //{ // var content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, MediaType); // var response = await client.PutAsync(JoinSessionRoute, content); // var json = await response.Content.ReadAsStringAsync(); // return JsonConvert.DeserializeObject(json).JoinSucceeded; //} //public async Task PostJoinPrivateSession(PostJoinPrivateSession request) //{ // var content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, MediaType); // var response = await client.PostAsync(JoinSessionRoute, content); // var json = await response.Content.ReadAsStringAsync(); // var deserialized = JsonConvert.DeserializeObject(json); // if (deserialized.JoinSucceeded) // { // return deserialized.SessionName; // } // return null; //} //public async Task> GetMoves(string gameName) //{ // var uri = $"Session/{gameName}/Moves"; // var get = await client.GetAsync(Uri.EscapeUriString(uri)); // var json = await get.Content.ReadAsStringAsync(); // if (string.IsNullOrWhiteSpace(json)) // { // return new List(); // } // var response = JsonConvert.DeserializeObject(json); // return response.Moves.Select(m => new Move(m)).ToList(); //} //public async Task PostMove(string gameName, PostMove request) //{ // var uri = $"Session/{gameName}/Move"; // var content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, MediaType); // await client.PostAsync(Uri.EscapeUriString(uri), content); //} public async Task PostJoinCode(string gameName, string userName) { // var uri = $"JoinCode/{gameName}"; // var serialized = JsonConvert.SerializeObject(new PostJoinCode { PlayerName = userName }); // var content = new StringContent(serialized, Encoding.UTF8, MediaType); // var json = await (await client.PostAsync(Uri.EscapeUriString(uri), content)).Content.ReadAsStringAsync(); // return JsonConvert.DeserializeObject(json).JoinCode; return string.Empty; } //public async Task GetPlayer(string playerName) //{ // var uri = $"Player/{playerName}"; // var get = await client.GetAsync(Uri.EscapeUriString(uri)); // var content = await get.Content.ReadAsStringAsync(); // if (!string.IsNullOrWhiteSpace(content)) // { // var response = JsonConvert.DeserializeObject(content); // return new Player(response.Player.Name); // } // return null; //} public async Task CreateGuestUser(string userName) { var couchModel = new User(userName, User.LoginPlatform.Guest); var content = new StringContent(JsonConvert.SerializeObject(couchModel), Encoding.UTF8, ApplicationJson); var response = await client.PostAsync(string.Empty, content); return response.IsSuccessStatusCode; } public async Task IsGuestUser(string userName) { var req = new HttpRequestMessage(HttpMethod.Head, new Uri($"{client.BaseAddress}/{User.GetDocumentId(userName)}")); var response = await client.SendAsync(req); return response.IsSuccessStatusCode; } } }