package com.schneeloch.bostonbusmap_library.transit;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import javax.xml.parsers.ParserConfigurationException;
import com.schneeloch.bostonbusmap_library.data.BusLocation;
import com.schneeloch.bostonbusmap_library.data.Directions;
import com.schneeloch.bostonbusmap_library.data.HubwayStopLocation;
import com.schneeloch.bostonbusmap_library.data.IAlerts;
import com.schneeloch.bostonbusmap_library.data.ITransitDrawables;
import com.schneeloch.bostonbusmap_library.data.Locations;
import com.schneeloch.bostonbusmap_library.data.PredictionStopLocationPair;
import com.schneeloch.bostonbusmap_library.data.RouteConfig;
import com.schneeloch.bostonbusmap_library.data.RoutePool;
import com.schneeloch.bostonbusmap_library.data.Selection;
import com.schneeloch.bostonbusmap_library.data.StopLocation;
import com.schneeloch.bostonbusmap_library.data.TransitSourceCache;
import com.schneeloch.bostonbusmap_library.data.TransitSourceTitles;
import com.schneeloch.bostonbusmap_library.data.VehicleLocations;
import com.schneeloch.bostonbusmap_library.database.Schema;
import com.schneeloch.bostonbusmap_library.parser.HubwayParser;
import com.schneeloch.bostonbusmap_library.util.DownloadHelper;
import com.schneeloch.bostonbusmap_library.util.SearchHelper;
/**
* Created by schneg on 9/1/13.
*/
public class HubwayTransitSource implements TransitSource {
public static final String stopTagPrefix = "hubway_";
private static final String routeTag = "Hubway";
private static final String infoUrl = "https://gbfs.thehubway.com/gbfs/en/station_information.json";
private static final String statusUrl = "https://gbfs.thehubway.com/gbfs/en/station_status.json";
private final ITransitDrawables drawables;
private final TransitSourceTitles routeTitles;
private final ITransitSystem transitSystem;
private final TransitSourceCache cache;
private static Schema.Routes.SourceId[] transitSourceIds = new Schema.Routes.SourceId[] {Schema.Routes.SourceId.Hubway};
public HubwayTransitSource(ITransitDrawables drawables, TransitSourceTitles routeTitles,
TransitSystem transitSystem) {
this.drawables = drawables;
this.routeTitles = routeTitles;
this.transitSystem = transitSystem;
cache = new TransitSourceCache();
}
@Override
public void refreshData(RouteConfig routeConfig, Selection selection,
int maxStops, double centerLatitude, double centerLongitude,
VehicleLocations busMapping,
RoutePool routePool, Directions directions,
Locations locationsObj) throws IOException, ParserConfigurationException, SAXException {
Selection.Mode mode = selection.getMode();
switch (mode) {
case VEHICLE_LOCATIONS_ALL:
case VEHICLE_LOCATIONS_ONE:
// no need for that here
break;
case BUS_PREDICTIONS_ALL:
case BUS_PREDICTIONS_ONE:
case BUS_PREDICTIONS_STAR:
if (!cache.canUpdateAllPredictions()) {
return;
}
RouteConfig hubwayRouteConfig = routePool.get(routeTag);
DownloadHelper infoHelper = new DownloadHelper(infoUrl);
DownloadHelper statusHelper = new DownloadHelper(statusUrl);
try {
InputStream infoStream = infoHelper.getResponseData();
InputStream statusStream = statusHelper.getResponseData();
HubwayParser parser = new HubwayParser(hubwayRouteConfig);
parser.runParse(new InputStreamReader(infoStream), new InputStreamReader(statusStream));
parser.addMissingStops(locationsObj);
List<PredictionStopLocationPair> pairs = parser.getPairs();
for (PredictionStopLocationPair pair : pairs) {
pair.stopLocation.clearPredictions(null);
pair.stopLocation.addPrediction(pair.prediction);
}
cache.updateAllPredictions();
}
finally {
infoHelper.disconnect();
}
break;
default:
throw new RuntimeException("Unknown mode encountered");
}
}
@Override
public boolean hasPaths() {
return false;
}
@Override
public String searchForRoute(String indexingQuery, String lowercaseQuery) {
return SearchHelper.naiveSearch(indexingQuery, lowercaseQuery, routeTitles);
}
@Override
public ITransitDrawables getDrawables() {
return drawables;
}
@Override
public StopLocation createStop(float latitude, float longitude, String stopTag, String stopTitle, String route, Optional<String> parent) {
HubwayStopLocation stop = new HubwayStopLocation.HubwayBuilder(latitude,
longitude, stopTag, stopTitle, parent).build();
stop.addRoute(route);
return stop;
}
@Override
public BusLocation createVehicleLocation(float latitude, float longitude, String id, long lastFeedUpdateInMillis, Optional<Integer> heading, String routeName, String headsign) {
throw new RuntimeException("Cannot create hubway location");
}
@Override
public TransitSourceTitles getRouteTitles() {
return routeTitles;
}
@Override
public int getLoadOrder() {
return 4;
}
@Override
public Schema.Routes.SourceId[] getTransitSourceIds() {
return transitSourceIds;
}
@Override
public boolean requiresSubwayTable() {
return false;
}
@Override
public IAlerts getAlerts() {
return transitSystem.getAlerts();
}
@Override
public String getDescription() {
return "Hubway";
}
}