package nl.topicus.onderwijs.dashboard.modules.ns;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.HTMLElementName;
import net.htmlparser.jericho.Source;
import nl.topicus.onderwijs.dashboard.config.ISettings;
import nl.topicus.onderwijs.dashboard.datasources.Trains;
import nl.topicus.onderwijs.dashboard.datatypes.train.Train;
import nl.topicus.onderwijs.dashboard.datatypes.train.TrainType;
import nl.topicus.onderwijs.dashboard.keys.Key;
import nl.topicus.onderwijs.dashboard.modules.AbstractService;
import nl.topicus.onderwijs.dashboard.modules.DashboardRepository;
import nl.topicus.onderwijs.dashboard.modules.ServiceConfiguration;
import nl.topicus.onderwijs.dashboard.modules.topicus.RetrieverUtils;
import nl.topicus.onderwijs.dashboard.modules.topicus.StatusPageResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
@ServiceConfiguration(interval = 1, unit = TimeUnit.MINUTES)
public class NSService extends AbstractService {
private static final Logger log = LoggerFactory.getLogger(NSService.class);
private static final int TIME = 0;
private static final int DESTINATION = 1;
private static final int PLATFORM = 2;
private static final int DETAILS = 4;
private Map<Key, List<Train>> trains = new HashMap<Key, List<Train>>();
@Autowired
public NSService(ISettings settings) {
super(settings);
}
@Override
public void onConfigure(DashboardRepository repository) {
for (Key key : getSettings().getKeysWithConfigurationFor(
NSService.class)) {
trains.put(key, Collections.<Train> emptyList());
repository.addDataSource(key, Trains.class, new TrainsImpl(key,
this));
}
}
@Override
public void refreshData() {
Map<Key, List<Train>> newTrains = new HashMap<Key, List<Train>>();
Map<Key, Map<String, ?>> serviceSettings = getSettings()
.getServiceSettings(NSService.class);
for (Map.Entry<Key, Map<String, ?>> configEntry : serviceSettings
.entrySet()) {
Key location = configEntry.getKey();
String station = configEntry.getValue().get("station").toString();
List<Train> newDeps = fetchDepartures(location, station);
newTrains.put(location, newDeps == null ? trains.get(location)
: newDeps);
}
trains = newTrains;
}
private List<Train> fetchDepartures(Key location, String station) {
try {
StatusPageResponse response = RetrieverUtils
.getStatuspage("http://www.ns.nl/actuele-vertrektijden/main.link?station="
+ station);
if (response.getHttpStatusCode() != 200) {
return null;
}
Source source = new Source(response.getPageContent());
source.fullSequentialParse();
List<Train> newTrains = new ArrayList<Train>();
List<Element> tableRows = source.getAllElements(HTMLElementName.TR);
for (Element tableRow : tableRows) {
if (tableRow.getParentElement().getName().equals(
HTMLElementName.TBODY)) {
Train train = new Train();
int index = 0;
for (Element curCell : tableRow.getChildElements()) {
String contents = curCell.getTextExtractor().toString();
switch (index) {
case TIME:
setTime(train, contents);
break;
case DESTINATION:
setDestination(train, contents);
break;
case PLATFORM:
setPlatform(train, contents, curCell
.getAttributeValue("class"));
break;
case DETAILS:
setDetails(train, contents);
break;
}
index++;
}
newTrains.add(train);
}
}
return newTrains;
} catch (Exception e) {
log.error("Unable to refresh data from ns: {} {}", e.getClass()
.getSimpleName(), e.getMessage());
return null;
}
}
private void setTime(Train train, String content) {
String time;
int space = content.indexOf(' ');
if (space > 0) {
time = content.substring(0, space);
try {
String delayPart = content.substring(space + 3);
train.setDelay(Integer.parseInt(delayPart.substring(0,
delayPart.indexOf(' '))));
} catch (Exception e) {
log.info("Cannot parse delay from '" + content + "': "
+ e.getMessage());
}
} else {
time = content;
}
train.setDepartureTime(time);
}
private void setDestination(Train train, String destination) {
train.setDestination(destination);
}
private void setPlatform(Train train, String platform, String classAttr) {
train.setPlatform(platform);
if (classAttr != null && classAttr.contains("highlight"))
train.setPlatformChange(true);
}
private void setDetails(Train train, String details) {
if (details.contains("Sprinter") || details.contains("SPR"))
train.setType(TrainType.SPRINTER);
else if (details.contains("Intercity"))
train.setType(TrainType.INTERCITY);
else if (details.contains("Sneltrein"))
train.setType(TrainType.SNELTREIN);
else if (details.contains("Stoptrein"))
train.setType(TrainType.STOPTREIN);
else if (details.contains("Int. Trein"))
train.setType(TrainType.INTERNATIONAL);
else if (details.contains("Fyra"))
train.setType(TrainType.HIGH_SPEED);
else if (details.contains("Thalys"))
train.setType(TrainType.HIGH_SPEED);
else if (details.contains("ICE"))
train.setType(TrainType.HIGH_SPEED);
else if (details.contains("Rijdt vandaag niet"))
train.setType(TrainType.CANCELED);
else
train.setType(TrainType.UNKNOWN);
}
public List<Train> getTrains(Key key) {
return trains.get(key);
}
}