package com.vaguehope.onosendai.ui;
import java.lang.ref.WeakReference;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.widget.TextView;
import com.vaguehope.onosendai.util.exec.ExecutorEventListener;
public class ExecutorStatus implements ExecutorEventListener {
private final TextView textView;
private final RefreshUiHandler refreshUiHandler;
private final Map<Thread, String> threads = new ConcurrentSkipListMap<Thread, String>(new Comparator<Thread>() {
@Override
public int compare (final Thread lhs, final Thread rhs) {
final long thisVal = lhs.getId();
final long anotherVal = rhs.getId();
return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1));
}
});
private final Map<Long, String> threadPoolNames = new ConcurrentHashMap<Long, String>();
public ExecutorStatus (final TextView textView) {
this.textView = textView;
textView.setHorizontallyScrolling(true);
textView.setEllipsize(null);
this.refreshUiHandler = new RefreshUiHandler(this);
}
@Override
public void execStart (final String logPrefix, final Runnable command) {
this.threads.put(Thread.currentThread(), "[task]");
final Long key = Long.valueOf(Thread.currentThread().getId());
if (!this.threadPoolNames.containsKey(key)) this.threadPoolNames.put(key, logPrefix);
this.refreshUiHandler.sendEmptyMessage(0);
}
@Override
public void execStart (final AsyncTask<?, ?, ?> task) {
this.threads.put(Thread.currentThread(), task.toString());
this.refreshUiHandler.sendEmptyMessage(0);
}
@Override
public void execEnd (final AsyncTask<?, ?, ?> task) {
// Unused.
}
@Override
public void execEnd (final Runnable command) {
this.threads.put(Thread.currentThread(), "idle.");
this.refreshUiHandler.sendEmptyMessage(1);
}
private static class RefreshUiHandler extends Handler {
private final WeakReference<ExecutorStatus> parentRef;
public RefreshUiHandler (final ExecutorStatus parent) {
this.parentRef = new WeakReference<ExecutorStatus>(parent);
}
@Override
public void handleMessage (final Message msg) {
final ExecutorStatus parent = this.parentRef.get();
if (parent != null) parent.msgOnUiThread();
}
}
private long lastUpdate = 0L;
private boolean sentReminder = false;
protected void msgOnUiThread () {
if (SystemClock.uptimeMillis() - this.lastUpdate < 100) {
if (!this.sentReminder) {
this.refreshUiHandler.sendEmptyMessageDelayed(2, 200);
this.sentReminder = true;
}
return;
}
cleapThreads();
redraw();
this.lastUpdate = SystemClock.uptimeMillis();
this.sentReminder = false;
}
private void cleapThreads () {
final Iterator<Entry<Thread, String>> i = this.threads.entrySet().iterator();
while (i.hasNext()) {
final Thread t = i.next().getKey();
if (!t.isAlive()) {
i.remove();
this.threadPoolNames.remove(Long.valueOf(t.getId()));
}
}
}
private void redraw () {
final StringBuilder s = new StringBuilder();
for (final Entry<Thread, String> e : this.threads.entrySet()) {
if (s.length() > 0) s.append("\n");
s.append(this.threadPoolNames.get(Long.valueOf(e.getKey().getId())))
.append(" ").append(e.getKey().getId())
.append(" ").append(e.getValue());
}
if (s.length() < 1) s.append("idle.");
this.textView.setText(s);
}
}