/// <summary>
        /// Before posting a shipment, you can retrieve the carrier’s shipment rules, including the available services and parcel types, with
        /// weight and dimension restrictions.
        ///
        /// Things to Consider:
        ///     * The call to retrieve rate rules is an expensive API call because of the size of the returned data.It is recommended that you
        ///     cache the returned data and make the API call only once a day.
        ///     * At the top level, rules are organized by service type.
        ///     * Within a service type, each set of rules applies to a combination of parcel type (parcelTypeRules.parcelType) and rate type
        ///     (parcelTypeRules.rateTypeId).
        ///
        /// Rules tell you:
        ///     * Compatible special services (parcelTypeRules.specialServiceRules)
        ///     * Required special services (parcelTypeRules.specialServiceRules.prerequisiteRules)
        ///     * Incompatible special services (parcelTypeRules.specialServiceRules.incompatibleSpecialServices)
        ///     * Required input parameters (parcelTypeRules.specialServiceRules.inputParameterRules)
        ///     * Weight constraints (parcelTypeRules.weightRules)
        ///     * Dimension constraints (parcelTypeRules.dimensionRules)
        /// <param name="request"></param>
        /// <param name="session"></param>
        /// <returns></returns>
        /// </summary>
        public async static Task <ShippingApiResponse <CarrierRule> > RatingServices(RatingServicesRequest request, ISession session = null)
        {
            var response = await WebMethod.Get <ServiceRule[], RatingServicesRequest>("/shippingservices/v1/information/rules/rating-services", request, session);

            var carrierRuleResponse = new ShippingApiResponse <CarrierRule>
            {
                Errors     = response.Errors,
                HttpStatus = response.HttpStatus,
                Success    = response.Success
            };

            if (response.Success)
            {
                carrierRuleResponse.APIResponse = new CarrierRule()
                {
                    Carrier            = request.Carrier,
                    DestinationCountry = request.DestinationCountryCode,
                    OriginCountry      = request.OriginCountryCode,
                    ServiceRules       = new IndexedList <Services, ServiceRule>()
                };
                foreach (var s in response.APIResponse)
                {
                    carrierRuleResponse.APIResponse.ServiceRules.Add(s.ServiceId, s);
                }
            }
            return(carrierRuleResponse);
        }
        public void TestPrintLabelSurchargeAdhoc()
        {
            ShippingApiResponse response = TestFile("printLabel_surcharge_Adhoc.txt");

            Assert.NotNull(response);
            Assert.NotNull(response.ResponseObject);
        }
        public void TestStandardMail()
        {
            ShippingApiResponse response = TestFile("StdMail.txt");

            Assert.NotNull(response);
            Assert.NotNull(response.ResponseObject);
        }
        public void TestPrintLabelDomesticAdhoc()
        {
            ShippingApiResponse response = TestFile("printLabel_Domestic_Adhoc.txt");

            Assert.NotNull(response);
            Assert.NotNull(response.ResponseObject);
        }
        public void TestPrintLabelDomesticValueOfGoods()
        {
            ShippingApiResponse response = TestFile("printLabel_Domestic_valueOfGoods.txt");

            Assert.NotNull(response);
            Assert.NotNull(response.ResponseObject);
        }
        public void TestNewgistics()
        {
            ShippingApiResponse response = TestFile("Newgistics.txt");

            Assert.NotNull(response);
            Assert.NotNull(response.ResponseObject);
        }
        public void TestPrintLabelCubic()
        {
            ShippingApiResponse response = TestFile("printLabel_Cubic.txt");

            Assert.NotNull(response);
            Assert.NotNull(response.ResponseObject);
        }
        public void TestCubaEMIPkg()
        {
            ShippingApiResponse response = TestFile("cuba_emi_pkg.txt");

            Assert.NotNull(response);
            Assert.NotNull(response.ResponseObject);
        }
        public void TestAddressesVerify()
        {
            ShippingApiResponse response = TestFile("addresses_verify.txt");

            Assert.NotNull(response);
            Assert.NotNull(response.ResponseObject);
        }
        //[Fact]   // need to have UPS account set up
        public void TestUPS()
        {
            ShippingApiResponse response = TestFile("UPS.txt");

            Assert.NotNull(response);
            Assert.NotNull(response.ResponseObject);
        }
#pragma warning disable CS1998 // No async operations in mock
        /// <summary>
        /// Implements the same method as the real service interface allowing the mock to be plugged in
        /// </summary>
        /// <typeparam name="Response"></typeparam>
        /// <typeparam name="Request"></typeparam>
        /// <param name="resource"></param>
        /// <param name="verb"></param>
        /// <param name="request"></param>
        /// <param name="deleteBody"></param>
        /// <param name="session"></param>
        /// <returns></returns>
        public async Task <ShippingApiResponse <Response> > HttpRequest <Response, Request>(string resource, HttpVerb verb, Request request, bool deleteBody, ISession session = null) where Request : IShippingApiRequest
        {
            string fullPath = request.RecordingFullPath(resource, session);

            if (File.Exists(fullPath))
            {
                var apiResponse = new ShippingApiResponse <Response> {
                    HttpStatus = HttpStatusCode.OK, Success = true
                };
                long jsonPosition = 0;
                using (var fileStream = new FileStream(fullPath, FileMode.Open, FileAccess.Read))
                    using (var mimeStream = new MimeStream(fileStream))
                    {
                        mimeStream.SeekNextPart(); //request
                        mimeStream.SeekNextPart(); //response
                        mimeStream.ClearHeaders();
                        mimeStream.ReadHeaders();  // reads http headers as well
                        if (!mimeStream.FirstLine.StartsWith("HTTP", StringComparison.InvariantCulture))
                        {
                            apiResponse = new ShippingApiResponse <Response> {
                                HttpStatus = HttpStatusCode.InternalServerError, Success = false
                            };
                            session.LogDebug(string.Format("Mock request failed {0}", fullPath));
                            apiResponse.Errors.Add(new ErrorDetail()
                            {
                                ErrorCode = "Mock 500", Message = "Bad format " + fullPath
                            });
                            return(apiResponse);
                        }
                        var hrc = mimeStream.FirstLine.Split(' ');
                        apiResponse.HttpStatus = (HttpStatusCode)int.Parse(hrc[1]);
                        apiResponse.Success    = apiResponse.HttpStatus == HttpStatusCode.OK;

                        foreach (var h in mimeStream.Headers)
                        {
                            apiResponse.ProcessResponseAttribute(h.Key, h.Value);
                        }

                        using (var recordingStream = new RecordingStream(mimeStream, request.RecordingFullPath(resource, session), FileMode.Create, RecordingStream.RecordType.PlainText))
                        {
                            try
                            {
                                //dont open the record file
                                recordingStream.IsRecording = false;
                                ShippingApiResponse <Response> .Deserialize(session, recordingStream, apiResponse, jsonPosition);
                            }
                            catch (Exception ex)
                            {
                                session.LogError(string.Format("Mock request {0} got deserialization exception {1}", fullPath, ex.Message));
                                throw ex;
                            }
                        }
                    }
                return(apiResponse);
            }

            else
            {
                var apiResponse = new ShippingApiResponse <Response> {
                    HttpStatus = HttpStatusCode.NotFound, Success = false
                };
                session.LogDebug(string.Format("Mock request failed {0}", fullPath));
                apiResponse.Errors.Add(new ErrorDetail()
                {
                    ErrorCode = "Mock 401", Message = "Could not find response file" + fullPath
                });
                return(apiResponse);
            }
        }
        public void BasicRate()
        {
            List <string> fromAddressLine = new List <string>()
            {
                "8445 Graves Ave #25"
            };

            List <string> toAddressLine = new List <string>()
            {
                "10553 KERRIGAN Ct"
            };

            Address fromAddress = new Address
            {
                AddressLines  = fromAddressLine,
                Email         = "*****@*****.**",
                CityTown      = "Santee",
                Name          = "X X",
                CountryCode   = "US",
                PostalCode    = "92071",
                StateProvince = "CA",
            };

            Address toAddress = new Address
            {
                AddressLines  = toAddressLine,
                Email         = "*****@*****.**",
                CityTown      = "Santee",
                Name          = "X",
                CountryCode   = "US",
                PostalCode    = "92071",
                StateProvince = "CA",
            };


            ParcelDimension parcelDimension = new ParcelDimension
            {
                Height            = 1,
                Length            = 1,
                Width             = 1,
                UnitOfMeasurement = UnitOfDimension.IN
            };

            ParcelWeight parcelWeight = new ParcelWeight
            {
                UnitOfMeasurement = UnitOfWeight.OZ,
                Weight            = 1
            };

            Parcel parcel = new Parcel
            {
                CurrencyCode = "US",
                Dimension    = parcelDimension,
                Weight       = parcelWeight
            };

            Rates rates = new Rates
            {
                Carrier    = Carrier.USPS,
                ParcelType = ParcelType.LGENV
            };

            Shipment shipment = new Shipment
            {
                FromAddress = fromAddress,
                ToAddress   = toAddress,
                Parcel      = parcel,
                Rates       = new List <Rates> {
                    rates
                }
            };

            try
            {
                // Get rates
                ShippingApiResponse shippingApiResponse = Api.Rates(shipment).Result;
            }
            catch (Exception)
            {
                throw;
            }
        }