using Microsoft.AspNetCore.SignalR; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Collections.Concurrent; using Sledgemapper.Shared.Entities; using Sledgemapper.Clients; using System; using Sledgemapper.Api.Infrastructure.Data; using Microsoft.AspNetCore.Authorization; using Sledgemapper.Api.Models; namespace Sledgemapper.Api.Hubs { [Authorize] public class SledgemapperHub : Hub { private static readonly ConcurrentDictionary UserColors = new(); private readonly SledgemapperDbContext _dbContext; // private readonly DataContext _datacontext; public SledgemapperHub(SledgemapperDbContext dbContext/*, DataContext datacontext*/) { _dbContext = dbContext; // _datacontext = datacontext; } // other colors // #cca300, #20f200, #004011, #00e6d6, #005c73, #0057d9, #d900ca, #660029, #d9003a // private static Dictionary _sessions = new Dictionary(); public List Colors = new() { "#e6194B", "#f58231", "#3cb44b", "#000075", "#911eb4", "#800000", "#808000", "#469990" }; public async Task NewTile(string sessionName, Tile tile) { await Clients.Group(sessionName).NewTile(tile); } public async Task NewRoom(string sessionName, Room room) { await Clients.Group(sessionName).NewRoom(room); } public async Task NewLine(string sessionName, Line line) { await Clients.Group(sessionName).NewLine(line); } public async Task NewWall(string sessionName, Wall tile) { await Clients.Group(sessionName).NewWall(tile); } public async Task NewOverlay(string sessionName, Overlay tile) { await Clients.Group(sessionName).NewOverlay(tile); } public async Task NewNote(string sessionName, Note note) { await Clients.Group(sessionName).NewNote(note); } public async Task DeleteTile(string sessionName, Tile tile) { await Clients.Group(sessionName).DeleteTile(tile); } public async Task DeleteWall(string sessionName, Wall tile) { await Clients.Group(sessionName).DeleteWall(tile); } public async Task DeleteOverlay(string sessionName, Overlay tile) { await Clients.Group(sessionName).DeleteOverlay(tile); } public async Task Ping(string sessionName, Tile location) { var userId = int.Parse(Context.User.Identity.Name); var user = _dbContext.Users.First(u => u.Id == Context.User.Identity.Name); var player = new Player { UserId = userId, Initials = user.Initials, Position = new Tile { X = 0, Y = 0 }, Color = UserColors[userId] }; await Clients.Group(sessionName).Ping(new Ping{X=location.X, Y=location.Y, Player=player}); } public async Task JoinSession(string sessionName) { var session = _dbContext.Sessions.FirstOrDefault(s => s.SessionName == sessionName); var userId = int.Parse(Context.User.Identity.Name); if (session != null) { var userSession = new SessionUser { SessionId = session.SessionId, UserId = userId }; _dbContext.SessionUsers.Add(userSession); await _dbContext.SaveChangesAsync(); await Groups.AddToGroupAsync(Context.ConnectionId, session.SessionName); var user = _dbContext.Users.First(u => u.Id == Context.User.Identity.Name); var player = new Player { UserId = userId, Initials = user.Initials, Position = new Tile { X = 0, Y = 0 }, Color = UserColors[userId] }; await Clients.Group(session.SessionName).NewPlayer(player); await Clients.Group(session.SessionName).RefreshPlayers(); var newSession = new Shared.Entities.Session { SessionName = session.SessionName, SessionId = session.SessionId }; return newSession; } else { return null; } } //public async Task UpdatePosition(string sessionName, int sessionId, Tile tile) //{ // //var userId = int.Parse(Context.User.Identity.Name); // //var SessionUsers = _dbContext.SessionUsers.Where(m => m.SessionId == sessionId).OrderBy(m => m.UserId).ToList(); // //var user = _dbContext.Users.First(u => u.Id == Context.User.Identity.Name); // //var player = new Player { UserId = userId, Initials = user.Initials, Position = tile, Color = UserColors[userId] }; // //await Clients.Group(sessionName).PlayerUpdate(player); //} public async Task UpdatePosition(string sessionName, Guid sessionId, Tile tile) { var userId = int.Parse(Context.User.Identity.Name); var SessionUsers = _dbContext.SessionUsers.Where(m => m.SessionId == sessionId).OrderBy(m => m.UserId).ToList(); var user = _dbContext.Users.First(u => u.Id == Context.User.Identity.Name); var player = new Player { UserId = userId, Initials = user.Initials, Position = tile, Color = UserColors[userId] }; await Clients.Group(sessionName).PlayerUpdate(player); } public override async Task OnConnectedAsync() { var userId = int.Parse(Context.User.Identity.Name); var userConnection = new UserConnection { ConnectionId = Context.ConnectionId, UserId = userId }; _dbContext.UserConnections.Add(userConnection); await _dbContext.SaveChangesAsync(); var availableColor = Colors.Where(m => !UserColors.Values.Contains(m)).First(); UserColors.AddOrUpdate(userId, availableColor, (key, oldValue) => availableColor); await base.OnConnectedAsync(); } public override async Task OnDisconnectedAsync(Exception exception) { var userConnection = _dbContext.UserConnections.FirstOrDefault(m => m.ConnectionId == Context.ConnectionId); var userId = userConnection.UserId; if (userConnection != null) { _dbContext.UserConnections.Remove(userConnection); } var userSessions = _dbContext.SessionUsers.Where(m => m.UserId == userId).ToList(); { foreach (var userSession in userSessions) { var session = _dbContext.Sessions.FirstOrDefault(m => m.SessionId == userSession.SessionId); await Clients.Group(session.SessionName).RemovePlayer(new Player { UserId = userId }); //send remove player _dbContext.SessionUsers.Remove(userSession); } } await _dbContext.SaveChangesAsync(); await base.OnDisconnectedAsync(exception); } } }