package net.osmand.plus;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.osmand.OsmAndFormatter;
import net.osmand.data.Amenity;
import net.osmand.data.AmenityType;
import net.osmand.data.index.IndexConstants;
import net.osmand.osm.MapUtils;
import net.osmand.plus.activities.OsmandApplication;
public class PoiFilter {
public final static String STD_PREFIX = "std_"; //$NON-NLS-1$
public final static String USER_PREFIX = "user_"; //$NON-NLS-1$
public final static String CUSTOM_FILTER_ID = USER_PREFIX + "custom_id"; //$NON-NLS-1$
private Map<AmenityType, LinkedHashSet<String>> acceptedTypes = new LinkedHashMap<AmenityType, LinkedHashSet<String>>();
private String filterByName = null;
protected String filterId;
protected String name;
private final boolean isStandardFilter;
private final static int finalZoom = 6;
private final static int initialZoom = 13;
private final static int maxInitialCount = 200;
private int zoom = initialZoom;
private final OsmandApplication application;
// constructor for standard filters
public PoiFilter(AmenityType type, OsmandApplication application){
this.application = application;
isStandardFilter = true;
filterId = STD_PREFIX + type;
name = type == null ? application.getString(R.string.poi_filter_closest_poi) : OsmAndFormatter.toPublicString(type, application); //$NON-NLS-1$
if(type == null){
initSearchAll();
} else {
acceptedTypes.put(type, null);
}
}
// constructor for standard filters
public PoiFilter(String name, String filterId, Map<AmenityType, LinkedHashSet<String>> acceptedTypes, OsmandApplication app){
application = app;
isStandardFilter = false;
if(filterId == null){
filterId = USER_PREFIX + name.replace(' ', '_').toLowerCase();
}
this.filterId = filterId;
this.name = name;
if(acceptedTypes == null){
initSearchAll();
} else {
this.acceptedTypes.putAll(acceptedTypes);
}
}
private void initSearchAll(){
for(AmenityType t : AmenityType.values()){
acceptedTypes.put(t, null);
}
}
public boolean isSearchFurtherAvailable(){
return zoom > finalZoom;
}
public List<Amenity> searchFurther(double latitude, double longitude){
zoom --;
List<Amenity> amenityList = application.getResourceManager().searchAmenities(this, latitude, longitude, zoom, -1);
MapUtils.sortListOfMapObject(amenityList, latitude, longitude);
return amenityList;
}
public String getSearchArea(){
if(zoom <= 14){
int d = (int) (1 * (1 << (14 - zoom)));
return " < " + d + " " + application.getString(R.string.km); //$NON-NLS-1$//$NON-NLS-2$
} else {
return " < 500 " + application.getString(R.string.m); //$NON-NLS-1$
}
}
public void clearPreviousZoom(){
zoom = getInitialZoom();
}
private int getInitialZoom(){
int zoom = initialZoom;
if(areAllTypesAccepted()){
zoom += 1;
}
return zoom;
}
public List<Amenity> initializeNewSearch(double lat, double lon, int firstTimeLimit){
zoom = getInitialZoom();
List<Amenity> amenityList = application.getResourceManager().searchAmenities(this, lat, lon, zoom, maxInitialCount);
MapUtils.sortListOfMapObject(amenityList, lat, lon);
while (amenityList.size() > firstTimeLimit) {
amenityList.remove(amenityList.size() - 1);
}
return amenityList;
}
public List<Amenity> searchAgain(double lat, double lon){
int limit = -1;
if(zoom == getInitialZoom()){
limit = maxInitialCount;
}
List<Amenity> amenityList = application.getResourceManager().searchAmenities(this, lat, lon, zoom, limit);
MapUtils.sortListOfMapObject(amenityList, lat, lon);
return amenityList;
}
public String getName(){
return name;
}
/**
* @param type
* @return null if all subtypes are accepted/ empty list if type is not accepted at all
*/
public Set<String> getAcceptedSubtypes(AmenityType type){
if(!acceptedTypes.containsKey(type)){
return Collections.emptySet();
}
return acceptedTypes.get(type);
}
public boolean isTypeAccepted(AmenityType t){
return acceptedTypes.containsKey(t);
}
public boolean acceptTypeSubtype(AmenityType t, String subtype){
if(!acceptedTypes.containsKey(t)){
return false;
}
LinkedHashSet<String> set = acceptedTypes.get(t);
if(set == null){
return true;
}
return set.contains(subtype);
}
public boolean areAllTypesAccepted(){
if(AmenityType.values().length == acceptedTypes.size()){
for(AmenityType a : acceptedTypes.keySet()){
if(acceptedTypes.get(a) != null){
return false;
}
}
return true;
}
return false;
}
public void setTypeToAccept(AmenityType type, boolean accept){
if(accept){
acceptedTypes.put(type, new LinkedHashSet<String>());
} else {
acceptedTypes.remove(type);
}
}
public String buildSqlWhereFilter(){
if(areAllTypesAccepted()){
return null;
}
assert IndexConstants.POI_TABLE != null : "use constants here to show table usage "; //$NON-NLS-1$
if(acceptedTypes.size() == 0){
return "1 > 1"; //$NON-NLS-1$
}
StringBuilder b = new StringBuilder();
b.append("("); //$NON-NLS-1$
boolean first = true;
for(AmenityType a : acceptedTypes.keySet()){
if(first){
first = false;
} else {
b.append(" OR "); //$NON-NLS-1$
}
b.append("(type = '").append(AmenityType.valueToString(a)).append("'"); //$NON-NLS-1$ //$NON-NLS-2$
if(acceptedTypes.get(a) != null){
LinkedHashSet<String> list = acceptedTypes.get(a);
b.append(" AND subtype IN ("); //$NON-NLS-1$
boolean bfirst = true;
for(String s : list){
if(bfirst){
bfirst = false;
} else {
b.append(", "); //$NON-NLS-1$
}
b.append("'").append(s).append("'"); //$NON-NLS-1$ //$NON-NLS-2$
}
b.append(")"); //$NON-NLS-1$
}
b.append(")"); //$NON-NLS-1$
}
b.append(")"); //$NON-NLS-1$
return b.toString();
}
public Map<AmenityType, LinkedHashSet<String>> getAcceptedTypes(){
return new LinkedHashMap<AmenityType, LinkedHashSet<String>>(acceptedTypes);
}
public void selectSubTypesToAccept(AmenityType t, LinkedHashSet<String> accept){
acceptedTypes.put(t, accept);
}
public String getFilterId(){
return filterId;
}
public String getFilterByName() {
return filterByName;
}
public void setFilterByName(String filterByName) {
this.filterByName = filterByName;
}
public boolean isStandardFilter(){
return isStandardFilter;
}
public OsmandApplication getApplication() {
return application;
}
}