/// <summary>
        /// The Update function won't accept a change to some values - specifically the billing interval. This creates a request
        /// that the API can understand for updates only
        /// </summary>
        /// <returns></returns>
        public ARBSubscriptionType ToUpdateableAPI()
        {
            var sub = new ARBSubscriptionType();

            sub.name = this.SubscriptionName;

            if (!String.IsNullOrEmpty(this.CardNumber) && (this.CardNumber.Trim().Length > 0))
            {
                DateTime dt;
                if (!CommonFunctions.ParseDateTime(this.CardExpirationYear, this.CardExpirationMonth, 1, out dt))
                {
                    throw new InvalidOperationException("Need a valid CardExpirationMonth and CardExpirationYear to set up this subscription");
                }

                var creditCard = new creditCardType
                {
                    cardNumber     = this.CardNumber,
                    expirationDate = dt.ToString("yyyy-MM")
                };
                //string.Format("{0}-{1}", this.CardExpirationYear, this.CardExpirationMonth);  // required format for API is YYYY-MM
                sub.payment = new paymentType {
                    Item = creditCard
                };
            }

            if ((this.eCheckBankAccount != null) && !String.IsNullOrEmpty(this.eCheckBankAccount.accountNumber) &&
                (this.eCheckBankAccount.accountNumber.Trim().Length > 0))
            {
                var eCheck = new bankAccountType()
                {
                    accountTypeSpecified = eCheckBankAccount.accountTypeSpecified,
                    accountType          = (bankAccountTypeEnum)Enum.Parse(typeof(bankAccountTypeEnum), eCheckBankAccount.accountType.ToString(), true),
                    routingNumber        = eCheckBankAccount.routingNumber,
                    accountNumber        = eCheckBankAccount.accountNumber,
                    nameOnAccount        = eCheckBankAccount.nameOnAccount,
                    echeckTypeSpecified  = eCheckBankAccount.echeckTypeSpecified,
                    echeckType           = (echeckTypeEnum)Enum.Parse(typeof(echeckTypeEnum), eCheckBankAccount.echeckType.ToString(), true),
                    bankName             = eCheckBankAccount.bankName,
                    checkNumber          = eCheckBankAccount.checkNumber
                };
                sub.payment = new paymentType {
                    Item = eCheck
                };
            }

            if (!String.IsNullOrEmpty(this.CustomerProfileId) && !String.IsNullOrEmpty(this.CustomerPaymentProfileId))
            {
                var customerProfile = new customerProfileIdType
                {
                    customerProfileId        = this.CustomerProfileId,
                    customerPaymentProfileId = this.CustomerPaymentProfileId,
                    customerAddressId        = this.CustomerAddressId
                };

                sub.profile = customerProfile;
            }
            else
            {
                sub.customer = new customerType
                {
                    email = this.CustomerEmail,
                    id    = this.CustomerID
                };
            }

            if (this.BillingAddress != null)
            {
                sub.billTo = this.BillingAddress.ToAPINameAddressType();
            }
            if (this.ShippingAddress != null)
            {
                sub.shipTo = this.ShippingAddress.ToAPINameAddressType();
            }

            sub.paymentSchedule = new paymentScheduleType
            {
                totalOccurrences          = this.BillingCycles,
                totalOccurrencesSpecified = true
            };

            sub.amount          = this.Amount;
            sub.amountSpecified = true;



            sub.order = new orderType
            {
                description   = this.Description,
                invoiceNumber = this.Invoice
            };

            return(sub);
        }
        /// <summary>
        /// This is mostly for internal processing needs - it takes the SubscriptionRequest and turns it into something the Gateway can serialize.
        /// </summary>
        /// <returns></returns>
        public ARBSubscriptionType ToAPI()
        {
            var sub = new ARBSubscriptionType();

            sub.name = this.SubscriptionName;

            bool          isCardValid    = false;
            bool          isBankValid    = false;
            bool          isProfileValid = false;
            StringBuilder sbError        = new StringBuilder("");
            bool          bError         = false;


            if (!String.IsNullOrEmpty(this.CardNumber) &&
                this.CardNumber.Trim().Length == 0)
            {
                isCardValid = true;
            }
            else if (this.eCheckBankAccount != null &&
                     !String.IsNullOrEmpty(this.eCheckBankAccount.accountNumber) &&
                     this.eCheckBankAccount.accountNumber.Trim().Length != 0)
            {
                isBankValid = true;
            }
            else if (!String.IsNullOrEmpty(this.CustomerProfileId) &&
                     !String.IsNullOrEmpty(this.CustomerPaymentProfileId))
            {
                isProfileValid = true;
            }

            if (!(isCardValid || isBankValid || isProfileValid))
            {
                sbError.Append("Need a credit card number or a bank account number to set up this subscription");
                bError = true;
            }

            DateTime dt = new DateTime();

            if (isCardValid && !CommonFunctions.ParseDateTime(this.CardExpirationYear, this.CardExpirationMonth, 1, out dt))
            {
                sbError.Append("Need a valid CardExpirationMonth and CardExpirationYear to set up this subscription");
                bError = true;
            }

            if (bError)
            {
                throw new InvalidOperationException(sbError.ToString());
            }

            if (isCardValid)
            {
                var creditCard = new creditCardType
                {
                    cardNumber = this.CardNumber,
                    // required format for API is YYYY-MM
                    expirationDate = dt.ToString("yyyy-MM")
                };
                sub.payment = new paymentType {
                    Item = creditCard
                };
            }
            else if (isBankValid)
            {
                var eCheck = new bankAccountType()
                {
                    accountTypeSpecified = eCheckBankAccount.accountTypeSpecified,
                    accountType          = (bankAccountTypeEnum)Enum.Parse(typeof(bankAccountTypeEnum), eCheckBankAccount.accountType.ToString(), true),
                    routingNumber        = eCheckBankAccount.routingNumber,
                    accountNumber        = eCheckBankAccount.accountNumber,
                    nameOnAccount        = eCheckBankAccount.nameOnAccount,
                    echeckTypeSpecified  = eCheckBankAccount.echeckTypeSpecified,
                    echeckType           = (echeckTypeEnum)Enum.Parse(typeof(echeckTypeEnum), eCheckBankAccount.echeckType.ToString(), true),
                    bankName             = eCheckBankAccount.bankName,
                    checkNumber          = eCheckBankAccount.checkNumber
                };
                sub.payment = new paymentType {
                    Item = eCheck
                };
            }
            else if (isProfileValid)
            {
                var customerProfile = new customerProfileIdType
                {
                    customerProfileId        = this.CustomerProfileId,
                    customerPaymentProfileId = this.CustomerPaymentProfileId,
                    customerAddressId        = this.CustomerAddressId
                };

                sub.profile = customerProfile;
            }

            if (this.BillingAddress != null)
            {
                sub.billTo = this.BillingAddress.ToAPINameAddressType();
            }
            if (this.ShippingAddress != null)
            {
                sub.shipTo = this.ShippingAddress.ToAPINameAddressType();
            }

            sub.paymentSchedule = new paymentScheduleType
            {
                startDate                 = this.StartsOn,
                startDateSpecified        = true,
                totalOccurrences          = this.BillingCycles,
                totalOccurrencesSpecified = true
            };


            // free 1 month trial
            if (this.TrialBillingCycles >= 0)
            {
                sub.paymentSchedule.trialOccurrences          = this.TrialBillingCycles;
                sub.paymentSchedule.trialOccurrencesSpecified = true;
            }

            if (this.TrialAmount >= 0)
            {
                sub.trialAmount          = this.TrialAmount;
                sub.trialAmountSpecified = true;
            }

            sub.amount          = this.Amount;
            sub.amountSpecified = true;

            sub.paymentSchedule.interval        = new paymentScheduleTypeInterval();
            sub.paymentSchedule.interval.length = this.BillingInterval;

            if (this.BillingIntervalUnits == BillingIntervalUnits.Months)
            {
                sub.paymentSchedule.interval.unit = ARBSubscriptionUnitEnum.months;
            }
            else
            {
                sub.paymentSchedule.interval.unit = ARBSubscriptionUnitEnum.days;
            }
            if (!isProfileValid)
            {
                sub.customer = new customerType
                {
                    email = this.CustomerEmail,
                    id    = this.CustomerID
                };
            }

            sub.order = new orderType
            {
                description   = this.Description,
                invoiceNumber = this.Invoice
            };

            return(sub);
        }