/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

using System;

using Term = Lucene.Net.Index.Term;
using PriorityQueue = Lucene.Net.Util.PriorityQueue;

namespace Lucene.Net.Search
{
	
	/// <summary>Implements parallel search over a set of <code>Searchables</code>.
	/// 
	/// <p>Applications usually need only call the inherited {@link #Search(Query)}
	/// or {@link #search(Query,Filter)} methods.
	/// </summary>
	public class ParallelMultiSearcher : MultiSearcher
	{
		private class AnonymousClassHitCollector1 : HitCollector
		{
			public AnonymousClassHitCollector1(Lucene.Net.Search.HitCollector results, int start, ParallelMultiSearcher enclosingInstance)
			{
				InitBlock(results, start, enclosingInstance);
			}
			private void  InitBlock(Lucene.Net.Search.HitCollector results, int start, ParallelMultiSearcher enclosingInstance)
			{
				this.results = results;
				this.start = start;
				this.enclosingInstance = enclosingInstance;
			}
			private Lucene.Net.Search.HitCollector results;
			private int start;
			private ParallelMultiSearcher enclosingInstance;
			public ParallelMultiSearcher Enclosing_Instance
			{
				get
				{
					return enclosingInstance;
				}
				
			}
			public override void  Collect(int doc, float score)
			{
				results.Collect(doc + start, score);
			}
		}
		
		private Lucene.Net.Search.Searchable[] searchables;
		private int[] starts;
		
		/// <summary>Creates a searcher which searches <i>searchables</i>. </summary>
		public ParallelMultiSearcher(Lucene.Net.Search.Searchable[] searchables) : base(searchables)
		{
			this.searchables = searchables;
			this.starts = GetStarts();
		}
		
		/// <summary> TODO: parallelize this one too</summary>
		public override int DocFreq(Term term)
		{
			return base.DocFreq(term);
		}
		
		/// <summary> A search implementation which spans a new thread for each
		/// Searchable, waits for each search to complete and merge
		/// the results back together.
		/// </summary>
		public override TopDocs Search(Weight weight, Filter filter, int nDocs)
		{
			HitQueue hq = new HitQueue(nDocs);
			int totalHits = 0;
			MultiSearcherThread[] msta = new MultiSearcherThread[searchables.Length];
			for (int i = 0; i < searchables.Length; i++)
			{
				// search each searcher
				// Assume not too many searchables and cost of creating a thread is by far inferior to a search
				msta[i] = new MultiSearcherThread(searchables[i], weight, filter, nDocs, hq, i, starts, "MultiSearcher thread #" + (i + 1));
				msta[i].Start();
			}
			
			for (int i = 0; i < searchables.Length; i++)
			{
				try
				{
					msta[i].Join();
				}
				catch (System.Threading.ThreadInterruptedException ie)
				{
					; // TODO: what should we do with this???
				}
				System.IO.IOException ioe = msta[i].GetIOException();
				if (ioe == null)
				{
					totalHits += msta[i].Hits();
				}
				else
				{
					// if one search produced an IOException, rethrow it
					throw ioe;
				}
			}
			
			ScoreDoc[] scoreDocs = new ScoreDoc[hq.Size()];
			for (int i = hq.Size() - 1; i >= 0; i--)
			// put docs in array
				scoreDocs[i] = (ScoreDoc) hq.Pop();
			
			float maxScore = (totalHits == 0) ? System.Single.NegativeInfinity : scoreDocs[0].score;
			
			return new TopDocs(totalHits, scoreDocs, maxScore);
		}
		
		/// <summary> A search implementation allowing sorting which spans a new thread for each
		/// Searchable, waits for each search to complete and merges
		/// the results back together.
		/// </summary>
		public override TopFieldDocs Search(Weight weight, Filter filter, int nDocs, Sort sort)
		{
			// don't specify the fields - we'll wait to do this until we get results
			FieldDocSortedHitQueue hq = new FieldDocSortedHitQueue(null, nDocs);
			int totalHits = 0;
			MultiSearcherThread[] msta = new MultiSearcherThread[searchables.Length];
			for (int i = 0; i < searchables.Length; i++)
			{
				// search each searcher
				// Assume not too many searchables and cost of creating a thread is by far inferior to a search
				msta[i] = new MultiSearcherThread(searchables[i], weight, filter, nDocs, hq, sort, i, starts, "MultiSearcher thread #" + (i + 1));
				msta[i].Start();
			}
			
			float maxScore = System.Single.NegativeInfinity;
			
			for (int i = 0; i < searchables.Length; i++)
			{
				try
				{
					msta[i].Join();
				}
				catch (System.Threading.ThreadInterruptedException ie)
				{
					; // TODO: what should we do with this???
				}
				System.IO.IOException ioe = msta[i].GetIOException();
				if (ioe == null)
				{
					totalHits += msta[i].Hits();
					maxScore = System.Math.Max(maxScore, msta[i].GetMaxScore());
				}
				else
				{
					// if one search produced an IOException, rethrow it
					throw ioe;
				}
			}
			
			ScoreDoc[] scoreDocs = new ScoreDoc[hq.Size()];
			for (int i = hq.Size() - 1; i >= 0; i--)
			// put docs in array
				scoreDocs[i] = (ScoreDoc) hq.Pop();
			
			return new TopFieldDocs(totalHits, scoreDocs, hq.GetFields(), maxScore);
		}
		
		/// <summary>Lower-level search API.
		/// 
		/// <p>{@link HitCollector#Collect(int,float)} is called for every non-zero
		/// scoring document.
		/// 
		/// <p>Applications should only use this if they need <i>all</i> of the
		/// matching documents.  The high-level search API ({@link
		/// Searcher#Search(Query)}) is usually more efficient, as it skips
		/// non-high-scoring hits.
		/// 
		/// </summary>
		/// <param name="weight">to match documents
		/// </param>
		/// <param name="filter">if non-null, a bitset used to eliminate some documents
		/// </param>
		/// <param name="results">to receive hits
		/// 
		/// </param>
		/// <todo>  parallelize this one too </todo>
		public override void  Search(Weight weight, Filter filter, HitCollector results)
		{
			for (int i = 0; i < searchables.Length; i++)
			{
				
				int start = starts[i];
				
				searchables[i].Search(weight, filter, new AnonymousClassHitCollector1(results, start, this));
			}
		}
		
		/*
		* TODO: this one could be parallelized too
		* @see Lucene.Net.Search.Searchable#rewrite(Lucene.Net.Search.Query)
		*/
		public override Query Rewrite(Query original)
		{
			return base.Rewrite(original);
		}
	}
	
	/// <summary> A thread subclass for searching a single searchable </summary>
	class MultiSearcherThread : SupportClass.ThreadClass
	{
		
		private Lucene.Net.Search.Searchable searchable;
		private Weight weight;
		private Filter filter;
		private int nDocs;
		private TopDocs docs;
		private int i;
		private PriorityQueue hq;
		private int[] starts;
		private System.IO.IOException ioe;
		private Sort sort;
		
		public MultiSearcherThread(Lucene.Net.Search.Searchable searchable, Weight weight, Filter filter, int nDocs, HitQueue hq, int i, int[] starts, System.String name):base(name)
		{
			this.searchable = searchable;
			this.weight = weight;
			this.filter = filter;
			this.nDocs = nDocs;
			this.hq = hq;
			this.i = i;
			this.starts = starts;
		}
		
		public MultiSearcherThread(Lucene.Net.Search.Searchable searchable, Weight weight, Filter filter, int nDocs, FieldDocSortedHitQueue hq, Sort sort, int i, int[] starts, System.String name):base(name)
		{
			this.searchable = searchable;
			this.weight = weight;
			this.filter = filter;
			this.nDocs = nDocs;
			this.hq = hq;
			this.i = i;
			this.starts = starts;
			this.sort = sort;
		}
		
		override public void  Run()
		{
			try
			{
				docs = (sort == null) ? searchable.Search(weight, filter, nDocs) : searchable.Search(weight, filter, nDocs, sort);
			}
			// Store the IOException for later use by the caller of this thread
			catch (System.IO.IOException ioe)
			{
				this.ioe = ioe;
			}
			if (this.ioe == null)
			{
				// if we are sorting by fields, we need to tell the field sorted hit queue
				// the actual type of fields, in case the original list contained AUTO.
				// if the searchable returns null for fields, we'll have problems.
				if (sort != null)
				{
					((FieldDocSortedHitQueue) hq).SetFields(((TopFieldDocs) docs).fields);
				}
				ScoreDoc[] scoreDocs = docs.scoreDocs;
				for (int j = 0; j < scoreDocs.Length; j++)
				{
					// merge scoreDocs into hq
					ScoreDoc scoreDoc = scoreDocs[j];
					scoreDoc.doc += starts[i]; // convert doc 
					//it would be so nice if we had a thread-safe insert 
					lock (hq)
					{
						if (!hq.Insert(scoreDoc))
							break;
					} // no more scores > minScore
				}
			}
		}
		
		public virtual int Hits()
		{
			return docs.totalHits;
		}
		
		public virtual float GetMaxScore()
		{
			return docs.GetMaxScore();
		}
		
		public virtual System.IO.IOException GetIOException()
		{
			return ioe;
		}
	}
}