/// <summary>
        /// Called to save a customer to the device
        /// </summary>
        /// <param name="e">The event arguments</param>
        /// <param name="smsSendAttempts">Number of attempts</param>
        /// <param name="smsAttemptLimit">The Limit</param>
        /// <returns>An empty task</returns>
        private async Task SaveCustomerToDevice(CustomerService.RegistrationStatusChangedEventArgs e, int smsSendAttempts, int smsAttemptLimit)
        {
            bool succeeded = e.SmsRegistrationSucceeded || e.Response.RegistrationSuccessful;

            if (!succeeded)
            {
                this.Logger.Debug(string.Format("Sms send attempts = {0} and sms send limts = {1}", smsSendAttempts, smsAttemptLimit));

                succeeded = e.Channel == DataChannel.Fallback && smsAttemptLimit == smsSendAttempts;
                if (!succeeded)
                {
                    return;
                }
            }

            this.Logger.Debug("Attempting to save customer to device");
            if (e.Response == null || e.Response.Customer == null)
            {
                return;
            }

            ProspectsController prospectsController = new ProspectsController();

            Mkopa.Core.BL.Models.People.Prospect prospect = await prospectsController
                                                            .GetByPhoneNumberAsync(e.Response.Customer.Phone);

            await Resolver.Instance.Get <ISQLiteDB>().Connection.RunInTransactionAsync(
                async(SQLiteConnection connTran) =>
            {
                try
                {
                    this.Logger.Debug("Trying to save customer");
                    CustomersController customersController = new CustomersController();
                    e.Response.Customer.Channel             = e.Channel;
                    string customerPhone = e.Response.Customer.Phone;
                    Guid custGuid;

                    Mkopa.Core.BL.Models.People.Customer customer =
                        await customersController.GetSingleByCriteria(CriteriaBuilder.New()
                                                                      .Add("Phone", customerPhone));

                    // customer to have more than one product
                    if (customer == null || customer.Id == default(Guid))
                    {
                        SaveResponse <Mkopa.Core.BL.Models.People.Customer> saveResponse =
                            await customersController.SaveAsync(connTran, e.Response.Customer, true);

                        if (saveResponse.SavedModel == null || saveResponse.SavedModel.Id == default(Guid))
                        {
                            new ReusableScreens(this.Activity)
                            .ShowInfo(
                                Resource.String.customer_save_err_actionbar,
                                Resource.String.customer_save_err_title,
                                Resource.String.customer_save_err_message,
                                Resource.String.customer_save_err_button);
                            return;
                        }
                        custGuid = saveResponse.SavedModel.Id;
                    }
                    else
                    {
                        custGuid = customer.Id;
                    }

                    await this.SaveCustomerProductToDevice(custGuid, connTran);

                    if (prospect != null)
                    {
                        this.Logger.Debug("There was a prospect with the same number so we convert to customer");
                        prospect.Converted = true;
                        await prospectsController.SaveAsync(connTran, prospect);
                    }

                    RecordStatus syncStatus = e.Channel == DataChannel.Fallback
                                ? (e.SmsRegistrationSucceeded
                                    ? RecordStatus.FallbackSent
                                    : RecordStatus.Pending)
                                : RecordStatus.Synced;

                    SyncingController syncController = new SyncingController();

                    SyncRecord syncRec = await syncController.GetSyncRecordAsync(e.Response.Customer.RequestId);
                    this.Logger.Debug("Fetching sync record for customer");

                    if (syncRec == null)
                    {
                        this.Logger.Debug("The sync record is null so we generate one");
                        syncRec = new SyncRecord
                        {
                            ModelId   = e.Response.Customer.Id,
                            ModelType = e.Response.Customer.TableName,
                            Status    = syncStatus,
                            RequestId = e.Response.Customer.RequestId
                        };
                        this.Logger.Debug("Saving generated sync record");
                        SaveResponse <SyncRecord> syncSaveResponse = await syncController.SaveAsync(
                            connTran,
                            syncRec);

                        this.Logger.Debug("Sync record was saved correctly");
                    }
                    else
                    {
                        syncRec.Status = syncStatus;
                    }

                    await syncController.SaveAsync(connTran, syncRec);
                }
                catch (Exception exception)
                {
                    this.Logger.Error(exception);
                }
            });
        }
        /// <summary>
        /// Called when registration information has changed
        /// </summary>
        /// <param name="sender">The sender</param>
        /// <param name="e">The event arguments</param>
        private async void RegistrationStatusChanged(object sender, CustomerService.RegistrationStatusChangedEventArgs e)
        {
            this.registrationFailedFragment     = null;
            this.registrationSuccessfulFragment = null;

            this.Logger.Verbose(e.Response != null ? e.Response.ResponseText : "No response...");

            this.maxSmsTries = Settings.Instance.MaxFallbackRetries;

            // still trying to post via API
            if (!e.Response.Successful && e.Channel != DataChannel.Fallback)
            {
                // still trying to register customer, show progress
                string message       = this.WizardActivity.GetString(Resource.String.not_able_to_send);
                string messageDetail = string.Format(this.WizardActivity.GetString(Resource.String.retrying), e.NumberOfTries);
                this.WizardActivity.ShowWaitInfo(message, messageDetail);
            }
            else if (e.Response.RegistrationSuccessful)
            {
                this.savingProgress = SavingProgress.Succeeded;

                // make sure we show the processing fragment for some time
                // await this.FragmentShowAwaiter(this.processingShown, DateTime.Now);

                // pass boolean whether the registration was SMS to control the message to the user
                this.registrationSuccessfulFragment = new RegistrationFinishedFragment();
                Bundle arguments = new Bundle();
                arguments.PutBoolean(RegistrationFinishedFragment.WasRegistrationKey, e.Channel == DataChannel.Fallback);
                arguments.PutBoolean(RegistrationFinishedFragment.SuccessKey, true);
                arguments.PutString(RegistrationFinishedFragment.IntentStartPointKey, this.ActivityBase.StartPointIntent.ToString());
                this.registrationSuccessfulFragment.Arguments = arguments;
                this.WizardActivity.ShowOverlay(this.registrationSuccessfulFragment, true);
            }
            else if (e.Response.Successful && !e.Response.RegistrationSuccessful)
            {
                // if registration is not done, show error
                this.savingProgress = SavingProgress.Failed;

                // make sure we show the processing fragment for some time
                await this.FragmentShowAwaiter(this.processingShown, DateTime.Now);

                // pass boolean whether the registration was SMS to control the message to the user
                this.registrationFailedFragment = new RegistrationFinishedFragment();/*
                                                                                      * e.Channel == DataChannel.Fallback,
                                                                                      * true,
                                                                                      * this.ActivityBase.StartPointIntent);*/

                Bundle arguments = new Bundle();
                arguments.PutBoolean(RegistrationFinishedFragment.WasRegistrationKey, e.Channel == DataChannel.Fallback);
                arguments.PutBoolean(RegistrationFinishedFragment.SuccessKey, true);
                arguments.PutString(RegistrationFinishedFragment.IntentStartPointKey, this.ActivityBase.StartPointIntent.ToString());
                this.registrationFailedFragment.Arguments = arguments;

                this.WizardActivity.ShowOverlay(this.registrationFailedFragment, true);
            }
            else if (e.Channel == DataChannel.Fallback)
            {
                // process the case of SMS
                this.savingProgress = SavingProgress.Failed;

                // make sure we show the processing fragment for some time
                await this.FragmentShowAwaiter(this.processingShown, DateTime.Now);

                this.smsFailed++;

                // depending on how many times SMS failed, decide what to show
                string posButtonTxt;
                string negButtonTxt;
                if (this.smsFailed >= this.maxSmsTries)
                {
                    posButtonTxt = this.WizardActivity.GetString(Resource.String.add_new_customer);
                    switch (this.ActivityBase.StartPointIntent)
                    {
                    case IntentStartPointTracker.IntentStartPoint.CustomerList:
                        negButtonTxt = this.WizardActivity.GetString(Resource.String.prospect_followup_return_to_customer_list);
                        break;

                    case IntentStartPointTracker.IntentStartPoint.ProspectsList:
                        negButtonTxt = this.WizardActivity.GetString(Resource.String.prospect_followup_return_to_prospect_list);
                        break;

                    case IntentStartPointTracker.IntentStartPoint.WelcomeScreen:
                        negButtonTxt = this.WizardActivity.GetString(Resource.String.return_to_home);
                        break;

                    default:
                        negButtonTxt = this.WizardActivity.GetString(Resource.String.return_to_home);
                        break;
                    }
                }
                else
                {
                    posButtonTxt = this.WizardActivity.GetString(Resource.String.try_again);
                    negButtonTxt = this.WizardActivity.GetString(Resource.String.cancel_registration);
                }

                bool stillTryingToSendSms = this.smsFailed < this.maxSmsTries;

                // SMS must have failed otherwise if statement before would have caught it
                string message = stillTryingToSendSms
                    ? this.WizardActivity.GetString(Resource.String.sms_registration_failed)
                    : string.Format(this.WizardActivity.GetString(Resource.String.unified_sms_registration_failed_n_tries), this.smsFailed);

                this.registrationFailedFragment = new RegistrationFinishedFragment();

                /*
                 *  e.Channel == DataChannel.Fallback,
                 *  false,
                 *  message,
                 *  posButtonTxt,
                 *  negButtonTxt,
                 *  this.ActivityBase.StartPointIntent);
                 */

                Bundle arguments = new Bundle();
                arguments.PutBoolean(RegistrationFinishedFragment.WasRegistrationKey, e.Channel == DataChannel.Fallback);
                arguments.PutBoolean(RegistrationFinishedFragment.SuccessKey, false);
                arguments.PutString(RegistrationFinishedFragment.MessageKey, message);
                arguments.PutString(RegistrationFinishedFragment.BtnPositiveKey, posButtonTxt);
                arguments.PutString(RegistrationFinishedFragment.BtnNegativeKey, negButtonTxt);
                arguments.PutString(RegistrationFinishedFragment.IntentStartPointKey, this.ActivityBase.StartPointIntent.ToString());
                this.registrationFailedFragment.Arguments = arguments;

                // depending on sms retries, decide the event hadler
                if (this.smsFailed >= this.maxSmsTries)
                {
                    (this.registrationFailedFragment as RegistrationFinishedFragment).PositiveAction += delegate
                    {
                        WizardLauncher.Launch(this.Activity, WizardTypes.CustomerRegistration, ActivityBase.StartPointIntent);
                        (this.WizardActivity as Activity).Finish();
                    };

                    (this.registrationFailedFragment as RegistrationFinishedFragment).NegativeAction += this.OnCancel;
                }
                else
                {
                    (this.registrationFailedFragment as RegistrationFinishedFragment).PositiveAction += this.Save;
                    (this.registrationFailedFragment as RegistrationFinishedFragment).NegativeAction += this.OnCancel;
                }

                this.WizardActivity.ShowOverlay(this.registrationFailedFragment, true);
            }

            await this.SaveCustomerToDevice(e, this.smsFailed, this.maxSmsTries);

            this.registrationInProgress = false;
            this.savingProgress         = SavingProgress.Done;
        }