/// <summary>
        /// Add a customer charge for a customer
        /// </summary>
        /// <param name="customCharge">A CustomerChargePost object with the customer charge and customer code</param>
        /// <returns>A Customer object with the reflected custom charge</returns>
        public static Customer AddCustomCharge(CustomChargePost customCharge)
        {
            Customers customers = new Customers();
            Customer editCustomer = new Customer();

            try
            {
                string urlBase = "https://cheddargetter.com/xml";
                string urlPath = string.Format("/customers/set-item-quantity/productCode/{0}/code/{1}/itemCode/{2}", _ProductCode, customCharge.CustomerCode, customCharge.ItemCode);
                string postParams = string.Format(
                  "chargeCode={0}" +
                  "&quantity={1}" +
                  "&eachAmount={2}" +
                  "&description={3}",
                  HttpUtility.UrlEncode(customCharge.ChargeCode),
                  HttpUtility.UrlEncode(customCharge.Quantity.ToString()),
                  HttpUtility.UrlEncode(customCharge.EachAmount.ToString()),
                  HttpUtility.UrlEncode(customCharge.Description));

                string result = postRequest(urlBase, urlPath, postParams);
                XDocument newCustomerXML = XDocument.Parse(result);

                customers = getCustomerList(newCustomerXML);

                if (customers.CustomerList.Count > 0)
                {
                    editCustomer = customers.CustomerList[0];
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }

            return editCustomer;
        }
        /// <summary>
        /// Get the customer list and any associated CG errors from a XDocument (customer XML)
        /// </summary>
        /// <param name="customersXML">A XDocument that contains customer XML data</param>
        /// <returns>A Customers object (which is a list of customers and any associated GC errors) 
        /// that is built from the parsed XDocument</returns>
        private static Customers getCustomerList(XDocument customersXML)
        {
            Customers customers = new Customers();
            List<Customer> customerList = new List<Customer>();
            List<CGError> errorList = new List<CGError>();

            try
            {
                customerList = (from c in customersXML.Descendants("customer")
                                select new Customer
                                {
                                    ID = (Guid)c.Attribute("id"),
                                    Code = (string)c.Attribute("code"),
                                    FirstName = (string)c.Element("firstName"),
                                    LastName = (string)c.Element("lastName"),
                                    Company = (string)c.Element("company"),
                                    Notes = (string)c.Element("notes"),
                                    Email = (string)c.Element("email"),
                                    GatewayToken = (string)c.Element("gatewayToken"),

                                    CreatedDateTime = ParseTime(c.Element("createdDatetime").Value),
                                    ModifiedDateTime = ParseTime(c.Element("modifiedDatetime").Value),
                                    Subscriptions = getSubscriptionList(c.Element("subscriptions")),
                                }).ToList();

                errorList = (from e in customersXML.Descendants("errors")
                             select new CGError
                             {
                                 ID = (string)e.Attribute("id"),
                                 Code = (string)e.Attribute("code"),
                                 AuxCode = (string)e.Attribute("auxCode"),
                                 Message = (string)e.Element("error")
                             }).ToList();

                customers.CustomerList = customerList;
                customers.ErrorList = errorList;

            }
            catch (Exception ex)
            {
                throw ex;
            }

            return customers;
        }
        /// <summary>
        /// Update a customer's subscription
        /// </summary>
        /// <param name="customer">A CustomerPost object with the subscription details to update</param>
        /// <returns>A Customer object with the applied changes</returns>
        public static Customer UpdateSubscription(CustomerPost customer)
        {
            Customers customers = new Customers();
            Customer updatedCustomer = new Customer();

            try
            {
                // Create the web request
                string urlBase = "https://cheddargetter.com/xml";
                string urlPath = string.Format("/customers/edit-subscription/productCode/{0}/code/{1}", _ProductCode, customer.Code);

                //note: expiration date must be in MM/YYYY format
                StringBuilder postParamsSB = new StringBuilder();
                postParamsSB.Append(string.Format("planCode={0}", HttpUtility.UrlEncode(customer.PlanCode.ToString().ToUpper())));
                postParamsSB.Append(string.Format("&ccFirstName={0}", HttpUtility.UrlEncode(customer.CCFirstName)));
                postParamsSB.Append(string.Format("&ccLastName={0}", HttpUtility.UrlEncode(customer.CCLastName)));

                if (!string.IsNullOrEmpty(customer.CCNumber))
                {
                    postParamsSB.Append(string.Format("&ccNumber={0}", HttpUtility.UrlEncode(customer.CCNumber)));
                }

                postParamsSB.Append(string.Format("&ccExpiration={0}", HttpUtility.UrlEncode(string.Format("{0}/{1}", formatMonth(customer.CCExpMonth), customer.CCExpYear))));

                if (!string.IsNullOrEmpty(customer.CCCardCode))
                {
                    postParamsSB.Append(string.Format("&ccCardCode={0}", HttpUtility.UrlEncode(customer.CCCardCode)));
                }

                postParamsSB.Append(string.Format("&ccZip={0}", HttpUtility.UrlEncode(customer.CCZip)));

                string result = postRequest(urlBase, urlPath, postParamsSB.ToString());
                XDocument newCustomerXML = XDocument.Parse(result);

                customers = getCustomerList(newCustomerXML);

                if (customers.CustomerList.Count > 0)
                {
                    updatedCustomer = customers.CustomerList[0];
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return updatedCustomer;
        }
        /// <summary>
        /// Update a customer's subscription plan
        /// </summary>
        /// <param name="customerCode">The customer's code of the customer to be updated</param>
        /// <param name="newPlan">The plan to set the customer to</param>
        /// <returns>A Customer object with the updated changes applied</returns>
        public static Customer UpdateSubscriptionPlanOnly(string customerCode, string newPlan)
        {
            Customers customers = new Customers();
            Customer updatedCustomer = new Customer();

            try
            {
                // Create the web request
                string urlBase = "https://cheddargetter.com/xml";
                string urlPath = string.Format("/customers/edit-subscription/productCode/{0}/code/{1}", _ProductCode, customerCode);

                //note: expiration date must be in MM/YYYY format
                string postParams = string.Format("planCode={0}", HttpUtility.UrlEncode(newPlan.ToString().ToUpper()));

                string result = postRequest(urlBase, urlPath, postParams);
                XDocument newCustomerXML = XDocument.Parse(result);

                customers = getCustomerList(newCustomerXML);

                if (customers.CustomerList.Count > 0)
                {
                    updatedCustomer = customers.CustomerList[0];
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return updatedCustomer;
        }
        /// <summary>
        /// Update a customer
        /// </summary>
        /// <param name="customer">A CustomerPost object that represents the changes to be updated</param>
        /// <returns>An updated Customer object with the changes applied</returns>
        public static Customer UpdateCustomer(CustomerPost customer)
        {
            Customers customers = new Customers();
            Customer updatedCustomer = new Customer();

            try
            {
                // Create the web request
                string urlBase = "https://cheddargetter.com/xml";
                string urlPath = string.Format("/customers/edit-customer/productCode/{0}/code/{1}", _ProductCode, customer.Code);
                string postParams = string.Format(
                    "firstName={0}" +
                    "&lastName={1}" +
                    "&email={2}" +
                    "&company={3}"+
                    "&notes={4}",
                    HttpUtility.UrlEncode(customer.FirstName),
                    HttpUtility.UrlEncode(customer.LastName),
                    HttpUtility.UrlEncode(customer.Email),
                    HttpUtility.UrlEncode(customer.Company),
                    HttpUtility.UrlEncode(customer.Notes));

                string result = postRequest(urlBase, urlPath, postParams);

                XDocument newCustomerXML = XDocument.Parse(result);

                customers = getCustomerList(newCustomerXML);

                if (customers.CustomerList.Count > 0)
                {
                    updatedCustomer = customers.CustomerList[0];
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return updatedCustomer;
        }
        /// <summary>
        /// Update a customer and their subscription
        /// </summary>
        /// <param name="customer">A CustomerPost object that represents the changes to be updated</param>
        /// <returns>An updated Customer object with the changes applied</returns>
        public static Customer UpdateCustomerAndSubscription(CustomerPost customer)
        {
            Customers customers = new Customers();
            Customer updatedCustomer = new Customer();

            try
            {
                //we don't want to send an empty cc number
                //if the customer isn't updating the card number
                if (customer.CCNumber != "")
                {
                    // Create the web request
                    string urlBase = "https://cheddargetter.com/xml";
                    string urlPath = string.Format("/customers/edit/productCode/{0}/code/{1}", _ProductCode, customer.Code);
                    string postParams = string.Format(
                        "firstName={0}" +
                        "&lastName={1}" +
                        "&email={2}" +
                        "&company={3}" +
                        "&notes={4}" +
                        "&subscription[planCode]={5}" +
                        "&subscription[ccFirstName]={6}" +
                        "&subscription[ccLastName]={7}" +
                        "&subscription[ccNumber]={8}" +
                        "&subscription[ccExpiration]={9}" +
                        "&subscription[ccCardCode]={10}" +
                        "&subscription[ccZip]={11}",
                        HttpUtility.UrlEncode(customer.FirstName),
                        HttpUtility.UrlEncode(customer.LastName),
                        HttpUtility.UrlEncode(customer.Email),
                        HttpUtility.UrlEncode(customer.Company),
                        HttpUtility.UrlEncode(customer.Notes),
                        HttpUtility.UrlEncode(customer.PlanCode.ToUpper()),
                        HttpUtility.UrlEncode(customer.CCFirstName),
                        HttpUtility.UrlEncode(customer.CCLastName),
                        HttpUtility.UrlEncode(customer.CCNumber),
                        HttpUtility.UrlEncode(string.Format("{0}/{1}", formatMonth(customer.CCExpMonth), customer.CCExpYear)),
                        HttpUtility.UrlEncode(customer.CCCardCode),
                        HttpUtility.UrlEncode(customer.CCZip));
                    string result = postRequest(urlBase, urlPath, postParams);

                    XDocument newCustomerXML = XDocument.Parse(result);

                    customers = getCustomerList(newCustomerXML);

                    if (customers.CustomerList.Count > 0)
                    {
                        updatedCustomer = customers.CustomerList[0];
                    }
                }
                else
                {
                    // Create the web request
                    string urlBase = "https://cheddargetter.com/xml";
                    string urlPath = string.Format("/customers/edit/productCode/{0}/code/{1}", _ProductCode, customer.Code);
                    string postParams = string.Format(
                        "firstName={0}" +
                        "&lastName={1}" +
                        "&email={2}" +
                        "&company={3}" +
                        "&notes={4}" +
                        "&subscription[planCode]={5}" +
                        "&subscription[ccFirstName]={6}" +
                        "&subscription[ccLastName]={7}" +
                        "&subscription[ccExpiration]={8}" +
                        "&subscription[ccCardCode]={9}" +
                        "&subscription[ccZip]={10}",
                        HttpUtility.UrlEncode(customer.FirstName),
                        HttpUtility.UrlEncode(customer.LastName),
                        HttpUtility.UrlEncode(customer.Email),
                        HttpUtility.UrlEncode(customer.Company),
                        HttpUtility.UrlEncode(customer.Notes),
                        HttpUtility.UrlEncode(customer.PlanCode.ToUpper()),
                        HttpUtility.UrlEncode(customer.CCFirstName),
                        HttpUtility.UrlEncode(customer.CCLastName),
                        HttpUtility.UrlEncode(string.Format("{0}/{1}", formatMonth(customer.CCExpMonth), customer.CCExpYear)),
                        HttpUtility.UrlEncode(customer.CCCardCode),
                        HttpUtility.UrlEncode(customer.CCZip));
                    string result = postRequest(urlBase, urlPath, postParams);

                    XDocument newCustomerXML = XDocument.Parse(result);

                    customers = getCustomerList(newCustomerXML);

                    if (customers.CustomerList.Count > 0)
                    {
                        updatedCustomer = customers.CustomerList[0];
                    }
                }

                //if (result.IndexOf("Error") > -1)
                //{

                //}
                //else
                //{

                //}
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return updatedCustomer;
        }
        /// <summary>
        /// Refunds the charge.
        /// </summary>
        /// <param name="refund">The refund.</param>
        /// <returns></returns>
        public static Customer RefundCharge(RefundChargePost refund)
        {
            Customers customers = new Customers();
            Customer refundCustomer = new Customer();

            try
            {
                string urlBase = "https://cheddargetter.com/xml";
                string urlPath = string.Format("/invoices/refund/productCode/{0}/", _ProductCode);
                string postParams = string.Format(
                  "number={0}" +
                  "&amount={1}",
                  HttpUtility.UrlEncode(refund.InvoiceNumber),
                  HttpUtility.UrlEncode(refund.RefundAmount.ToString()));

                string result = postRequest(urlBase, urlPath, postParams);
                XDocument newCustomerXML = XDocument.Parse(result);

                customers = getCustomerList(newCustomerXML);

                if (customers.CustomerList.Count > 0)
                {
                    refundCustomer = customers.CustomerList[0];
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }

            return refundCustomer;
        }
        /// <summary>
        /// Set an item count to a specific quantity
        /// </summary>
        /// <param name="customerCode">The customer's code of the customer that will be updated </param>
        /// <param name="itemCode">The code of the item that will be updated</param>
        /// <param name="quantityToSet">The quantity to set for the item</param>
        /// <returns>A Customer object reflecting the updated item and quantity count</returns>
        public static Customer SetItem(string customerCode, ProductItemCode itemCode, int quantityToSet)
        {
            Customers customers = new Customers();
            Customer editCustomer = new Customer();

            try
            {
                string urlBase = "https://cheddargetter.com/xml";
                string urlPath = string.Format("/customers/set-item-quantity/productCode/{0}/code/{1}/itemCode/{2}", _ProductCode, customerCode, itemCode.ToString());
                string postParams = string.Format("quantity={0}", HttpUtility.UrlEncode(quantityToSet.ToString()));

                string result = postRequest(urlBase, urlPath, postParams);
                XDocument newCustomerXML = XDocument.Parse(result);

                customers = getCustomerList(newCustomerXML);

                if (customers.CustomerList.Count > 0)
                {
                    editCustomer = customers.CustomerList[0];
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }

            return editCustomer;
        }
        /// <summary>
        /// Issues the void.
        /// </summary>
        /// <param name="voidinvoice">The voidinvoice.</param>
        /// <returns></returns>
        public static Customer IssueVoid(IssueVoidPost voidinvoice)
        {
            Customers customers = new Customers();
            Customer voidCustomer = new Customer();

            try
            {
                string urlBase = "https://cheddargetter.com/xml";
                string urlPath = string.Format("/invoices/void/productCode/{0}/", _ProductCode);
                string postParams = string.Format(
                  "number={0}",
                  HttpUtility.UrlEncode(voidinvoice.InvoiceNumber));

                string result = postRequest(urlBase, urlPath, postParams);
                XDocument newCustomerXML = XDocument.Parse(result);

                customers = getCustomerList(newCustomerXML);

                if (customers.CustomerList.Count > 0)
                {
                    voidCustomer = customers.CustomerList[0];
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }

            return voidCustomer;
        }
        /// <summary>
        /// Get a list of all customers for your product code
        /// </summary>
        /// <returns>A list of Customer objects</returns>
        public static List<Customer> GetCustomers()
        {
            Customers customers = new Customers();

            try
            {
                string urlBase = "https://cheddargetter.com/xml";
                string urlPath = string.Format("/customers/get/productCode/{0}", _ProductCode);

                string result = getRequest(urlBase, urlPath);
                XDocument customersXML = XDocument.Parse(result);

                customers = getCustomerList(customersXML);
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return customers.CustomerList;
        }
        /// <summary>
        /// Get a particular customer based on a passed in customer code and your product code
        /// </summary>
        /// <param name="customerCode">A string representing a customer's code in CG </param>
        /// <returns>A associated Customer object for the passed in customer code</returns>
        public static Customer GetCustomer(string customerCode)
        {
            Customers customers = new Customers();
            Customer customer = new Customer();

            string urlBase = "https://cheddargetter.com/xml";
            string urlPath = string.Format("/customers/get/productCode/{0}", _ProductCode);

            try
            {
                string result = getRequest(urlBase, urlPath);

                XDocument customersXML = XDocument.Parse(result);

                customers = getCustomerList(customersXML);

                if (customers.CustomerList.Count > 0)
                {
                    customer = customers.CustomerList.First(x => x.Code == customerCode);
                }
            }
            catch (WebException ex)
            {
                HttpWebResponse response = (HttpWebResponse)ex.Response;
                if (response.StatusCode == HttpStatusCode.NotFound)
                {
                    return null;
                }
                throw ex;
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return customer;
        }
        public static bool DeleteCustomer(string customerCode)
        {
            Customers customers = new Customers();
            Customer deleteCustomer = new Customer();
            bool deleted = false;

            try
            {
                string urlBase = "https://cheddargetter.com/xml";
                string urlPath = string.Format("/customers/delete/productCode/{0}/code/{1}", _ProductCode, customerCode);

                string result = getRequest(urlBase, urlPath);
                XDocument newCustomerXML = XDocument.Parse(result);

                customers = getCustomerList(newCustomerXML);

                if (customers.CustomerList.Count > 0)
                {
                    deleteCustomer = customers.CustomerList[0];
                }

                deleted = true;
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return deleted;
        }
        /// <summary>
        /// Create a new customer based on the passed in CustomerPost object
        /// </summary>
        /// <param name="customer">A CustomerPost object that represents a customer to be created</param>
        /// <returns>A newly created Customer object</returns>
        public static Customer CreateCustomer(CustomerPost customer)
        {
            Customers customers = new Customers();
            Customer newCustomer = new Customer();

            try
            {
                string urlBase = "https://cheddargetter.com/xml";
                string urlPath = string.Format("/customers/new/productCode/{0}", _ProductCode);
                string postParams = string.Format(
                    "code={0}" +
                    "&firstName={1}" +
                    "&lastName={2}" +
                    "&email={3}" +
                    "&company={4}" +
                    "&subscription[planCode]={5}" +
                    "&subscription[ccFirstName]={6}" +
                    "&subscription[ccLastName]={7}" +
                    "&subscription[method]={8}" +
                    "&subscription[returnUrl]={9}" +
                    "&subscription[cancelUrl]={10}" +
                    "&subscription[couponCode]={11}",

                    HttpUtility.UrlEncode(customer.Code),
                    HttpUtility.UrlEncode(customer.FirstName),
                    HttpUtility.UrlEncode(customer.LastName),
                    HttpUtility.UrlEncode(customer.Email),
                    HttpUtility.UrlEncode(customer.Company),
                    HttpUtility.UrlEncode(customer.PlanCode),
                    HttpUtility.UrlEncode(customer.CCFirstName),
                    HttpUtility.UrlEncode(customer.CCLastName),
                    HttpUtility.UrlEncode("paypal"),
                    HttpUtility.UrlEncode("http://www.maxcut.co.za"),
                    HttpUtility.UrlEncode("http://www.maxcut.co.za"),
                    HttpUtility.UrlEncode(customer.CouponCode));

                string result = postRequest(urlBase, urlPath, postParams);
                XDocument newCustomerXML = XDocument.Parse(result);

                customers = getCustomerList(newCustomerXML);

                OpenWebBrowserTo(customers.CustomerList.First().Subscriptions.First().RedirectURL);

                if (customers.CustomerList.Count > 0)
                {
                    newCustomer = customers.CustomerList[0];
                }
            }
            catch (Exception ex)
            {

                throw ex;

            }

            return newCustomer;
        }