public IList <Message> GetMessagesNear(List <Message> messages,
                                               GeoJsonPoint coords,
                                               int radius           = 100,
                                               int skip             = -1,
                                               int limit            = -1,
                                               OrderDirection order = OrderDirection.None,
                                               CancellationToken ct = default)
        {
            DistanceCalcuationMethod calc;
            var queryResults = new List <Message>(messages.Count);

            for (var idx = 0; idx < messages.Count; idx++)
            {
                queryResults.Add(null);
            }

            var results = queryResults;

            if (radius >= ErrorMarginBoundary || messages.Count > MeasurementMargin)
            {
                calc = FastCalculateDistanceBetween;
            }
            else
            {
                calc = CalculateDistanceBetween;
            }

            var geoCoords = coords.ToCoordinates();

            Parallel.For(0, messages.Count, (index, state) => {
                double maxDist = radius;
                var message    = messages[index];
                var dist       = calc(geoCoords, message.Location.Coordinates);

                if (dist > maxDist)
                {
                    return;
                }

                results[index] = message;
            });

            queryResults.RemoveAll(x => x == null);

            queryResults = order switch {
                OrderDirection.Descending => queryResults.OrderByDescending(x => x.Timestamp).ToList(),
                OrderDirection.Ascending => queryResults.OrderBy(x => x.Timestamp).ToList(),
                _ => queryResults
            };

            if (skip > 0)
            {
                queryResults = queryResults.Skip(skip).ToList();
            }

            if (limit > 0)
            {
                queryResults = queryResults.Take(limit).ToList();
            }

            return(queryResults);
        }
    }
        public async Task <PaginationResult <AuditLog> > FindAsync(
            IEnumerable <string> uids,
            string text,
            RequestMethod method     = RequestMethod.Any,
            int skip                 = 0,
            int limit                = 0,
            OrderDirection direction = OrderDirection.None
            )
        {
            IQueryable <AuditLog> logs;
            var rv = new PaginationResult <AuditLog>();

            if (method == RequestMethod.Any)
            {
                if (text == null)
                {
                    logs =
                        from log in this.Data
                        where uids.Contains(log.AuthorId)
                        select log;
                }
                else
                {
                    logs =
                        from log in this.Data
                        where uids.Contains(log.AuthorId) &&
                        log.Route.Contains(text)
                        select log;
                }
            }
            else
            {
                if (text == null)
                {
                    logs = this.Data.Where(log => uids.Contains(log.AuthorId) && log.Method == method);
                }
                else
                {
                    logs = this.Data.Where(log => uids.Contains(log.AuthorId) && log.Method == method && log.Route.Contains(text));
                }
            }

            logs = direction switch {
                OrderDirection.Ascending => logs.OrderBy(x => x.Timestamp),
                OrderDirection.Descending => logs.OrderByDescending(x => x.Timestamp),
                _ => logs
            };

            rv.Count = await logs.CountAsync().AwaitBackground();

            if (skip > 0)
            {
                logs = logs.Skip(skip);
            }

            if (limit > 0)
            {
                logs = logs.Take(limit);
            }

            rv.Values = await logs.ToListAsync().AwaitBackground();

            foreach (var log in rv.Values)
            {
                log.Timestamp = DateTime.SpecifyKind(log.Timestamp, DateTimeKind.Utc);
            }

            return(rv);
        }