package com.neuron.trafikanten.views.realtime;
import java.util.ArrayList;
import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import com.google.android.AnalyticsUtils;
import com.neuron.trafikanten.R;
import com.neuron.trafikanten.dataProviders.trafikanten.TrafikantenDevi;
import com.neuron.trafikanten.dataProviders.trafikanten.TrafikantenRealtime;
import com.neuron.trafikanten.dataSets.DeviData;
import com.neuron.trafikanten.dataSets.RealtimeData;
import com.neuron.trafikanten.dataSets.StationData;
import com.neuron.trafikanten.db.FavoriteLineDbAdapter;
import com.neuron.trafikanten.tasks.NotificationTask;
import com.neuron.trafikanten.tasks.SelectDeviTask;
/*
* Generic view for rendering realtime data. This is used by RealtimeView and FavoritesView
*/
public abstract class GenericRealtimeView extends ListActivity {
private static final String KEY_TIMEDIFFERENCE = "timeDifference";
private static final String KEY_LAST_UPDATE = "lastUpdate";
private static final String KEY_LIST = "list";
/*
* Options menu:
*/
private static final int REFRESH_ID = Menu.FIRST;
/*
* Context menu:
*/
private static final int NOTIFY_ID = Menu.FIRST;
private static final int DEVI_ID = Menu.FIRST + 1;
private static final int FAVORITE_ID = Menu.FIRST + 2;
/*
* Data providers
*/
protected ArrayList<TrafikantenRealtime> _realtimeProviders = null;
protected TrafikantenDevi deviProvider = null;
protected FavoriteLineDbAdapter favoriteLineDbAdapter = null;
/*
* Saved instance data
*/
protected GenericRealtimeListAdapter realtimeList;
public long timeDifference = 0; // This is the time desync between system clock and trafikanten servers.
protected long lastUpdate;
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState, String viewName, int groupBy) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
/*
* Analytics
*/
AnalyticsUtils.getInstance(this).trackPageView(viewName);
favoriteLineDbAdapter = new FavoriteLineDbAdapter(this);
realtimeList = new GenericRealtimeListAdapter(this, this, groupBy);
if (savedInstanceState != null) {
timeDifference = savedInstanceState.getLong(KEY_TIMEDIFFERENCE);
lastUpdate = savedInstanceState.getLong(KEY_LAST_UPDATE);
realtimeList.setItems(savedInstanceState.getParcelable(KEY_LIST));
realtimeList.notifyDataSetChanged();
}
/*
ListView lv = getListView();
lv.setCacheColorHint(Color.TRANSPARENT);
lv.setFastScrollEnabled(true);
lv.setScrollingCacheEnabled(true);*/
setListAdapter(realtimeList);
}
public TrafikantenRealtime createRealtimeProvider(Context context, int stationId) {
TrafikantenRealtime provider = new TrafikantenRealtime(context, stationId);
if (_realtimeProviders == null) {
_realtimeProviders = new ArrayList<TrafikantenRealtime>();
}
_realtimeProviders.add(provider);
return provider;
}
public void clearRealtimeProvider(TrafikantenRealtime realtimeProvider) {
if (_realtimeProviders != null) {
_realtimeProviders.remove(realtimeProvider);
}
}
public void stopProviders() {
if (_realtimeProviders != null) {
for (TrafikantenRealtime realtimeProvider : _realtimeProviders) {
realtimeProvider.kill();
}
}
if (deviProvider != null) {
deviProvider.kill();
}
setProgressBarIndeterminateVisibility(false);
}
protected void refresh() {
realtimeList.notifyDataSetChanged(); // force rendering times again
}
protected void load() {
lastUpdate = System.currentTimeMillis();
stopProviders();
clearView();
}
protected void clearView() {
realtimeList.clear();
}
/*
* Keep refreshing the view every 10 seconds while view is visible.
*/
final Handler autoRefreshHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
refresh();
autoRefreshHandler.sendEmptyMessageDelayed(0, 20000);
return true;
}
});
/**
* Saving load instance state/onpause/ondestroy etc
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putLong(KEY_TIMEDIFFERENCE, timeDifference);
outState.putParcelable(KEY_LIST, realtimeList.getParcelable());
outState.putLong(KEY_LAST_UPDATE, lastUpdate);
}
/*
* Functions for dealing with program state.
*/
@Override
protected void onPause() {
//Debug.stopMethodTracing();
favoriteLineDbAdapter.close();
autoRefreshHandler.removeMessages(0);
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
favoriteLineDbAdapter.open();
refresh();
autoRefreshHandler.sendEmptyMessageDelayed(0, 10000);
}
@Override
protected void onStop() {
/*
* make sure background threads is properly killed off.
*/
stopProviders();
super.onStop();
}
/**
* Options menu code
*/
/*
* Options menu, visible on menu button.
* @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
final MenuItem refresh = menu.add(0, REFRESH_ID, 0, R.string.refresh);
refresh.setIcon(R.drawable.ic_menu_refresh);
return true;
}
/*
* Options menu item selected, options menu visible on menu button.
* @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case REFRESH_ID:
onOptionsMenuRefresh();
return true;
}
return super.onOptionsItemSelected(item);
}
public abstract void onOptionsMenuRefresh();
/**
* Context menu code
*/
/*
* onCreate - Context menu is a popup from a longpress on a list item.
* @see android.app.Activity#onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo)
*/
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
final RealtimeData realtimeData = realtimeList.getRealtimeItem(info.position);
final StationData station = getStation(info.position);
if (realtimeData == null || station == null) return;
if (realtimeData.devi.size() > 0)
menu.add(0, DEVI_ID, 0, R.string.warnings);
menu.add(0, NOTIFY_ID, 0, R.string.alarm);
if (favoriteLineDbAdapter.isFavorite(station, realtimeData.lineId, realtimeData.destination)) {
menu.add(0, FAVORITE_ID, 0, R.string.removeFavorite);
} else {
menu.add(0, FAVORITE_ID, 0, R.string.addFavorite);
}
}
/*
* onSelected - Context menu is a popup from a longpress on a list item.
* @see android.app.Activity#onContextItemSelected(android.view.MenuItem)
*/
@Override
public boolean onContextItemSelected(MenuItem item) {
final AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
final RealtimeData realtimeData = (RealtimeData) realtimeList.getRealtimeItem(info.position);
final StationData station = getStation(info.position);
if (realtimeData != null && station != null) {
switch(item.getItemId()) {
case NOTIFY_ID:
final String notifyWith = realtimeData.lineName.equals(realtimeData.destination)
? realtimeData.lineName
: realtimeData.lineName + " " + realtimeData.destination;
new NotificationTask(this, realtimeData, station, notifyWith, timeDifference);
return true;
case DEVI_ID:
final ArrayList<DeviData> deviPopup = realtimeData.devi;
new SelectDeviTask(this, deviPopup);
return true;
case FAVORITE_ID:
favoriteLineDbAdapter.toggleFavorite(station, realtimeData.lineId, realtimeData.destination);
return true;
}
}
return super.onContextItemSelected(item);
}
/*
* For realtime this returns current station. For favorites this scans up from the selected position to find the station belonging to that realtime data.
*/
public abstract StationData getStation(int pos);
}