package net.osmand.plus.search;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.data.FavouritePoint;
import net.osmand.data.LatLon;
import net.osmand.plus.FavouritesDbHelper;
import net.osmand.plus.FavouritesDbHelper.FavoriteGroup;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.GpxSelectionHelper;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.helpers.SearchHistoryHelper;
import net.osmand.plus.poi.PoiFiltersHelper;
import net.osmand.plus.resources.ResourceManager.ResourceListener;
import net.osmand.search.SearchUICore;
import net.osmand.search.SearchUICore.SearchResultCollection;
import net.osmand.search.core.CustomSearchPoiFilter;
import net.osmand.search.core.ObjectType;
import net.osmand.search.core.SearchCoreFactory.SearchBaseAPI;
import net.osmand.search.core.SearchPhrase;
import net.osmand.search.core.SearchResult;
import net.osmand.util.Algorithms;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
public class QuickSearchHelper implements ResourceListener {
public static final int SEARCH_FAVORITE_API_PRIORITY = 50;
public static final int SEARCH_FAVORITE_API_CATEGORY_PRIORITY = 50;
public static final int SEARCH_FAVORITE_OBJECT_PRIORITY = 50;
public static final int SEARCH_FAVORITE_CATEGORY_PRIORITY = 51;
public static final int SEARCH_WPT_API_PRIORITY = 50;
public static final int SEARCH_WPT_OBJECT_PRIORITY = 52;
public static final int SEARCH_HISTORY_API_PRIORITY = 50;
public static final int SEARCH_HISTORY_OBJECT_PRIORITY = 53;
private OsmandApplication app;
private SearchUICore core;
private SearchResultCollection resultCollection;
private boolean mapsIndexed;
public QuickSearchHelper(OsmandApplication app) {
this.app = app;
core = new SearchUICore(app.getPoiTypes(), app.getSettings().MAP_PREFERRED_LOCALE.get(),
app.getSettings().MAP_TRANSLITERATE_NAMES.get());
app.getResourceManager().addResourceListener(this);
}
public SearchUICore getCore() {
if (mapsIndexed) {
mapsIndexed = false;
setRepositoriesForSearchUICore(app);
}
return core;
}
public SearchResultCollection getResultCollection() {
return resultCollection;
}
public void setResultCollection(SearchResultCollection resultCollection) {
this.resultCollection = resultCollection;
}
public void initSearchUICore() {
mapsIndexed = false;
setRepositoriesForSearchUICore(app);
core.init();
// Register favorites search api
core.registerAPI(new SearchFavoriteAPI(app));
// Register favorites by category search api
core.registerAPI(new SearchFavoriteCategoryAPI(app));
// Register WptPt search api
core.registerAPI(new SearchWptAPI(app));
core.registerAPI(new SearchHistoryAPI(app));
refreshCustomPoiFilters();
}
public void refreshCustomPoiFilters() {
core.clearCustomSearchPoiFilters();
PoiFiltersHelper poiFilters = app.getPoiFilters();
for(CustomSearchPoiFilter udf : poiFilters.getUserDefinedPoiFilters()) {
core.addCustomSearchPoiFilter(udf, 0);
}
core.addCustomSearchPoiFilter(poiFilters.getLocalWikiPOIFilter(), 1);
core.addCustomSearchPoiFilter(poiFilters.getShowAllPOIFilter(), 1);
}
public void setRepositoriesForSearchUICore(final OsmandApplication app) {
BinaryMapIndexReader[] binaryMapIndexReaderArray = app.getResourceManager().getQuickSearchFiles();
core.getSearchSettings().setOfflineIndexes(Arrays.asList(binaryMapIndexReaderArray));
}
public static class SearchWptAPI extends SearchBaseAPI {
private OsmandApplication app;
public SearchWptAPI(OsmandApplication app) {
super(ObjectType.WPT);
this.app = app;
}
@Override
public boolean isSearchMoreAvailable(SearchPhrase phrase) {
return false;
}
@Override
public boolean search(SearchPhrase phrase, SearchUICore.SearchResultMatcher resultMatcher) throws IOException {
if (phrase.isEmpty()) {
return false;
}
List<GpxSelectionHelper.SelectedGpxFile> list = app.getSelectedGpxHelper().getSelectedGPXFiles();
for (GpxSelectionHelper.SelectedGpxFile selectedGpx : list) {
if (selectedGpx != null) {
for (GPXUtilities.WptPt point : selectedGpx.getGpxFile().points) {
SearchResult sr = new SearchResult(phrase);
sr.localeName = point.getPointDescription(app).getName();
sr.object = point;
sr.priority = SEARCH_WPT_OBJECT_PRIORITY;
sr.objectType = ObjectType.WPT;
sr.location = new LatLon(point.getLatitude(), point.getLongitude());
//sr.localeRelatedObjectName = app.getRegions().getCountryName(sr.location);
sr.relatedObject = selectedGpx.getGpxFile();
sr.preferredZoom = 17;
if (phrase.getUnknownSearchWordLength() <= 1 && phrase.isNoSelectedType()) {
resultMatcher.publish(sr);
} else if (phrase.getNameStringMatcher().matches(sr.localeName)) {
resultMatcher.publish(sr);
}
}
}
}
return true;
}
@Override
public int getSearchPriority(SearchPhrase p) {
if(!p.isNoSelectedType()) {
return -1;
}
return SEARCH_WPT_API_PRIORITY;
}
}
public static class SearchFavoriteCategoryAPI extends SearchBaseAPI {
private OsmandApplication app;
private FavouritesDbHelper helper;
public SearchFavoriteCategoryAPI(OsmandApplication app) {
super(ObjectType.FAVORITE_GROUP);
this.app = app;
this.helper = app.getFavorites();
}
@Override
public boolean isSearchMoreAvailable(SearchPhrase phrase) {
return false;
}
@Override
public boolean search(SearchPhrase phrase, SearchUICore.SearchResultMatcher resultMatcher) throws IOException {
String baseGroupName = app.getString(R.string.shared_string_favorites);
List<FavoriteGroup> groups = app.getFavorites().getFavoriteGroups();
for (FavoriteGroup group : groups) {
if (group.visible) {
SearchResult sr = new SearchResult(phrase);
sr.localeName = Algorithms.isEmpty(group.name) ? baseGroupName : group.name;
sr.object = group;
sr.priority = SEARCH_FAVORITE_CATEGORY_PRIORITY;
sr.objectType = ObjectType.FAVORITE_GROUP;
sr.preferredZoom = 17;
if (phrase.getNameStringMatcher().matches(sr.localeName)) {
if (group.points.size() < 5) {
for (FavouritePoint point : group.points) {
SearchResult srp = new SearchResult(phrase);
srp.localeName = point.getName();
srp.object = point;
srp.priority = SEARCH_FAVORITE_OBJECT_PRIORITY;
srp.objectType = ObjectType.FAVORITE;
srp.location = new LatLon(point.getLatitude(), point.getLongitude());
srp.preferredZoom = 17;
resultMatcher.publish(srp);
}
} else {
resultMatcher.publish(sr);
}
}
}
}
return true;
}
@Override
public int getSearchPriority(SearchPhrase p) {
if (!p.isNoSelectedType() || !p.isUnknownSearchWordPresent()) {
return -1;
}
return SEARCH_FAVORITE_API_CATEGORY_PRIORITY;
}
}
public static class SearchFavoriteAPI extends SearchBaseAPI {
private OsmandApplication app;
public SearchFavoriteAPI(OsmandApplication app) {
super(ObjectType.FAVORITE);
this.app = app;
}
@Override
public boolean isSearchMoreAvailable(SearchPhrase phrase) {
return false;
}
@Override
public boolean search(SearchPhrase phrase, SearchUICore.SearchResultMatcher resultMatcher) throws IOException {
List<FavouritePoint> favList = app.getFavorites().getFavouritePoints();
for (FavouritePoint point : favList) {
if (!point.isVisible()) {
continue;
}
SearchResult sr = new SearchResult(phrase);
sr.localeName = point.getName();
sr.object = point;
sr.priority = SEARCH_FAVORITE_OBJECT_PRIORITY;
sr.objectType = ObjectType.FAVORITE;
sr.location = new LatLon(point.getLatitude(), point.getLongitude());
sr.preferredZoom = 17;
if (phrase.isLastWord(ObjectType.FAVORITE_GROUP)) {
FavoriteGroup group = (FavoriteGroup) phrase.getLastSelectedWord().getResult().object;
if (group != null && !point.getCategory().equals(group.name)) {
continue;
}
}
if (phrase.getUnknownSearchWordLength() <= 1
&& (phrase.isNoSelectedType() || phrase.isLastWord(ObjectType.FAVORITE_GROUP))) {
resultMatcher.publish(sr);
} else if (phrase.getNameStringMatcher().matches(sr.localeName)) {
resultMatcher.publish(sr);
}
}
return true;
}
@Override
public int getSearchPriority(SearchPhrase p) {
if (p.isLastWord(ObjectType.FAVORITE_GROUP)) {
return SEARCH_FAVORITE_API_PRIORITY;
}
if(!p.isNoSelectedType() || !p.isUnknownSearchWordPresent()) {
return -1;
}
return SEARCH_FAVORITE_API_PRIORITY;
}
}
public static class SearchHistoryAPI extends SearchBaseAPI {
private OsmandApplication app;
public SearchHistoryAPI(OsmandApplication app) {
super(ObjectType.RECENT_OBJ);
this.app = app;
}
@Override
public boolean isSearchMoreAvailable(SearchPhrase phrase) {
return false;
}
@Override
public boolean search(SearchPhrase phrase, SearchUICore.SearchResultMatcher resultMatcher) throws IOException {
SearchHistoryHelper helper = SearchHistoryHelper.getInstance(app);
List<SearchHistoryHelper.HistoryEntry> points = helper.getHistoryEntries();
int p = 0;
for (SearchHistoryHelper.HistoryEntry point : points) {
SearchResult sr = new SearchResult(phrase);
sr.localeName = point.getName().getName();
sr.object = point;
sr.priority = SEARCH_HISTORY_OBJECT_PRIORITY + (p++);
sr.objectType = ObjectType.RECENT_OBJ;
sr.location = new LatLon(point.getLat(), point.getLon());
sr.preferredZoom = 17;
if (phrase.getUnknownSearchWordLength() <= 1 && phrase.isNoSelectedType()) {
resultMatcher.publish(sr);
} else if (phrase.getNameStringMatcher().matches(sr.localeName)) {
resultMatcher.publish(sr);
}
}
return true;
}
@Override
public int getSearchPriority(SearchPhrase p) {
if (!p.isEmpty()) {
return -1;
}
return SEARCH_HISTORY_API_PRIORITY;
}
}
@Override
public void onMapsIndexed() {
mapsIndexed = true;
}
}