package cgeo.geocaching.enumerations;
import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
import android.support.annotation.NonNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
/**
* Enum listing waypoint types
*/
public enum WaypointType {
FINAL("flag", "Final Location", R.string.wp_final, R.drawable.waypoint_flag, 3),
OWN("own", "Own", R.string.wp_waypoint, R.drawable.waypoint_waypoint, 5),
PARKING("pkg", "Parking Area", R.string.wp_pkg, R.drawable.waypoint_pkg, -1),
PUZZLE("puzzle", "Virtual Stage", R.string.wp_puzzle, R.drawable.waypoint_puzzle, 2),
STAGE("stage", "Physical Stage", R.string.wp_stage, R.drawable.waypoint_stage, 2),
TRAILHEAD("trailhead", "Trailhead", R.string.wp_trailhead, R.drawable.waypoint_trailhead, 1),
WAYPOINT("waypoint", "Reference Point", R.string.wp_waypoint, R.drawable.waypoint_waypoint, 2),
ORIGINAL("original", "Original Coordinates", R.string.wp_original, R.drawable.waypoint_waypoint, 4);
@NonNull
public final String id;
@NonNull public final String gpx;
public final int stringId;
public final int markerId;
public final int order;
WaypointType(@NonNull final String id, @NonNull final String gpx, final int stringId, final int markerId, final int order) {
this.id = id;
this.gpx = gpx;
this.stringId = stringId;
this.markerId = markerId;
this.order = order;
}
/**
* inverse lookup of waypoint IDs<br/>
* non public so that {@code null} handling can be handled centrally in the enum type itself
*/
private static final Map<String, WaypointType> FIND_BY_ID = new HashMap<>();
static {
for (final WaypointType wt : values()) {
FIND_BY_ID.put(wt.id, wt);
}
}
@NonNull
public static final List<WaypointType> ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL = orderedWaypointTypes();
private static List<WaypointType> orderedWaypointTypes() {
// enforce an order for these types
final Set<WaypointType> waypointTypes = new LinkedHashSet<>();
waypointTypes.addAll(Arrays.asList(PARKING, TRAILHEAD, PUZZLE, STAGE, FINAL));
// then add all remaining except "internal" types
waypointTypes.addAll(EnumSet.complementOf(EnumSet.of(OWN, ORIGINAL)));
return Collections.unmodifiableList(new ArrayList<>(waypointTypes));
}
/**
* inverse lookup of waypoint IDs<br/>
* here the {@code null} handling shall be done
*/
@NonNull
public static WaypointType findById(final String id) {
if (id == null) {
return WAYPOINT;
}
final WaypointType waypointType = FIND_BY_ID.get(id);
if (waypointType == null) {
return WAYPOINT;
}
return waypointType;
}
@NonNull
public final String getL10n() {
return CgeoApplication.getInstance().getBaseContext().getString(stringId);
}
@Override
public final String toString() {
return getL10n();
}
public boolean applyDistanceRule() {
return this == FINAL || this == STAGE;
}
public static WaypointType fromGPXString(@NonNull final String sym) {
// first check the somewhat "official" sym types
for (final WaypointType waypointType : WaypointType.values()) {
if (waypointType.gpx.equalsIgnoreCase(sym)) {
return waypointType;
}
}
// old names of multi cache stages
if ("stages of a multicache".equalsIgnoreCase(sym)) {
return WaypointType.STAGE;
}
if ("stage of a multicache".equalsIgnoreCase(sym)) {
return WaypointType.STAGE;
}
if ("question to answer".equalsIgnoreCase(sym)) {
return WaypointType.PUZZLE;
}
// this is not fully correct, but lets also look for localized waypoint types
for (final WaypointType waypointType : WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL) {
final String localized = waypointType.getL10n();
if (StringUtils.isNotEmpty(localized) && localized.equalsIgnoreCase(sym)) {
return waypointType;
}
}
return WaypointType.WAYPOINT;
}
}