internal virtual FullTextSearchResult Search(FullTextQuery query, int maxResults, int timeLimit)
            {
                const int TICKS_PER_MSEC = 10000;

                if (query == null || !query.IsConstrained)
                {
                    return(null);
                }

                long stop = DateTime.Now.Ticks + (long)timeLimit * TICKS_PER_MSEC;

                buildOccurrenceKindWeightTable();
                kwdList = new ArrayList();
                query.Visit(this);
                kwds  = (KeywordList[])kwdList.ToArray(typeof(KeywordList));
                query = optimize(query);
                //Console.WriteLine(query.ToString());
                FullTextSearchHit[] hits = new FullTextSearchHit[maxResults];
                int   currDoc            = 1;
                int   nResults           = 0;
                float nearnessWeight     = impl.helper.NearnessWeight;
                bool  noMoreMatches      = false;

                while (nResults < maxResults && DateTime.Now.Ticks < stop)
                {
                    currDoc = intersect(currDoc, query);
                    if (currDoc == int.MaxValue)
                    {
                        noMoreMatches = true;
                        break;
                    }
                    reset();
                    double kwdRank = evaluate(currDoc, query);
                    if (kwdRank >= 0)
                    {
                        double nearness = calculateNearness();
                        float  rank     = (float)(kwdRank * (1 + calculateNearness() * nearnessWeight));
                        //Console.WriteLine("kwdRank=" + kwdRank + ", nearness=" + nearness + ", total rank=" + rank);
                        hits[nResults++] = new FullTextSearchHit(impl.Storage, currDoc, rank);
                    }
                    currDoc += 1;
                }
                int estimation;

                if (nResults < maxResults)
                {
                    FullTextSearchHit[] realHits = new FullTextSearchHit[nResults];
                    Array.Copy(hits, 0, realHits, 0, nResults);
                    hits = realHits;
                }
                if (noMoreMatches)
                {
                    estimation = nResults;
                }
                else if (query is FullTextQueryMatchOp)
                {
                    estimation = kwds[0].list.Count;
                }
                else
                {
                    estimation = calculateEstimation(query, nResults);
                }
                Array.Sort(hits);
                return(new FullTextSearchResult(hits, estimation));
            }