/// <summary>
            /// Updates an existing tournament
            /// </summary>
            /// <param name="tournament">Tournament ID (e.g. 10230) or URL (e.g. 'single_elim' for challonge.com/single_elim). If assigned to a subdomain, URL format must be "subdomain-tournament_url" (e.g. 'test-mytourney' for test.challonge.com/mytourney) </param>
            /// <param name="url">Url of your tournament (letters, numbers and underscores only).
            /// Make sure it is unique (you can leave it blank and have challonge pick a random url for you)</param>
            /// <param name="name">Name of the tournament</param>
            /// <param name="type">Type of tournament</param>
            /// <param name="subdomain">Subdomain to assign the tournament to (requires write access to
            /// the subdomain)</param>
            /// <param name="description">Description/instructions to be displayed above the bracket</param>
            /// <param name="openSignup">Have Challonge host a sign-up page (otherwise, you manually add all participants)</param>
            /// <param name="holdThirdPlaceMatch">Single Elimination only. Include a match between semifinal losers?</param>
            /// <param name="ptsForMatchWin">Swiss only: number of points gained for a match win</param>
            /// <param name="ptsForMatchTie">Swiss only: number of points gained for a match tie</param>
            /// <param name="ptsForGameWin">Swiss only: number of points gained for a game win</param>
            /// <param name="ptsForGameTie">Swiss only: number of points gained for a game tie</param>
            /// <param name="ptsForBye">Swiss only: number of points gained for a bye</param>
            /// <param name="swissRounds">Number of rounds</param>
            /// <param name="rankedBy">How the participants are ranked</param>
            /// <param name="acceptAttachments">Allow match attachment uploads</param>
            /// <param name="hideForum">Hide the forum tab on your Challonge page</param>
            /// <param name="showRounds">Whether or not to label each round above the bracket</param>
            /// <param name="isPrivate">Hide this tournament from the public browsable index and your profile</param>
            /// <param name="notifyUsersWhenMatchesOpen">Whether or not to email registered Challonge
            /// participants when matches open up for them</param>
            /// <param name="notifyUsersWhenTournamentsEnds">Whether or not to email registered Challonge
            /// participants when this tournament ends</param>
            /// <param name="sequentialPairings">When enabled, instead of traditional seeding rules, make
            /// pairings by going straight down the list of participants. First round matches are filled in top
            /// to bottom, then qualifying matches (if applicable).</param>
            /// <param name="signupCap">Maximum number of participants in the bracket. Once the cap is reached,
            /// new participants will be put in waiting list, and <see cref="Participant.OnWaitingList"/> will
            /// be set to <see langword="true"/></param>
            /// <param name="startAt"></param>
            /// <param name="checkInDuration">Length of the participant check-in window in minutes.</param>
            /// <param name="grandFinalsModifier">Double elimination only: how the grand finals will be played</param>
            /// <returns>The updated tournament</returns>
            public async Task <Tournament> UpdateTournamentAsync(string tournament, string name = null,
                                                                 string url                                = null, TournamentType type  = TournamentType.SingleElimination, string subdomain = null,
                                                                 string description                        = null, bool openSignup      = false, bool holdThirdPlaceMatch = false,
                                                                 float ptsForMatchWin                      = 1.0f, float ptsForMatchTie = 0.5f, float ptsForGameWin       = 0f,
                                                                 float ptsForGameTie                       = 0f, float ptsForBye        = 1.0f, int?swissRounds           = null,
                                                                 TournamentRankingStats rankedBy           = TournamentRankingStats.MatchWins, bool acceptAttachments = false,
                                                                 bool hideForum                            = false, bool showRounds = false, bool isPrivate = false, bool notifyUsersWhenMatchesOpen = false,
                                                                 bool notifyUsersWhenTournamentsEnds       = false, bool sequentialPairings = false, int?signupCap = null,
                                                                 DateTimeOffset?startAt                    = null, int?checkInDuration = null,
                                                                 TournamentGrandFinals grandFinalsModifier = TournamentGrandFinals.TwoChances)
            {
                string request = $"https://api.challonge.com/v1/tournaments/{tournament}.json";

                Dictionary <string, string> parameters = PrepareParams(name, url, type, subdomain, description,
                                                                       openSignup, holdThirdPlaceMatch, ptsForMatchWin, ptsForMatchTie, ptsForGameWin, ptsForGameTie,
                                                                       ptsForBye, swissRounds, rankedBy, acceptAttachments, hideForum, showRounds, isPrivate,
                                                                       notifyUsersWhenMatchesOpen, notifyUsersWhenTournamentsEnds, sequentialPairings, signupCap, startAt,
                                                                       checkInDuration, grandFinalsModifier);

                FormUrlEncodedContent content = new FormUrlEncodedContent(parameters);

                TournamentData tournamentData = await PutAsync <TournamentData>(_httpClient, request, content);

                return(tournamentData.Tournament);
            }
            private Dictionary <string, string> PrepareParams(string name, string url, TournamentType type,
                                                              string subdomain, string description, bool openSignup, bool holdThirdPlaceMatch,
                                                              float ptsForMatchWin, float ptsForMatchTie, float ptsForGameWin, float ptsForGameTie,
                                                              float ptsForBye, int?swissRounds, TournamentRankingStats rankedBy, bool acceptAttachments,
                                                              bool hideForum, bool showRounds, bool isPrivate, bool notifyUsersWhenMatchesOpen,
                                                              bool notifyUsersWhenTournamentsEnds, bool sequentialPairings, int?signupCap,
                                                              DateTimeOffset?startAt, int?checkInDuration, TournamentGrandFinals grandFinalsModifier)
            {
                Dictionary <string, string> parameters = new Dictionary <string, string>
                {
                    ["api_key"] = _apiKey
                };

                if (name != null)
                {
                    parameters["tournament[name]"] = name;
                }

                if (url != null)
                {
                    parameters["tournament[url]"] = url;
                }

                parameters["tournament[tournament_type]"] = type switch
                {
                    TournamentType.SingleElimination => "single elimination",
                    TournamentType.DoubleElimination => "double elimination",
                    TournamentType.RoundRobin => "round robin",
                    TournamentType.Swiss => "swiss",
                    _ => ""
                };

                if (subdomain != null)
                {
                    parameters["tournament[subdomain]"] = subdomain;
                }

                if (description != null)
                {
                    parameters["tournament[description]"] = description;
                }

                parameters["tournament[open_signup]"] = openSignup.ToString().ToLower();

                parameters["tournament[hold_third_place_match]"] = holdThirdPlaceMatch.ToString().ToLower();

                parameters["tournament[pts_for_match_win]"] = string.Format(CultureInfo.InvariantCulture, "{0:G}", ptsForMatchWin);
                parameters["tournament[pts_for_match_tie]"] = string.Format(CultureInfo.InvariantCulture, "{0:G}", ptsForMatchTie);
                parameters["tournament[pts_for_game_win]"]  = string.Format(CultureInfo.InvariantCulture, "{0:G}", ptsForGameWin);
                parameters["tournament[pts_for_game_tie]"]  = string.Format(CultureInfo.InvariantCulture, "{0:G}", ptsForGameTie);
                parameters["tournament[pts_for_bye]"]       = string.Format(CultureInfo.InvariantCulture, "{0:G}", ptsForBye);

                parameters["tournament[rr_pts_for_match_win]"]   = string.Format(CultureInfo.InvariantCulture, "{0:G}", ptsForMatchWin);
                parameters["tournament[rr_pts_f, or_match_tie]"] = string.Format(CultureInfo.InvariantCulture, "{0:G}", ptsForMatchTie);
                parameters["tournament[rr_pts_for_game_tie]"]    = string.Format(CultureInfo.InvariantCulture, "{0:G}", ptsForGameTie);
                parameters["tournament[rr_pts_fo r_game_win]"]   = string.Format(CultureInfo.InvariantCulture, "{0:G}", ptsForGameWin);
                if (swissRounds != null)
                {
                    parameters["swiss_rounds]"] = swissRounds.Value.ToString();
                }

                parameters["tournament[ranked_by]"] = rankedBy switch
                {
                    // TODO check if the api accepts game wins percentage
                    TournamentRankingStats.MatchWins => "match wins",
                    TournamentRankingStats.GameWins => "game wins",
                    TournamentRankingStats.PointsScored => "points scored",
                    TournamentRankingStats.PointsDifference => "points difference",
                    TournamentRankingStats.Custom => "custom",
                    _ => parameters["tournament[ranked_by]"]
                };

                parameters["tournament[accept_attachments]"] = acceptAttachments.ToString().ToLower();

                parameters["tournament[hide_forum]"] = hideForum.ToString().ToLower();

                parameters["tournament[show_rounds]"] = showRounds.ToString().ToLower();

                parameters["tournament[private]"] = isPrivate.ToString().ToLower();

                parameters["tournament[notify_users_when_matches_open]"] = notifyUsersWhenMatchesOpen.ToString().ToLower();

                parameters["tournament[notify_users_when_the_tournament_ends]"] = notifyUsersWhenTournamentsEnds.ToString().ToLower();

                parameters["tournament[sequential_pairings]"] = sequentialPairings.ToString().ToLower();

                if (signupCap != null)
                {
                    parameters["tournament[signup_cap]"] = signupCap.Value.ToString();
                }

                if (startAt != null)
                {
                    parameters["tournament[start_at]"] = startAt.Value.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffzzz");
                }

                if (checkInDuration != null)
                {
                    parameters["tournament[check_in_duration]"] = checkInDuration.Value.ToString();
                }

                parameters["tournament[grand_finals_modifier]"] = grandFinalsModifier switch
                {
                    TournamentGrandFinals.TwoChances => "",
                    TournamentGrandFinals.Skip => "skip",
                    TournamentGrandFinals.SingleMatch => "single match",
                    _ => parameters["tournament[grand_finals_modifier]"]
                };

                return(parameters);
            }