package be.irail.betrains.adapters;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import tof.cv.mpp.R;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import be.irail.api.IRail;
import be.irail.api.data.ArrivalDeparture;
import be.irail.api.data.Liveboard;
import be.irail.api.data.Station;
import com.commonsware.cwac.adapter.EndlessAdapter;
public class EndlessArrivalDepartureAdapter extends EndlessAdapter {
private static final String TAG = "EndlessArrivalDepartureAdapter";
private final LayoutInflater mInflater;
private final IRail mIRail;
private final ArrivalDepartureAdapter mWrappedAdapter;
private List<ArrivalDeparture> mNewArrivalsDepartures;
private Station mStation;
private String mInitialStartTime;
private boolean mDepartures;
private View mLoadingView = null;
public EndlessArrivalDepartureAdapter(ArrivalDepartureAdapter wrapped, LayoutInflater inflator, IRail iRail) {
super(wrapped);
mWrappedAdapter = wrapped;
mNewArrivalsDepartures = null; // Set to null so that list is
// initialized in cacheInBackground
mInflater = inflator;
mIRail = iRail;
}
@Override
protected View getPendingView(ViewGroup parent) {
if (mLoadingView == null) {
mLoadingView = mInflater.inflate(R.layout.list_item_loading, null);
}
return mLoadingView;
}
@Override
protected boolean cacheInBackground() {
// Determine starting time for fetching new arrivals/departures
String startTime;
if (mNewArrivalsDepartures == null) {
startTime = mInitialStartTime;
mNewArrivalsDepartures = new ArrayList<ArrivalDeparture>();
} else {
startTime = toHHmm(mNewArrivalsDepartures.get(mNewArrivalsDepartures.size() - 1).getDate());
mNewArrivalsDepartures.clear();
}
// Fetch livebaord
Log.d(TAG, "Loading new arrivals/departures for time " + startTime + "...");
Liveboard liveboard;
try {
liveboard = mIRail.getLiveboard(mStation, startTime, mDepartures);
} catch (Exception e) {
Log.e(TAG, "Could not fetch departures/arrivals: " + e);
e.printStackTrace();
return false;
}
// Get arrivals/departures
List<ArrivalDeparture> newArrivalDepartures = liveboard.getArrivalsAndDepartures();
if (newArrivalDepartures.isEmpty()) {
Log.d(TAG, "No new items returned for time " + startTime + ".");
return false;
} else if (!mNewArrivalsDepartures.isEmpty()) {
Date lastPreviousDate = mNewArrivalsDepartures.get(mNewArrivalsDepartures.size() - 1).getDate();
Date lastNewData = newArrivalDepartures.get(newArrivalDepartures.size() - 1).getDate();
if (lastPreviousDate.equals(lastNewData)) {
Log.d(TAG, "Same items as before returned for time " + startTime + ".");
return false;
}
}
removeOverlap(newArrivalDepartures);
mNewArrivalsDepartures = newArrivalDepartures;
Log.d(TAG, "Finished loading " + mNewArrivalsDepartures.size() + " new arrivals/departures for " + startTime + ".");
return true;
}
@Override
protected void appendCachedData() {
ArrivalDepartureAdapter adapter = mWrappedAdapter;
adapter.addItems(mNewArrivalsDepartures);
}
/**
* Had to override this method, otherwise IndexOutOfBoundException. Bug in
* EndlessAdapter/AdapterWrapper?
*/
@Override
public long getItemId(int position) {
if (position >= mWrappedAdapter.getCount()) {
return -1;
}
return super.getItemId(position);
}
/**
* Sets the query parameters used when updating the arrivals/departures.
*
* @param station
* @param startTime
* the starting time of the arrivals/departures; null to use the
* current time
* @param departures
* true to fetch departures; false to fetch arrivals
*/
public void setQueryParams(Station station, String initialStartTime, boolean departures) {
mStation = station;
mInitialStartTime = initialStartTime;
mDepartures = departures;
}
/**
* Removes items from the new arrivals/deparatures that overlap with the
* last previous arrival/departure.
*
* Note that this algorithm depends on the iRail API always returning
* arrivals/departures in the same order. This does not seem to always be
* the case though. In that case the beginning of the new list will contain
* duplicates from the previous list.
*
* @param newList the new arrivals/departures
*/
private void removeOverlap(List<ArrivalDeparture> newList) {
if (mWrappedAdapter.getCount() == 0) {
return;
}
ArrivalDeparture lastArrDep = (ArrivalDeparture) mWrappedAdapter.getItem(mWrappedAdapter.getCount() - 1);
for (Iterator<ArrivalDeparture> it = newList.iterator(); it.hasNext();) {
ArrivalDeparture newArrDep = it.next();
if (newArrDep.getDate().before(lastArrDep.getDate())) {
// Lists overlap, remove from new list
it.remove();
} else if (newArrDep.getDate().equals(lastArrDep.getDate()) && newArrDep.getPlatform().equals(lastArrDep.getPlatform())) {
// Lists overlap, remove from new list
it.remove();
} else {
// List no longer overlap, return
return;
}
}
}
private static String toHHmm(Date date) {
return new SimpleDateFormat("HHmm").format(date);
}
}
|