public async Task UpdateProfileImageAsync(ApplicationUser user, string data)
        {
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            if (string.IsNullOrEmpty(data))
            {
                throw new ArgumentNullException(nameof(data));
            }

            var bytes = GetImageBytes(data);
            var relativePath = BuildImagePath("users", user.UserName, data);

            var image = await UpdateImageAsync(user.ProfileImage, Defaults.ProfileImage, relativePath, bytes);
            if (image.ImageId <= 0)
            {
                _db.Add(image);
            }

            user.ProfileImage = image;
            _db.Attach(user);

            await _db.SaveChangesAsync();
        }
        public async Task<Player> CreatePlayerForUserAsync(ApplicationUser user)
        {
            var player = new Player { User = user };

            _db.Players.Add(player);
            await _db.SaveChangesAsync();

            return player;
        }
        public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl = null)
        {
            if (User.IsSignedIn())
            {
                return View("ExternalSigninSuccess");
            }

            if (ModelState.IsValid)
            {
                var info = await _signInManager.GetExternalLoginInfoAsync();
                if (info == null)
                {
                    return View("Error");
                }

                var user = new ApplicationUser
                {
                    UserName = model.Username,
                    Battletag = info.ExternalPrincipal.GetBattletag(),
                    Email = model.Email,
                    ProfileImage = await _imageManager.GetDefaultImageAsync(Defaults.ProfileImage),
                    HeaderImage = await _imageManager.GetDefaultImageAsync(Defaults.HeaderImage)
                };

                var result = await _userManager.CreateAsync(user);
                if (result.Succeeded)
                {
                    // Create a player for this user
                    var player = await _playerManager.CreatePlayerForUserAsync(user);

                    var innerResult = await _userManager.AddLoginAsync(user, info);
                    if (innerResult.Succeeded)
                    {
                        await _signInManager.SignInAsync(user, false);
                        return RedirectToAction(nameof(ExternalSigninSuccess), new { ReturnUrl = returnUrl });
                    }
                    AddErrors(innerResult);
                }
                AddErrors(result);
            }

            ViewData["ReturnUrl"] = returnUrl;
            return View(model);
        }
        public async Task CreateAdministrator(string username, string email, string battletag, string battlenetUserId)
        {
            if (string.IsNullOrEmpty(username))
            {
                throw new ArgumentNullException(nameof(username));
            }
            if (string.IsNullOrEmpty(email))
            {
                throw new ArgumentNullException(nameof(email));
            }
            if (string.IsNullOrEmpty(battletag))
            {
                throw new ArgumentNullException(nameof(battletag));
            }
            if (string.IsNullOrEmpty(battlenetUserId))
            {
                throw new ArgumentNullException(nameof(battlenetUserId));
            }

            // Make sure the admin role exists
            if (await _roleManager.FindByNameAsync("Admin") == null)
            {
                var r = await _roleManager.CreateAsync(new IdentityRole("Admin"));
                if (!r.Succeeded)
                {
                    throw new InvalidProgramException("Failed to create admin role");
                }
            }

            // first look for the user
            var user = await _userManager.FindByNameAsync(username);
            if (user != null)
            {
                await CreatePlayerForUserAsync(user);
                var logins = await _userManager.GetLoginsAsync(user);
                if (!logins.Any(x => x.LoginProvider == "Battlenet" && x.ProviderKey == battlenetUserId))
                {
                    var r = await _userManager.AddLoginAsync(user, new UserLoginInfo("Battlenet", battlenetUserId, null));

                    if (!r.Succeeded)
                    {
                        throw new InvalidProgramException("Failed to associate login with existing admin user.");
                    }
                }

                if (await _userManager.IsInRoleAsync(user, "Admin"))
                {
                    return;
                }
                else
                {
                    var r = await _userManager.AddToRoleAsync(user, "Admin");
                    if (r.Succeeded)
                    {
                        return;
                    }
                    else
                    {
                        throw new InvalidProgramException("Failed to add user to admin role");
                    }
                }
            }

            var defaultImage = await _db.DefaultImages
                .Include(x => x.Image)
                .SingleOrDefaultAsync(x => x.Name == Defaults.ProfileImage);
            var image = defaultImage != null ? defaultImage.Image : null;

            user = new ApplicationUser
            {
                UserName = username,
                Email = email,
                Battletag = battletag,
                ProfileImage = image
            };

            var result = await _userManager.CreateAsync(user);
            if (result.Succeeded)
            {
                await CreatePlayerForUserAsync(user);
                result = await _userManager.AddLoginAsync(user, new UserLoginInfo("Battlenet", battlenetUserId, null));
            }
            else
            {
                throw new InvalidProgramException("Failed to create administrator");
            }

            if (result.Succeeded)
            {
                result = await _userManager.AddToRoleAsync(user, "Admin");
            }
            else
            {
                throw new InvalidProgramException("Failed to add login to user");
            }

            if (result.Succeeded)
            {
                return;
            }
            else
            {
                throw new InvalidProgramException("Failed to add user to admin role");
            }
        }
        private async Task CreatePlayerForUserAsync(ApplicationUser user)
        {
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            // Make sure the user has a player entity
            var player = await _db.Players
                .Include(x => x.User)
                .SingleOrDefaultAsync(x => x.User.Id == user.Id);
            if (player == null)
            {
                var rating = new Rating { MatchMakingRating = 1500 };
                _db.Add(rating);

                // Setup default rank
                var rank = new Rank { Rating = rating };
                var defaultSeason = await _db.DefaultSeasons
                    .Include(x => x.Season)
                    .FirstOrDefaultAsync();
                if (defaultSeason != null)
                {
                    var season = await _db.Seasons
                        .Include(x => x.Brackets)
                        .SingleOrDefaultAsync(x => x.SeasonId == defaultSeason.Season.SeasonId);
                    if (season != null && season.Brackets.Any(x => x.Type == RankBrackets.NeverLucky))
                    {
                        rank.RankBracket = season.Brackets.Single(x => x.Type == RankBrackets.NeverLucky);
                    }
                }

                _db.Add(rank);

                player = new Player
                {
                    User = user,
                    Rank = rank
                };

                _db.Add(player);
                await _db.SaveChangesAsync();
            }
        }