/// <summary>
        /// Führt Aktualisierung der Abstimmung aus. Es wird ermittelt welche Eigenschaften eine Aktualisierung 
        /// erhalten haben. Die Aktualisierungen werden an den Server übermittelt, der die Aktualisierung auf
        /// dem Serverdatensatz ausführt und die Gruppenmitglieder über die Änderung informiert.
        /// Ebenso werden die Abstimmungsoptionen aktualisiert, falls Änderungen vorgenommen wurden.
        /// </summary>
        /// <param name="groupId">Die Id der Gruppe, zu der die Abstimmung gehört.</param>
        /// <param name="oldBallot">Der Datensatz der Abstimmung, vor der Aktualisierung.</param>
        /// <param name="newBallot">Der Datensatz mit den neu eingegebenen Daten. Enthält auch die festgelegten
        ///     Abstimmungsoptionen.</param>
        /// <returns>Liefert true, wenn die Aktualisierung erfolgreich war, ansonsten false.</returns>
        /// <exception cref="ClientException">Wirft ClientException, wenn Aktualisierung fehlgeschlagen ist, oder nur
        ///     in Teilen erfolgreich durchgeführt werden konnte.</exception>
        public async Task<bool> EditBallotAsync(int groupId, Ballot oldBallot, Ballot newBallot)
        {
            if (oldBallot == null || newBallot == null)
                return false;

            // Validiere zunächst die neu eingegebenen Daten. Bei Validierungsfehlern kann man hier gleich abbrechen.
            clearValidationErrors();
            newBallot.ClearValidationErrors();
            newBallot.ValidateAll();
            if (newBallot.HasValidationErrors())
            {
                reportValidationErrors(newBallot.GetValidationErrors());
                return false;
            }

            // Generiere Ballot Objekt für die Aktualisierung. Dieses Objekt enthält nur die aktualisierten Eigenschaften.
            bool requiresUpdate = true;
            Ballot updatableBallot = perpareUpdatableBallotInstance(oldBallot, newBallot);
            if (updatableBallot == null)
            {
                Debug.WriteLine("EditBallotAsync: No update required.");
                requiresUpdate = false;
            }

            if (requiresUpdate)
            {
                // Erstelle JSON-Dokument für die Aktualisierung.
                string jsonContent = jsonParser.ParseBallotToJson(updatableBallot);
                if (jsonContent == null)
                {
                    Debug.WriteLine("EditBallotAsync: Failed to generate json document.");
                    throw new ClientException(ErrorCodes.JsonParserError, "Failed to generate json document.");
                }

                // Setze Request zur Aktualisierung der Abstimmung ab.
                string serverResponse = null;
                try
                {
                    serverResponse = await groupAPI.SendUpdateBallotRequest(
                        getLocalUser().ServerAccessToken,
                        groupId,
                        oldBallot.Id,
                        jsonContent);
                }
                catch (APIException ex)
                {
                    Debug.WriteLine("EditBallotAsync: Failed request. Error code: {0}, msg is: '{1}'.", ex.ErrorCode, ex.Message);
                    handleGroupRelatedErrors(ex.ErrorCode, groupId, null, oldBallot.Id);

                    throw new ClientException(ex.ErrorCode, ex.Message);
                }

                // Parse Antwort des Servers.
                Ballot serverBallot = jsonParser.ParseBallotFromJson(serverResponse);
                if (serverBallot != null)
                {
                    Debug.WriteLine("EditBallotAsync: Start local updating of ballot.");
                    // Aktualisiere die Abstimmung.
                    bool successful = UpdateBallot(serverBallot);
                    if (!successful)
                    {
                        throw new ClientException(ErrorCodes.LocalDatabaseException, "Failed to update local ballot");
                    }
                }
                else
                {
                    throw new ClientException(ErrorCodes.JsonParserError, "Failed to parse server response");
                }
            }

            // Führe noch eine Aktualisierung der Abstimmungsoptionen durch.
            List<Option> currentOptions = GetOptions(oldBallot.Id, false);
            // Extrahiere die Liste von Abstimmungsoptionen der neuen Abstimmung.
            List<Option> newOptionList = newBallot.Options;

            await SynchronizeBallotOptionsAsync(groupId, oldBallot.Id, currentOptions, newOptionList);

            return true;
        }
        /// <summary>
        /// Sendet einen Request zum Anlegen einer neuen Abstimmung an den Server.
        /// </summary>
        /// <param name="groupId">Die Id der Gruppe, in der die Abstimmung angelegt werden soll.</param>
        /// <param name="newBallot">Das Abstimmungsojekt mit den Daten der neuen Abstimmung.</param>
        /// <returns>Liefert true, wenn die Abstimmung erfolgreich angelegt werden konnte. Liefert false, 
        ///     wenn die Abstimmung nicht angelegt werden konnte, da z.B. die Validierung der Daten fehlgeschlagen ist.</returns>
        /// <exception cref="ClientException">Wirft ClientException, wenn Erzeugung der Abstimmung fehlgeschlagen ist, oder 
        ///     vom Server abgelehnt wurde.</exception>
        public async Task<bool> CreateBallotAsync(int groupId, Ballot newBallot)
        {
            bool successful = false;

            if (newBallot == null)
                return successful;

            // Führe Validierung der Abstimmungsdaten durch. Abbruch bei aufgetretenem Validierungsfehler.
            clearValidationErrors();
            newBallot.ClearValidationErrors();
            newBallot.ValidateAll();
            if (newBallot.HasValidationErrors())
            {
                reportValidationErrors(newBallot.GetValidationErrors());
                return successful;
            }

            // Die für die neue Abstimmung angegebenen Optionen.
            List<Option> ballotOptions = newBallot.Options;

            // Setze Optionen im Objekt selbst auf null zwecks Create Request.
            newBallot.Options = null;

            // Generiere JSON-Dokument.
            string jsonContent = jsonParser.ParseBallotToJson(newBallot);
            if (jsonContent == null)
            {
                Debug.WriteLine("CreateBallotAsync: Couldn't serialize ballot object to json. Cannot continue.");
                throw new ClientException(ErrorCodes.JsonParserError, "Failed to generate json document.");
            }

            // Setze Request zum Anlegen der Abstimmung ab.
            string serverResponse = null;
            try
            {
                serverResponse = await groupAPI.SendCreateBallotRequest(
                    getLocalUser().ServerAccessToken,
                    groupId,
                    jsonContent);

                successful = true;
            }
            catch (APIException ex)
            {
                Debug.WriteLine("CreateBallotAsync: Request failed. Error code is: {0}.", ex.ErrorCode);
                handleGroupRelatedErrors(ex.ErrorCode, groupId, null, null);

                throw new ClientException(ex.ErrorCode, ex.Message);
            }

            Ballot serverBallot = null;
            if (serverResponse != null)
            {
                // Parse Server Antwort.
                serverBallot = jsonParser.ParseBallotFromJson(serverResponse);

                if (serverBallot != null)
                {
                    // Speichere Abstimmung ab.
                    if (!StoreBallot(groupId, serverBallot))
                    {
                        Debug.WriteLine("CreateBallotAsync: Failed to store ballot.");
                        throw new ClientException(ErrorCodes.LocalDatabaseException, "Failed to store ballot with id " + serverBallot.Id + ".");
                    }
                }
                else
                {
                    throw new ClientException(ErrorCodes.JsonParserError, "Failed to parse server response.");
                }
            }

            // Sende noch die Requests zum Anlegen der Abstimmungsoptionen.
            if (serverBallot != null && ballotOptions != null)
            {
                bool successfullyCreatedOptions = true;

                foreach (Option option in ballotOptions)
                {
                    try
                    {
                        await CreateBallotOptionAsync(groupId, serverBallot.Id, option);
                    }
                    catch (ClientException ex)
                    {
                        // Nicht die ganze Ausführung abbrechen bei fehlgeschlagenem Request.
                        // Versuche den Rest der Optionen dennoch erfolgreich anzulegen.
                        Debug.WriteLine("CreateBallotAsync: Failed to store a ballot option. " + 
                            "The option with id {0} could not be created. Msg is: {1}.", option.Id, ex.Message);
                        successfullyCreatedOptions = false;
                    }
                }

                if (!successfullyCreatedOptions)
                {
                    // Werfe Fehler mit entsprechendem Fehlercode. Hinweis, dass nicht alle Optionen angelegt wurden.
                    throw new ClientException(ErrorCodes.OptionCreationHasFailedInBallotCreationProcess, "Failed to store options.");
                }
            }

            return successful;
        }