/// <summary>
        ///  Gets available shipping options
        /// </summary>
        /// <param name="getShippingOptionRequest">A request for getting shipping options</param>
        /// <returns>Represents a response of getting shipping rate options</returns>
        public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest getShippingOptionRequest)
        {
            if (getShippingOptionRequest == null)
                throw new ArgumentNullException("getShippingOptionRequest");

            var response = new GetShippingOptionResponse();

            if (getShippingOptionRequest.Items == null || getShippingOptionRequest.Items.Count == 0)
            {
                response.AddError("No shipment items");
                return response;
            }

            int? restrictByCountryId = (getShippingOptionRequest.ShippingAddress != null && getShippingOptionRequest.ShippingAddress.Country != null) ? (int?)getShippingOptionRequest.ShippingAddress.Country.Id : null;
            var shippingMethods = this._shippingService.GetAllShippingMethods(restrictByCountryId);
            foreach (var shippingMethod in shippingMethods)
            {
                var shippingOption = new ShippingOption();
                shippingOption.Name = shippingMethod.GetLocalized(x => x.Name);
                shippingOption.Description = shippingMethod.GetLocalized(x => x.Description);
                shippingOption.Rate = GetRate(shippingMethod.Id);
                response.ShippingOptions.Add(shippingOption);
            }

            return response;
        }
        public void Can_get_typed_value()
        {	
			"1000".Convert<int>().ShouldBe<int>();
			"1000".Convert<int>().ShouldEqual(1000);

			var intList = "1,2,3,4,5".Convert<List<int>>();
			intList.ShouldBe<List<int>>();
			Assert.AreEqual(5, intList.Count);
			Assert.AreEqual(3, intList[2]);

			var strList = "one,two,three".Convert<List<string>>();
			strList.ShouldBe<List<string>>();
			Assert.AreEqual(3, strList.Count);
			Assert.AreEqual("two", strList[1]);

			double dbl = 3;
			var r1 = dbl.Convert<int?>();
			r1.ShouldBe<int?>();
			Assert.AreEqual(r1.Value, 3);

			var shippingOption = new ShippingOption { Name = "Name", Description = "Desc", Rate = 1, ShippingRateComputationMethodSystemName = "SystemName" };
			var soStr = shippingOption.Convert<string>();
			Assert.IsNotEmpty(soStr);

			shippingOption = soStr.Convert<ShippingOption>();
			Assert.IsNotNull(shippingOption);
			Assert.AreEqual(shippingOption.Name, "Name");
			Assert.AreEqual(shippingOption.Description, "Desc");
			Assert.AreEqual(shippingOption.Rate, 1);
			Assert.AreEqual(shippingOption.ShippingRateComputationMethodSystemName, "SystemName");

			var shippingOptions = new List<ShippingOption> { 
				new ShippingOption { Name = "Name1", Description = "Desc1" },
				new ShippingOption { Name = "Name2", Description = "Desc2" }
			};
			soStr = shippingOptions.Convert<string>();
			Assert.IsNotEmpty(soStr);

			shippingOptions = soStr.Convert<List<ShippingOption>>();
			Assert.AreEqual(shippingOptions.Count, 2);
			Assert.AreEqual(shippingOptions[1].Description, "Desc2");

			var shippingOptions2 = soStr.Convert<IList<ShippingOption>>();
			Assert.AreEqual(shippingOptions2.Count, 2);
			Assert.AreEqual(shippingOptions2[1].Description, "Desc2");

			var enu = SmartStore.Core.Domain.Catalog.AttributeControlType.FileUpload;
			Assert.AreEqual((int)enu, enu.Convert<int>());
			Assert.AreEqual("FileUpload", enu.Convert<string>());
        }
        public void Can_convert_shippingOption_to_string_and_back()
        {
            var shippingOptionInput = new ShippingOption()
            {
                Name = "1",
                Description = "2",
                Rate = 3.57M,
                ShippingRateComputationMethodSystemName = "4"
            };
            var converter = TypeDescriptor.GetConverter(shippingOptionInput.GetType());
            var result = converter.ConvertTo(shippingOptionInput, typeof(string)) as string;

            var shippingOptionOutput = converter.ConvertFrom(result) as ShippingOption;
            shippingOptionOutput.ShouldNotBeNull();
            shippingOptionOutput.Name.ShouldEqual("1");
            shippingOptionOutput.Description.ShouldEqual("2");
            shippingOptionOutput.Rate.ShouldEqual(3.57M);
            shippingOptionOutput.ShippingRateComputationMethodSystemName.ShouldEqual("4");
        }
        /// <summary>
        ///  Gets available shipping options
        /// </summary>
        /// <param name="getShippingOptionRequest">A request for getting shipping options</param>
        /// <returns>Represents a response of getting shipping rate options</returns>
        public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest getShippingOptionRequest)
        {
            if (getShippingOptionRequest == null)
                throw new ArgumentNullException("getShippingOptionRequest");

            var response = new GetShippingOptionResponse();

            if (getShippingOptionRequest.Items == null || getShippingOptionRequest.Items.Count == 0)
            {
                response.AddError("No shipment items");
                return response;
            }

            int storeId = _storeContext.CurrentStore.Id;
            decimal subTotal = decimal.Zero;
            int countryId = 0;

            if (getShippingOptionRequest.ShippingAddress != null)
            {
                countryId = getShippingOptionRequest.ShippingAddress.CountryId ?? 0;
            }

            foreach (var shoppingCartItem in getShippingOptionRequest.Items)
            {
                if (shoppingCartItem.Item.IsFreeShipping || !shoppingCartItem.Item.IsShipEnabled)
                    continue;
                subTotal += _priceCalculationService.GetSubTotal(shoppingCartItem, true);
            }
            decimal weight = _shippingService.GetShoppingCartTotalWeight(getShippingOptionRequest.Items);

            var shippingMethods = _shippingService.GetAllShippingMethods(countryId);
            foreach (var shippingMethod in shippingMethods)
            {
                var record = _shippingByWeightService.FindRecord(shippingMethod.Id, storeId, countryId, weight);

                decimal? rate = GetRate(subTotal, weight, shippingMethod.Id, storeId, countryId);
                if (rate.HasValue)
                {
                    var shippingOption = new ShippingOption();
                    shippingOption.Name = shippingMethod.GetLocalized(x => x.Name);

                    if (record != null && record.SmallQuantityThreshold > subTotal)
                    {
                        shippingOption.Description = shippingMethod.GetLocalized(x => x.Description)
                            + _localizationService.GetResource("Plugin.Shipping.ByWeight.SmallQuantitySurchargeNotReached").FormatWith(
                                _priceFormatter.FormatPrice(record.SmallQuantitySurcharge),
                                _priceFormatter.FormatPrice(record.SmallQuantityThreshold));

                        shippingOption.Rate = rate.Value + record.SmallQuantitySurcharge;
                    }
                    else {
                        shippingOption.Description = shippingMethod.GetLocalized(x => x.Description);
                        shippingOption.Rate = rate.Value;
                    }
                    response.ShippingOptions.Add(shippingOption);
                }
            }

            return response;
        }
        /// <summary>
        ///  Gets available shipping options
        /// </summary>
        /// <param name="getShippingOptionRequest">A request for getting shipping options</param>
        /// <returns>Represents a response of getting shipping rate options</returns>
        public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest getShippingOptionRequest)
        {
            if (getShippingOptionRequest == null)
            {
                throw new ArgumentNullException("getShippingOptionRequest");
            }

            var response = new GetShippingOptionResponse();

            if (getShippingOptionRequest.Items == null || getShippingOptionRequest.Items.Count == 0)
            {
                response.AddError("No shipment items");
                return response;
            }
            if (getShippingOptionRequest.ShippingAddress == null)
            {
                response.AddError("Shipping address is not set");
                return response;
            }

			var storeId = _storeContext.CurrentStore.Id;
            int countryId = getShippingOptionRequest.ShippingAddress.CountryId.HasValue ? getShippingOptionRequest.ShippingAddress.CountryId.Value : 0;
            int stateProvinceId = getShippingOptionRequest.ShippingAddress.StateProvinceId.HasValue ? getShippingOptionRequest.ShippingAddress.StateProvinceId.Value : 0;
            string zip = getShippingOptionRequest.ShippingAddress.ZipPostalCode;
            decimal subTotal = decimal.Zero;

            foreach (var shoppingCartItem in getShippingOptionRequest.Items)
            {
                if (shoppingCartItem.Item.IsFreeShipping || !shoppingCartItem.Item.IsShipEnabled)
                {
                    continue;
                }
                subTotal += _priceCalculationService.GetSubTotal(shoppingCartItem, true);
            }

            decimal sqThreshold = _shippingByTotalSettings.SmallQuantityThreshold;
            decimal sqSurcharge = _shippingByTotalSettings.SmallQuantitySurcharge;

            var shippingMethods = _shippingService.GetAllShippingMethods(countryId);
            foreach (var shippingMethod in shippingMethods)
            {
                decimal? rate = GetRate(subTotal, shippingMethod.Id, storeId, countryId, stateProvinceId, zip);
                if (rate.HasValue)
                {
                    if (rate > 0 && sqThreshold > 0 && subTotal <= sqThreshold)
                    {
                        // add small quantity surcharge (Mindermengenzuschalg)
                        rate += sqSurcharge;
                    }
                    
                    var shippingOption = new ShippingOption();
                    shippingOption.Name = shippingMethod.Name;
                    shippingOption.Description = shippingMethod.Description;
                    shippingOption.Rate = rate.Value;
                    response.ShippingOptions.Add(shippingOption);
                }
            }

            return response;
        }
        /// <summary>
        ///  Gets available shipping options
        /// </summary>
        /// <param name="getShippingOptionRequest">A request for getting shipping options</param>
        /// <returns>Represents a response of getting shipping rate options</returns>
        public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest getShippingOptionRequest)
        {
            if (getShippingOptionRequest == null)
                throw new ArgumentNullException("getShippingOptionRequest");

            var response = new GetShippingOptionResponse();

            if (getShippingOptionRequest.Items == null || getShippingOptionRequest.Items.Count == 0)
            {
                response.AddError("No shipment items");
                return response;
            }
            if (getShippingOptionRequest.ShippingAddress == null)
            {
                response.AddError("Shipping address is not set");
                return response;
            }

			var storeId = _storeContext.CurrentStore.Id;
            int countryId = getShippingOptionRequest.ShippingAddress.CountryId.HasValue ? getShippingOptionRequest.ShippingAddress.CountryId.Value : 0;
            
            decimal subTotal = decimal.Zero;
            foreach (var shoppingCartItem in getShippingOptionRequest.Items)
            {
                if (shoppingCartItem.Item.IsFreeShipping || !shoppingCartItem.Item.IsShipEnabled)
                    continue;
                subTotal += _priceCalculationService.GetSubTotal(shoppingCartItem, true);
            }
            decimal weight = _shippingService.GetShoppingCartTotalWeight(getShippingOptionRequest.Items);

            var shippingMethods = _shippingService.GetAllShippingMethods(countryId);
            foreach (var shippingMethod in shippingMethods)
            {
                decimal? rate = GetRate(subTotal, weight, shippingMethod.Id, storeId, countryId);
                if (rate.HasValue)
                {
                    var shippingOption = new ShippingOption();
                    shippingOption.Name = shippingMethod.GetLocalized(x => x.Name);
                    shippingOption.Description = shippingMethod.GetLocalized(x => x.Description);
                    shippingOption.Rate = rate.Value;
                    response.ShippingOptions.Add(shippingOption);
                }
            }


            return response;
        }
        /// <summary>
        ///  Gets available shipping options
        /// </summary>
        /// <param name="getShippingOptionRequest">A request for getting shipping options</param>
        /// <returns>Represents a response of getting shipping rate options</returns>
        public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest getShippingOptionRequest)
        {
            if (getShippingOptionRequest == null)
                throw new ArgumentNullException("getShippingOptionRequest");

            var response = new GetShippingOptionResponse();

            if (getShippingOptionRequest.Items == null || getShippingOptionRequest.Items.Count == 0)
            {
                response.AddError(T("Admin.System.Warnings.NoShipmentItems"));
                return response;
            }

            var shippingMethods = this._shippingService.GetAllShippingMethods(getShippingOptionRequest);
            foreach (var shippingMethod in shippingMethods)
            {
                var shippingOption = new ShippingOption();
                shippingOption.ShippingMethodId = shippingMethod.Id;
                shippingOption.Name = shippingMethod.GetLocalized(x => x.Name);
                shippingOption.Description = shippingMethod.GetLocalized(x => x.Description);
                shippingOption.Rate = GetRate(shippingMethod.Id);
                response.ShippingOptions.Add(shippingOption);
            }

            return response;
        }