public async Task <INativeTrackResponse> ProcessTrackAsync(ITrackCriteria criteria, IUPSConfiguration configuration = null)
        {
            Track.UPSSecurity upsSecurity = configuration != null?SetupAuthentication <Track.UPSSecurity>(configuration?.Authentication) : UPSTrackAuthenticationDetail;

            var trackRequest = new Track.TrackRequest
            {
                InquiryNumber   = criteria.TrackingReferenceNumber,
                PickupDateRange = new Track.PickupDateRangeType
                {
                    BeginDate = criteria?.PickupDateRange?.BeginDate,
                    EndDate   = criteria?.PickupDateRange?.EndDate
                },
                ReferenceNumber = new Track.ReferenceNumberType
                {
                    Code  = criteria?.ReferenceNumber?.Code,
                    Value = criteria?.ReferenceNumber?.Value
                },
                ShipperNumber = criteria?.ShipperNumber,
                Request       = criteria?.RequestType != null ?
                                new Track.RequestType
                {
                    RequestOption        = criteria?.RequestType?.RequestOption,
                    SubVersion           = criteria?.RequestType?.SubVersion,
                    TransactionReference = criteria?.RequestType?.TransactionReference?.CustomerContext != null ?
                                           new Track.TransactionReferenceType
                    {
                        CustomerContext = criteria?.RequestType?.TransactionReference?.CustomerContext
                    } : UPSTrackTransactionReference
                } : new Track.RequestType()
                {
                    RequestOption = new string[] { "validate" }, TransactionReference = new Track.TransactionReferenceType {
                        CustomerContext = configuration?.Authentication?.CustomerContext ?? Configuration.Authentication.CustomerContext
                    }
                },
                TrackingOption = criteria?.TrackingOption
            };

            trackRequest.TrackingOption = trackRequest?.TrackingOption ?? configuration?.TrackConfiguration?.TrackingOption ?? Configuration?.TrackConfiguration?.TrackingOption;
            Track.TrackPortTypeClient client = new Track.TrackPortTypeClient();
            if (Configuration.AppSetupConfiguration.WriteXmlRequest)
            {
                WriteXML(trackRequest);
            }
            var response = await client.ProcessTrackAsync(upsSecurity, trackRequest);

            if (Configuration.AppSetupConfiguration.WriteXmlResponse)
            {
                WriteXML(response);
            }
            //var nativeResponse = BuildNativeTrackResponse(response);
            var nativeResponse = BuildResponse <Track.TrackResponse1, NativeTrackResponse>(response, TrackShipmentMapperConfiguration);

            nativeResponse.Message = nativeResponse.IsSuccessful ?
                                     string.Format(MessageConfiguration.SuccessfulShipmentTracking, criteria?.TrackingReferenceNumber)
                : string.Format(MessageConfiguration.FailedShipmentTracking, criteria?.TrackingReferenceNumber);
            return(nativeResponse);
        }
        public List <Track> GetTracks(ITrackCriteria trackCriteria)
        {
            if (!trackCriteria.CriteriaGroups.Any() &&
                !trackCriteria.OrderByProperty.HasValue &&
                !trackCriteria.MaxTracks.HasValue)
            {
                return(new List <Track>());
            }

            var tracks = new HashSet <Track>();

            if (!trackCriteria.CriteriaGroups.Any())
            {
                _library.Artists.SelectMany(a => a.Tracks)
                .ToList()
                .ForEach(t => tracks.Add(t));
            }
            else
            {
                foreach (var criteriaGroup in trackCriteria.CriteriaGroups)
                {
                    GetValidTracks(criteriaGroup).ForEach(t => tracks.Add(t));
                }
            }

            IEnumerable <Track> list = tracks;

            if (trackCriteria.OrderByProperty.HasValue)
            {
                var orderByFunction = _criteriaService.GetTrackOrderByFunction(trackCriteria.OrderByProperty.Value);

                list = trackCriteria.OrderByDescending
                    ? list.OrderByDescending(t => orderByFunction(t))
                    : list.OrderBy(t => orderByFunction(t));
            }

            if (trackCriteria.MaxTracks.HasValue)
            {
                list = list.Take(trackCriteria.MaxTracks.Value);
            }

            return(list.ToList());
        }