package com.vaguehope.onosendai.ui;

import java.util.ArrayList;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;

import com.vaguehope.onosendai.TweetListAdapter;
import com.vaguehope.onosendai.model.Tweet;
import com.vaguehope.onosendai.model.TweetList;
import com.vaguehope.onosendai.storage.DbClient;
import com.vaguehope.onosendai.util.LogWrapper;

public class TweetListFragment extends Fragment {

	public static final String ARG_COLUMN_ID = "column_id";

	protected final LogWrapper log = new LogWrapper();

	private int columnId;
	private TweetListAdapter adapter;
	private DbClient bndDb;

	@Override
	public View onCreateView (final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
		this.columnId = getArguments().getInt(ARG_COLUMN_ID);
		this.log.setPrefix("C" + this.columnId);

		ListView tweetList = new ListView(getActivity());
		this.adapter = new TweetListAdapter(getActivity());
		tweetList.setAdapter(this.adapter);
		return tweetList;
	}

	@Override
	public void onDestroy () {
		this.bndDb.finalize();
		super.onDestroy();
	}

	@Override
	public void onResume () {
		super.onResume();
		resumeDb();
	}

	@Override
	public void onPause () {
		super.onPause();
		suspendDb();
	}

	private void resumeDb () {
		this.log.i("Binding DB service...");
		if (this.bndDb == null) {
			this.bndDb = new DbClient(getActivity(), this.log.getPrefix(), new Runnable() {
				@Override
				public void run () {
					/*
					 * this convoluted method is because the service
					 * connection won't finish until this thread processes
					 * messages again (i.e., after it exits this thread). if
					 * we try to talk to the DB service before then, it will
					 * NPE.
					 */
					getBndDb().getDb().addTwUpdateListener(getGuiUpdateRunnable());
					refreshUi();
					TweetListFragment.this.log.i("DB service bound.");
				}
			});
		}
		else { // because we stop listening in onPause(), we must resume if the user comes back.
			this.bndDb.getDb().addTwUpdateListener(getGuiUpdateRunnable());
			refreshUi();
			this.log.i("DB service rebound.");
		}
	}

	private void suspendDb () {
		// We might be pausing before the callback has come.
		if (this.bndDb.getDb() != null) {
			this.bndDb.getDb().removeTwUpdateListener(getGuiUpdateRunnable());
		}
		else {
			// If we have not even had the callback yet, cancel it.
			this.bndDb.clearReadyListener();
		}
		this.log.i("DB service released.");
	}

	public DbClient getBndDb () {
		return this.bndDb;
	}

	public Runnable getGuiUpdateRunnable () {
		return this.guiUpdateRunnable;
	}

	private final Runnable guiUpdateRunnable = new Runnable() {
		@Override
		public void run () {
			refreshUi();
		}
	};

	protected void refreshUi () {
		ArrayList<Tweet> tweets = this.bndDb.getDb().getTweets(this.columnId, 200);
		this.adapter.setInputData(new TweetList(tweets));
		this.log.i("Refreshed %d tweets.", tweets.size());
	}

}
@@ -30,16 +30,52 @@
 ai.ui;%0A%0A
+import java.lang.ref.WeakReference;%0A
 import j
@@ -121,16 +121,70 @@
 Bundle;%0A
+import android.os.Handler;%0Aimport android.os.Message;%0A
 import a
@@ -824,16 +824,60 @@
 t bndDb;
+%0A%09private RefreshUiHandler refreshUiHandler;
 %0A%0A%09@Over
@@ -1101,16 +1101,70 @@
 mnId);%0A%0A
+%09%09this.refreshUiHandler = new RefreshUiHandler(this);%0A
 %09%09ListVi
@@ -1841,24 +1841,16 @@
  service
-%0A%09%09%09%09%09 *
  connect
@@ -1852,16 +1852,24 @@
 nnection
+%0A%09%09%09%09%09 *
  won't f
@@ -1901,24 +1901,16 @@
 rocesses
-%0A%09%09%09%09%09 *
  message
@@ -1916,16 +1916,24 @@
 es again
+%0A%09%09%09%09%09 *
  (i.e., 
@@ -1963,24 +1963,16 @@
 ead). if
-%0A%09%09%09%09%09 *
  we try 
@@ -1981,16 +1981,24 @@
  talk to
+%0A%09%09%09%09%09 *
  the DB 
@@ -2025,24 +2025,16 @@
  it will
-%0A%09%09%09%09%09 *
  NPE.%0A%09%09
@@ -3052,16 +3052,533 @@
 Ui () %7B%0A
+%09%09this.refreshUiHandler.sendEmptyMessage(0);%0A%09%7D%0A%0A%09private static class RefreshUiHandler extends Handler %7B%0A%0A%09%09private final WeakReference%3CTweetListFragment%3E parentRef;%0A%0A%09%09public RefreshUiHandler (final TweetListFragment parent) %7B%0A%09%09%09this.parentRef = new WeakReference%3CTweetListFragment%3E(parent);%0A%09%09%7D%0A%0A%09%09@Override%0A%09%09public void handleMessage (final Message msg) %7B%0A%09%09%09TweetListFragment parent = this.parentRef.get();%0A%09%09%09if (parent != null) parent.refreshUiOnUiThread();%0A%09%09%7D%0A%0A%09%7D%0A%0A%09protected void refreshUiOnUiThread () %7B%0A
 %09%09ArrayL
@@ -3757,8 +3757,9 @@
 );%0A%09%7D%0A%0A%7D
+%0A

Use Handler to refresh UI on correct thread.