internal void DeleteFinishedBatch(RequestBatch batch)
 {
     eventDataManager.DeleteEvents(batch.EventsCount);
 }
        internal void SendRequests()
        {
            RequestBatch batch = RequestBatchFactory.CreateNextBatch();

            if (batch.IsEmpty)
            {
                return;
            }

            IDictionary <string, string> multiRequestArgs = new Dictionary <string, string>();

            if (!Leanplum.ApiConfig.AttachApiKeys(multiRequestArgs))
            {
                return;
            }

            multiRequestArgs[Constants.Params.DATA]        = batch.JsonEncoded;
            multiRequestArgs[Constants.Params.SDK_VERSION] = Constants.SDK_VERSION;
            multiRequestArgs[Constants.Params.ACTION]      = Constants.Methods.MULTI;
            multiRequestArgs[Constants.Params.TIME]        = Util.GetUnixTimestamp().ToString();

            LeanplumNative.CompatibilityLayer.LogDebug($"Sending Request to" +
                                                       $" {Leanplum.ApiConfig.ApiHost}/{Leanplum.ApiConfig.ApiPath}:{Leanplum.ApiConfig.ApiSSL} with Parameters: " +
                                                       Json.Serialize(multiRequestArgs));

            RequestUtil.CreateWebRequest(Leanplum.ApiConfig.ApiHost,
                                         Leanplum.ApiConfig.ApiPath,
                                         multiRequestArgs,
                                         RequestBuilder.POST,
                                         Leanplum.ApiConfig.ApiSSL,
                                         Constants.NETWORK_TIMEOUT_SECONDS).GetResponseAsync(delegate(WebResponse response)
            {
                string responseError = response.GetError();
                long statusCode      = response.GetStatusCode();
                string log           = $"Received response with status code: {statusCode}";

                if (string.IsNullOrEmpty(responseError))
                {
                    // Success
                    LeanplumNative.CompatibilityLayer.LogDebug(log);

                    object json = response.GetResponseBodyAsJson();
                    LeanplumNative.CompatibilityLayer.LogDebug($"Received response body: {response.GetResponseBody()}");

                    if (RequestUtil.UpdateApiConfig(json))
                    {
                        // API config is changed and we need to send requests again
                        SendRequests();
                        return;
                    }

                    EventDataManager.InvokeCallbacks(json);

                    RequestBatchFactory.DeleteFinishedBatch(batch);

                    LeanplumNative.CompatibilityLayer.LogDebug("Response Done");
                }
                else
                {
                    // Error
                    LeanplumNative.CompatibilityLayer.LogDebug($"{log} and error: {responseError}");
                    bool connectionError = !string.IsNullOrEmpty(responseError) &&
                                           responseError.Contains("Could not resolve host");

                    if (statusCode == 408 || statusCode == 429 ||
                        statusCode == 502 || statusCode == 503 || statusCode == 504)
                    {
                        responseError = "Server is busy; will retry later";
                        LeanplumNative.CompatibilityLayer.LogWarning(responseError);
                    }
                    else if (connectionError)
                    {
                        LeanplumNative.CompatibilityLayer.LogWarning("Could not connect to Leanplum. Will retry later.");
                    }
                    else
                    {
                        object json = response.GetResponseBodyAsJson();
                        if (json != null && json.GetType() == typeof(IDictionary <string, object>))
                        {
                            IDictionary <string, object> responseDictionary = RequestUtil.GetLastResponse(response.GetResponseBodyAsJson()) as IDictionary <string, object>;
                            if (responseDictionary != null)
                            {
                                string error = RequestUtil.GetResponseError(responseDictionary);
                                if (error != null)
                                {
                                    if (error.StartsWith("App not found"))
                                    {
                                        error = "No app matching the provided app ID was found.";
                                        Constants.isInPermanentFailureState = true;
                                        Constants.isNoop = true;
                                    }
                                    else if (error.StartsWith("Invalid access key"))
                                    {
                                        error = "The access key you provided is not valid for this app.";
                                        Constants.isInPermanentFailureState = true;
                                        Constants.isNoop = true;
                                    }
                                    else if (error.StartsWith("Development mode requested but not permitted"))
                                    {
                                        error = "A call to Leanplum.setAppIdForDevelopmentMode with your production key was made, which is not permitted.";
                                        Constants.isInPermanentFailureState = true;
                                        Constants.isNoop = true;
                                    }

                                    if (Constants.isInPermanentFailureState)
                                    {
                                        RequestBatchFactory.DeleteFinishedBatch(batch);
                                    }

                                    responseError += ", message: " + error;
                                }
                            }
                        }
                        if (responseError != Constants.NETWORK_TIMEOUT_MESSAGE)
                        {
                            LeanplumNative.CompatibilityLayer.LogError(responseError);
                        }
                    }
                    eventDataManager.InvokeAllCallbacksWithError(new LeanplumException("Error sending request: " + responseError));

                    LeanplumNative.CompatibilityLayer.LogDebug("Response Done");
                }
            }
                                                                                             );
        }