package com.papagiannis.tuberun.fetchers;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import com.papagiannis.tuberun.LineType;
import com.papagiannis.tuberun.Status;
public class StatusesFetcher extends Fetcher {
private static final long serialVersionUID = 1L;
// region private state
protected ArrayList<Status> _all_statuses = new ArrayList<Status>();
protected Date last_update;
public Boolean forWeekend() {
return statusurl == WEEKENDURL;
}
private final String NOWURL = "http://www.tfl.gov.uk/tfl/livetravelnews/realtime/tube/default.html";
// private final String NOWURL = "http://tuberun.dyndns.org:55559/getStatuses.php";
// private final String NOWURL = "http://localhost:55559/getStatuses.php";
private final String WEEKENDURL = "http://www.tfl.gov.uk/tfl/livetravelnews/realtime/track.aspx?offset=weekend";
protected String statusurl;
// region constructors
public StatusesFetcher() {
}
public static StatusesFetcher fetcherNowSigleton;
public static StatusesFetcher fetcherWeekendSigleton;
public static StatusesFetcher getInstance() {
return getInstance(false);
}
public static StatusesFetcher getInstance(Boolean forWeekend) {
if (!forWeekend) {
if (fetcherNowSigleton == null) {
fetcherNowSigleton = new StatusesFetcher();
fetcherNowSigleton.setNowUrl();
}
return fetcherNowSigleton;
} else {
if (fetcherWeekendSigleton == null) {
fetcherWeekendSigleton = new StatusesFetcher();
fetcherWeekendSigleton.setWeekendUrl();
}
return fetcherWeekendSigleton;
}
}
// region set service url
private void setNowUrl() {
statusurl = NOWURL;
}
private void setWeekendUrl() {
statusurl = WEEKENDURL;
}
@Override
public Date getUpdateTime() {
if (last_update == null)
last_update = new Date();
return (Date) last_update.clone();
}
// region issue request
public Status getStatus(LineType req) {
for (Status s : _all_statuses) {
if (s.line_name == req)
return s;
}
return null;
}
protected AtomicBoolean isFirst = new AtomicBoolean(true);
protected transient RequestTask task=null;
public void update() {
boolean first = isFirst.compareAndSet(true, false);
if (!first)
return; // only one at a time
task = new RequestTask(new HttpCallback() {
public void onReturn(String s) {
getStatusesCallBack(s);
}
});
task.setDesktopUserAgent();
task.execute(statusurl);
}
protected String beautify(String problem) {
problem = problem.replaceAll("<(.*?)>", " ");
problem = problem.replaceAll("(\\s)+", " ");
problem = problem.replaceAll(" ", " ");
return problem.trim();
}
protected void getStatusesCallBack(String reply) {
try {
reply = unCapitalizeTags(reply);
HashMap<String, String> result = new HashMap<String, String>();
HashMap<String, String> problems = new HashMap<String, String>();
String[] lines = new String[] { "bakerloo", "central", "circle",
"district", "hammersmithandcity", "jubilee",
"metropolitan", "northern", "piccadilly", "victoria",
"waterlooandcity", "dlr", "overground" };
for (int i = 0; i < lines.length; i++) {
String filter1 = "<h3 class=\"" + lines[i] + " ltn-name\">";
int j = reply.indexOf(filter1) + filter1.length();
if (j > filter1.length() /* sth found */) {
String rest = reply.substring(j);
String start = "<div class=\"status\">";
String start2 = "<div class=\"problem status\">";
String end = "</li>";
j = rest.indexOf(start);
int k = rest.indexOf(start2);
int e = rest.indexOf(end);
String status;
if (j < e || k < e) {
if (j < e)
rest = rest.substring(j + start.length());
else
rest = rest.substring(k + start2.length());
j = rest.indexOf("</div>");
String statust = rest.substring(0, j);
if (statust.contains("<h4")) {
String l = "<h4 class=\"ltn-title\">";
j = statust.indexOf(l) + l.length();
status = statust.substring(j);
j = status.indexOf("</h4>");
/*
* k = status.IndexOf(","); if (k > 0 && k < j)
* status = status.Substring(0, k); else
*/status = status.substring(0, j);
} else
status = statust;
} else
status = "Failed";
if (!status.equals("Good service")) {
j = rest.indexOf("<div class=\"message\">") + 21;
rest = rest.substring(j);
j = rest.indexOf("<a");
k = rest.indexOf("<A");
if (j == -1 && k > 0)
j = k;
String problem = rest.substring(0, j);
// must remove hmtl tags here.
problem = problem.replaceAll("\n", "");
problem = problem.replaceAll("&", "and");
problems.put(lines[i], problem);
}
result.put(lines[i], status);
}
}
if (result.keySet().size() == 13) {
Date now = new Date();
// And lets write down the results
last_update = now;
_all_statuses = new ArrayList<Status>();
for (String name : result.keySet()) {
LineType ln = LineType.fromString(name);
String rstatus;
String rproblems;
if (result.containsKey(name))
rstatus = result.get(name);
else
throw new Exception("Failed to get a single status");
if (problems.containsKey(name))
rproblems = problems.get(name);
else
rproblems = "";
_all_statuses.add(new Status(ln, rstatus,
beautify(rproblems)));
}
notifyClients();
} else
throw new Exception("Wrong number of lines returned.");
} catch (Exception e) {
_all_statuses = new ArrayList<Status>();
notifyClients();
} finally {
isFirst.set(true);
}
}
private String unCapitalizeTags(String reply) {
StringBuilder res=new StringBuilder(reply.length());
boolean inTag=false;
for (int i=0;i<reply.length();i++) {
char c=reply.charAt(i);
switch (c) {
case '<':
inTag=true;
break;
case '>':
case ' ':
inTag=false;
break;
default:
if (inTag) c=Character.toLowerCase(c);
break;
}
res.append(c);
}
return res.toString();
}
@Override
public void abort() {
isFirst.set(true);
if (task!=null) task.cancel(true);
}
}