package cgeo.geocaching.connector.trackable;
import cgeo.geocaching.models.Trackable;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.storage.DataStore;
import cgeo.geocaching.utils.Log;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.lang3.StringUtils;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.xml.sax.InputSource;
import java.io.InputStream;
import java.util.List;
import java.util.regex.Pattern;
public final class GeolutinsConnector extends AbstractTrackableConnector {
private static final Pattern PATTERN_GL_CODE = Pattern.compile("GL[0-9A-F]{5}|[0-9]{7,8}-[0-9]{3,4}");
private static final String HOST = "www.geolutins.com";
private static final String URL = "http://" + HOST;
/**
* Get geocode from Geolutins id
*
*/
public static String geocode(final int id) {
return String.format("GL%05X", id);
}
public static int getId(final String geocode) {
try {
final String hex = geocode.substring(2);
return Integer.parseInt(hex, 16);
} catch (final NumberFormatException e) {
Log.e("Trackable.getId", e);
}
return -1;
}
@Override
public boolean canHandleTrackable(@Nullable final String geocode) {
return geocode != null && PATTERN_GL_CODE.matcher(geocode).matches();
}
@NonNull
@Override
public String getServiceTitle() {
throw new IllegalStateException("this connector does not have a corresponding name.");
}
@Override
@NonNull
public String getUrl(@NonNull final Trackable trackable) {
return getUrl(trackable.getGeocode());
}
private static String getUrl(final String geocode) {
return URL + "/profil_geolutin.php?ID_Geolutin_Selectionne=" + getId(geocode);
}
@Override
@Nullable
public Trackable searchTrackable(final String geocode, final String guid, final String id) {
final String glid;
if (StringUtils.startsWithIgnoreCase(geocode, "GL")) {
glid = geocode;
} else {
// This probably a Tracking Code
Log.d("GeolutinsConnector.searchTrackable: geocode=" + geocode);
final String geocodeFound = getGeocodeFromTrackingCode(geocode);
if (geocodeFound == null) {
return null;
}
glid = geocodeFound;
}
Log.i("GeolutinsConnector.searchTrackable: glid=" + glid);
try {
final String urlDetails = URL + "/xml/api.php?G=" + StringUtils.upperCase(glid);
Log.i("GeolutinsConnector.searchTrackable URL: " + urlDetails);
final InputStream response = Network.getResponseStream(Network.getRequest(urlDetails));
if (response == null) {
Log.e("GeolutinsConnector.searchTrackable: No data from server");
return null;
}
try {
final InputSource is = new InputSource(response);
final List<Trackable> trackables = GeolutinsParser.parse(is);
if (CollectionUtils.isNotEmpty(trackables)) {
DataStore.saveTrackable(trackables.get(0));
return trackables.get(0);
}
} finally {
IOUtils.closeQuietly(response);
}
} catch (final Exception e) {
Log.w("GeolutinsConnector.searchTrackable", e);
}
return null;
}
@Override
@Nullable
public String getTrackableCodeFromUrl(@NonNull final String url) {
final String glid = StringUtils.upperCase(StringUtils.substringAfterLast(url, "ID_Geolutin_Selectionne="));
if (StringUtils.isNumeric(glid)) {
return geocode(Integer.parseInt(glid));
}
return null;
}
@Override
@NonNull
public TrackableBrand getBrand() {
return TrackableBrand.GEOLUTINS;
}
@Override
@NonNull
public String getHost() {
return HOST;
}
@Override
@NonNull
public String getHostUrl() {
return URL;
}
/**
* Lookup Trackable Geocode from Tracking Code.
*
* @param trackingCode
* the Trackable Tracking Code to lookup
* @return
* the Trackable Geocode
*/
@Nullable
public static String getGeocodeFromTrackingCode(final String trackingCode) {
final Parameters params = new Parameters("G", trackingCode);
final InputStream response = Network.getResponseStream(Network.getRequest(URL + "/xml/decode.php", params));
try {
final List<Trackable> trackables = GeolutinsParser.parse(new InputSource(response));
if (CollectionUtils.isNotEmpty(trackables)) {
return trackables.get(0).getGeocode();
}
return null;
} finally {
IOUtils.closeQuietly(response);
}
}
}