/// <summary>
        /// Creates a single discount in Shopify
        /// </summary>
        public static void CreateDiscount(AuthInfo authInfo, Discount discount)
        {
            try
            {
                Console.Write("Creating {0}: ", discount.Code);

                string discountsUrl = String.Format(_discountsUrl, authInfo.StoreName,"");
                HttpWebRequest request = HttpWebRequest.Create(discountsUrl) as HttpWebRequest;

                // Set required HTTP headers
                request.Accept = "*/*";
                request.Headers["Accept-Language"] = "en-US";
                request.Headers["Accept-Charset"] = "utf-8";
                request.Headers["X-Requested-With"] = "XMLHttpRequest";
                request.Headers["X-Prototype-Version"] = "1.7";
                request.Headers["Cookie"] = String.Format("_secure_session_id={0}", authInfo.SessionId);
                request.Headers["X-CSRF-Token"] = authInfo.CsrfToken;

                // POST the create discount form
                IDictionary<string, string> postData = new Dictionary<string, string>();
                postData["authenticity_token"] = authInfo.CsrfToken;
                postData["discount[code]"] = discount.Code;
                postData["type"] = discount.Type;
                postData["discount[value]"] = discount.Value;
                postData["discount[applies_to_type]"] = discount.AppliesToType;
                postData["discount[minimum_order_amount]"] = discount.MinimumOrderAmount;
                postData["discount[applies_to_id]"] = discount.AppliesToId;
                postData["discount[starts_at]"] = discount.StartsAt;
                postData["discount[ends_at]"] = discount.EndsAt;
                postData["discount[usage_limit]"] = discount.UsageLimit;
                HttpWebResponse response = request.Post(postData);

                // Read response in.
                string responseText = response.GetResponseText();

                // Check for application level errors
                if (responseText.Contains("Messenger.error(\""))
                {
                    string errorMessage = responseText.GetFirstDelimitedValue("Messenger.error(\"", "\");");
                    throw new Exception(errorMessage);
                }

                // Check for success
                string successNotice = String.Format("Messenger.notice(\"Successfully created the discount {0}\\u0026hellip;\");", discount.Code);
                if (!responseText.Contains(successNotice))
                {
                    throw new Exception("Sanity check failed");
                }

                Console.WriteLine("OK");

            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR");

                string errorMessage = String.Format("Error Creating Discount ({0})", ( discount == null ? "" : discount.Code) );
                throw new Exception(errorMessage, ex);
            }
        }
        /// <summary>
        /// Helper method to parse the HTML screen scraped from the Shopify discounts page.
        /// </summary>
        private static Discount ParseDiscount(HtmlNode discountRow)
        {
            Discount discount = new Discount();

            Console.Write("Parsing Discount: ");
            try
            {
                string temp = null;

                // Id
                discount.Id = discountRow.Attributes["id"].Value.Replace("discount-", "");

                // Code
                discount.Code = discountRow.SelectSingleNode("td[position()=1]//strong").InnerHtml.Trim();

                // MinimumOrderAmount
                discount.MinimumOrderAmount = "0"; // Required

                temp = discountRow.SelectSingleNode("td[position()=2]").InnerHtml.Trim();
                if (temp.Contains("free shipping to"))
                {
                    // Type
                    discount.Type = "shipping";

                    // Value
                    Match match = Regex.Match(temp, "\\$[0-9]+\\.[0-9]{2}");
                    if (match.Success)
                    {
                        discount.Value = match.Value.Replace("$", "");
                    }

                    temp = discountRow.SelectSingleNode("td[position()=2]//strong").InnerHtml.Trim();
                    switch (temp)
                    {
                        case "Anywhere":

                            // AppliesToId
                            discount.AppliesToId = String.Empty;

                            break;
                        case "Rest of World":

                            // AppliesToId
                            discount.AppliesToId = "2848952";

                            // AppliesToType
                            discount.AppliesToType = "Country";

                            break;
                        case "United States":

                            // AppliesToId
                            discount.AppliesToId = "2848942";

                            // AppliesToType
                            discount.AppliesToType = "Country";

                            break;
                        // TODO: Other countries here???
                    }
                }
                else
                {
                    temp = discountRow.SelectSingleNode("td[position()=2]//strong").InnerHtml.Trim();
                    if (temp.Contains('$'))
                    {
                        // Type
                        discount.Type = "fixed_amount";

                        // Value
                        discount.Value = temp.Replace("$", "");
                    }
                    else if (temp.Contains('%'))
                    {
                        // Type
                        discount.Type = "percentage";

                        // Value
                        discount.Value = temp.Replace("%", "").Trim();
                    }

                    temp = discountRow.SelectSingleNode("td[position()=2]").OuterHtml.GetFirstDelimitedValue("</strong>", "</td>").ToLower();
                    if (temp.Contains("off of the collection"))
                    {
                        // AppliesToType
                        discount.AppliesToType = "Collection"; // Collection
                    }
                    else if (temp.Contains("off of"))
                    {
                        // AppliesToType
                        discount.AppliesToType = "Product"; // Product
                    }
                    else if (temp.Contains("off orders equal or above"))
                    {
                        // AppliesToType
                        discount.AppliesToType = "minimum_order_amount";

                        // MinimumOrderAmount
                        discount.MinimumOrderAmount = temp.Substring(temp.IndexOf('$') + 1).Trim();
                    }

                    if (discount.AppliesToType == "Product" || discount.AppliesToType == "Collection")
                    {
                        temp = discountRow.SelectSingleNode("td[position()=2]//a").Attributes["href"].Value;

                        // AppliesToId
                        discount.AppliesToId = temp.Substring(temp.LastIndexOf('/') + 1).Trim();
                    }
                }

                HtmlNodeCollection details = discountRow.SelectNodes("td[position()=3]//li");
                if (details != null)
                {
                    foreach (HtmlNode li in details)
                    {
                        if (Regex.IsMatch(li.InnerText, "Used [0-9]+ time[s]?"))
                        {
                            // UsageCount
                            discount.UsageCount = Regex.Match(li.InnerText, "[0-9]+").Value;
                        }
                        else if (Regex.IsMatch(li.InnerText, "[0-9]+ use[s]? remaining"))
                        {
                            // UsageLimit
                            temp = Regex.Match(li.InnerText, "[0-9]+").Value; // Uses Remaining
                            discount.UsageLimit = (Int32.Parse(discount.UsageCount) + Int32.Parse(temp)).ToString();
                        }
                        else if (Regex.IsMatch(li.InnerText, "Starts [A-Za-z0-9 ]+, ends [A-Za-z0-9 ]+"))
                        {
                            // StartsAt
                            discount.StartsAt = (DateTime.Parse(Regex.Matches(li.InnerText, "[A-Za-z]{3} [0-9]{2}( [0-9]{4})?")[0].Value)).ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);

                            // EndsAt
                            discount.EndsAt = (DateTime.Parse(Regex.Matches(li.InnerText, "[A-Za-z]{3} [0-9]{2}( [0-9]{4})?")[1].Value)).ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);
                        }
                        else if (li.InnerText.StartsWith("Starts"))
                        {
                            // StartAt
                            discount.StartsAt = (DateTime.Parse(Regex.Match(li.InnerText, "[A-Za-z]{3} [0-9]{2}( [0-9]{4})?").Value)).ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);
                        }
                        else if (li.InnerText.StartsWith("Ends"))
                        {
                            // EndsAt
                            discount.EndsAt = (DateTime.Parse(Regex.Match(li.InnerText, "[A-Za-z]{3} [0-9]{2}( [0-9]{4})?").Value)).ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);
                        }

                    }
                }

                // Enabled
                discount.Enabled = discountRow.SelectSingleNode("td[position()=4]//a[position()=1]").InnerHtml.Equals("Disable discount").ToString();

                Console.WriteLine("OK");
            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR");

                string errorMessage = String.Format("Error Parsing Discount ({0})", (discount == null ? "" : discount.Code));
                throw new Exception(errorMessage, ex);
            }
            return discount;
        }