/*=============================================================================#
 # Copyright (c) 2014, 2019 Stephan Wahlbrink and others.
 # 
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License 2.0 which is available at
 # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.internal.rhelp.core.index;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
import org.apache.lucene.queryparser.flexible.core.QueryNodeParseException;
import org.apache.lucene.queryparser.flexible.standard.StandardQueryParser;
import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler.Operator;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermInSetQuery;

import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.jcommons.status.ErrorStatus;
import org.eclipse.statet.jcommons.status.StatusException;

import org.eclipse.statet.internal.rhelp.core.RHelpCoreInternals;
import org.eclipse.statet.rhelp.core.RHelpCore;
import org.eclipse.statet.rhelp.core.RHelpSearchQuery;


@NonNullByDefault
public final class REnvIndexSearchQuery implements REnvIndexSchema {
	
	
	private static final ImList<String> TOPIC_SEARCH_FIELDS= ImCollections.newList(
			ALIAS_FIELD_NAME );
	
	private static final ImList<String> DOC_SEARCH_FIELDS= ImCollections.newList(
			TITLE_TXT_FIELD_NAME,
			DESCRIPTION_TXT_FIELD_NAME,
			DOC_TXT_FIELD_NAME,
			EXAMPLES_TXT_FIELD_NAME );
	
	private static final Map<String, Float> FIELD_BOOSTS= new HashMap<>();
	static { // see BoostQuery
		FIELD_BOOSTS.put(ALIAS_TXT_FIELD_NAME, 2.0f);
		FIELD_BOOSTS.put(TITLE_TXT_FIELD_NAME, 2.0f);
		FIELD_BOOSTS.put(DESCRIPTION_TXT_FIELD_NAME, 1.5f);
		FIELD_BOOSTS.put(EXAMPLES_TXT_FIELD_NAME, 0.5f);
	}
	
	
	private final static Analyzer QUERY_ANALYZER= new DefaultAnalyzer();
	
	
	public static REnvIndexSearchQuery compile(final RHelpSearchQuery searchQuery) throws StatusException {
		try {
			Query query= null;
			ImList<String> fields= ImCollections.emptyList();
			if (searchQuery.getSearchString().length() > 0) {
				switch (searchQuery.getSearchType()) {
				case RHelpSearchQuery.TOPIC_SEARCH:
					fields= TOPIC_SEARCH_FIELDS;
					query= createMainQuery(searchQuery.getSearchString(), fields, null);
					break;
				case RHelpSearchQuery.FIELD_SEARCH:
					fields= sortFields(searchQuery.getEnabledFields());
					if (fields.isEmpty()) {
						break;
					}
					query= createMainQuery(searchQuery.getSearchString(), fields, FIELD_BOOSTS);
					break;
				case RHelpSearchQuery.DOC_SEARCH:
					fields= DOC_SEARCH_FIELDS;
					query= createMainQuery(searchQuery.getSearchString(), fields, FIELD_BOOSTS);
					break;
				default:
					break;
				}
			}
			
			final List<Query> filters= new ArrayList<>(4);
			{	final List<String> packages= searchQuery.getPackages();
				if (!packages.isEmpty()) {
					filters.add(new TermInSetQuery(PACKAGE_FIELD_NAME,
							REnvIndexUtils.toByteRefTerms(packages) ));
				}
			}
			{	final List<String> keywords= searchQuery.getKeywords();
				if (!keywords.isEmpty()) {
					filters.add(new TermInSetQuery(KEYWORD_FIELD_NAME,
							REnvIndexUtils.toByteRefTerms(keywords) ));
				}
			}
			filters.add(REnvIndexReader.DOCTYPE_PAGE_FILTER);
			
			return new REnvIndexSearchQuery(query, fields, filters);
		}
		catch (final QueryNodeParseException e) {
			RHelpCoreInternals.log(new ErrorStatus(RHelpCore.BUNDLE_ID,
					String.format("An error occurred when creating the Lucene query for: %1$s.", //$NON-NLS-1$
							searchQuery.toString() ),
					e ));
			throw new StatusException(new ErrorStatus(RHelpCore.BUNDLE_ID,
					"The search string is invalid: " + e.getLocalizedMessage() ));
		}
		catch (final Exception e) {
			RHelpCoreInternals.log(new ErrorStatus(RHelpCore.BUNDLE_ID,
					String.format("An error occurred when creating the Lucene query for %1$s.", //$NON-NLS-1$
							searchQuery.toString() ),
					e ));
			throw new StatusException(new ErrorStatus(RHelpCore.BUNDLE_ID,
					"An error occurred when preparing the R help query." ));
		}
	}
	
	private static ImList<String> sortFields(final List<String> fields) {
		return ImCollections.toList(fields, new Comparator<String>() {
			@Override
			public int compare(final String o1, final String o2) {
				return getRank(o1) - getRank(o2);
			}
		});
	}
	
	
	static Query createMainQuery(final String queryText,
			final ImList<String> fields, final @Nullable Map<String, Float> fieldBoosts) throws QueryNodeException {
		final StandardQueryParser p= new StandardQueryParser(QUERY_ANALYZER);
		p.setDefaultOperator(Operator.AND);
		p.setAllowLeadingWildcard(true);
		p.setMultiFields(fields.toArray(new String[fields.size()]));
		if (fieldBoosts != null) {
			p.setFieldsBoost(fieldBoosts);
		}
		return p.parse(queryText, null);
	}
	
	
	private static int getRank(final String o) {
		if (o == PAGE_FIELD_NAME) {
			return 1;
		}
		if (o == ALIAS_FIELD_NAME || o == ALIAS_TXT_FIELD_NAME) {
			return 2;
		}
		if (o == TITLE_TXT_FIELD_NAME) {
			return 3;
		}
		if (o == CONCEPT_TXT_FIELD_NAME) {
			return 4;
		}
		if (o == DESCRIPTION_TXT_FIELD_NAME) {
			return 5;
		}
		if (o == DOC_TXT_FIELD_NAME || o == DOC_HTML_FIELD_NAME) {
			return 6;
		}
		if (o == EXAMPLES_TXT_FIELD_NAME) {
			return 15;
		}
		return 10;
	}
	
	
	public final ImList<String> fieldNames;
	
	private final @Nullable Query query;
	private final ImList<Query> filters;
	
	
	private REnvIndexSearchQuery(final @Nullable Query mainQuery,
			final List<String> fieldNames, final List<Query> filters) {
		this.fieldNames= ImCollections.toList(fieldNames);
		
		this.query= mainQuery;
		this.filters= ImCollections.toList(filters);
	}
	
	
	public @Nullable Query getQuery() {
		return this.query;
	}
	
	public ImList<Query> getFilters() {
		return this.filters;
	}
	
}
