package org.commcare.android.adapters;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;
import org.commcare.android.database.SqlStorage;
import org.commcare.android.database.user.models.FormRecord;
import org.commcare.android.tasks.FormRecordLoaderTask;
import org.commcare.android.util.AndroidCommCarePlatform;
import org.commcare.android.util.SessionUnavailableException;
import org.commcare.android.view.IncompleteFormRecordView;
import org.commcare.dalvik.activities.FormRecordListActivity.FormRecordFilter;
import org.commcare.dalvik.application.CommCareApplication;
import org.commcare.suite.model.Entry;
import org.commcare.suite.model.Suite;
import org.commcare.suite.model.Text;
import android.content.Context;
import android.database.DataSetObserver;
import android.os.AsyncTask.Status;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
/**
* @author ctsims
*
*/
public class IncompleteFormListAdapter extends BaseAdapter {
private AndroidCommCarePlatform platform;
private Context context;
List<DataSetObserver> observers;
FormRecordFilter filter;
private List<FormRecord> records;
private List<FormRecord> current;
private Hashtable<Integer, String[]> searchCache;
private String currentQuery;
FormRecordLoaderTask loader;
Hashtable<String,Text> names;
public IncompleteFormListAdapter(Context context, AndroidCommCarePlatform platform, FormRecordLoaderTask loader) throws SessionUnavailableException{
this.platform = platform;
this.context = context;
this.filter = null;
observers = new ArrayList<DataSetObserver>();
this.loader = loader;
names = new Hashtable<String,Text>();
for(Suite s : platform.getInstalledSuites()) {
for(Enumeration en = s.getEntries().elements(); en.hasMoreElements() ;) {
Entry entry = (Entry)en.nextElement();
if(entry.getXFormNamespace() == null) {
//This is a <view>, not an <entry>, so
//it can't define a form
} else {
names.put(entry.getXFormNamespace(),entry.getText());
}
}
}
}
public void resetRecords() throws SessionUnavailableException {
if(loader.getStatus() == Status.RUNNING) {
loader.cancel(false);
loader = loader.spawn();
} else if(loader.getStatus() == Status.FINISHED) {
loader = loader.spawn();
}
SqlStorage<FormRecord> storage = CommCareApplication._().getUserStorage(FormRecord.class);
if(filter == null) { filter = FormRecordFilter.SubmittedAndPending;}
records = new Vector<FormRecord>();
for(String status : filter.getStatus()) {
records.addAll(storage.getRecordsForValues(new String[] {FormRecord.META_STATUS}, new Object[] {status} ));
}
Collections.sort(records,new Comparator<FormRecord>() {
public int compare(FormRecord one, FormRecord two) {
long ot = one.lastModified().getTime();
long tt = two.lastModified().getTime();
// if(ot == 0) return -1;
// if(tt == 0) return 1;
return ot > tt ? -1 : ot == tt ? 0 : 1;
}
});
searchCache = new Hashtable<Integer, String[]>();
current = new ArrayList<FormRecord>();
this.filterValues(currentQuery);
loader.init(searchCache, names);
loader.execute(records.toArray(new FormRecord[0]));
}
public int findRecordPosition(int formRecordId) {
for(int i = 0 ; i < current.size() ; ++i) {
FormRecord record = current.get(i);
if(record.getID() == formRecordId) {
return i;
}
}
return -1;
}
/*
* (non-Javadoc)
* @see android.widget.BaseAdapter#notifyDataSetChanged()
*/
@Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
for (DataSetObserver observer: observers) {
observer.onChanged();
}
}
/*
* (non-Javadoc)
* @see android.widget.BaseAdapter#notifyDataSetInvalidated()
*/
@Override
public void notifyDataSetInvalidated() {
super.notifyDataSetInvalidated();
resetRecords();
for (DataSetObserver observer: observers) {
observer.onChanged();
}
}
/* (non-Javadoc)
* @see android.widget.ListAdapter#areAllItemsEnabled()
*/
public boolean areAllItemsEnabled() {
return true;
}
/* (non-Javadoc)
* @see android.widget.ListAdapter#isEnabled(int)
*/
public boolean isEnabled(int i) {
return true;
}
/* (non-Javadoc)
* @see android.widget.Adapter#getCount()
*/
public int getCount() {
return current.size();
}
/* (non-Javadoc)
* @see android.widget.Adapter#getItem(int)
*/
public Object getItem(int i) {
return current.get(i);
}
/* (non-Javadoc)
* @see android.widget.Adapter#getItemId(int)
*/
public long getItemId(int i) {
//Skeeeeetccchhyyyy maybe?
return current.get(i).getID();
}
/* (non-Javadoc)
* @see android.widget.Adapter#getItemViewType(int)
*/
public int getItemViewType(int i) {
return 0;
}
/* (non-Javadoc)
* @see android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup)
*/
public View getView(int i, View v, ViewGroup vg) {
FormRecord r = current.get(i);
IncompleteFormRecordView ifrv =(IncompleteFormRecordView)v;
if(ifrv == null) {
ifrv = new IncompleteFormRecordView(context, names);
}
if(searchCache.containsKey(r.getID())) {
ifrv.setParams(r, searchCache.get(r.getID())[1], r.lastModified().getTime());
} else {
//notify the loader that we need access to this record immediately
loader.registerPriority(r);
ifrv.setParams(r, "Loading...", r.lastModified().getTime());
}
return ifrv;
}
/* (non-Javadoc)
* @see android.widget.Adapter#getViewTypeCount()
*/
public int getViewTypeCount() {
return 1;
}
/* (non-Javadoc)
* @see android.widget.Adapter#hasStableIds()
*/
public boolean hasStableIds() {
return true;
}
/* (non-Javadoc)
* @see android.widget.Adapter#isEmpty()
*/
public boolean isEmpty() {
return getCount() > 0;
}
public void setFormFilter(FormRecordFilter filter) throws SessionUnavailableException {
this.filter = filter;
}
public FormRecordFilter getFilter() {
return this.filter;
}
private void filterValues(String query) {
this.currentQuery = query;
current.clear();
if(query == null || query.equals("")) {
current.addAll(records);
return;
}
String[] pieces = query.toLowerCase().split(" ");
//TODO: Don't let this happen until search cache is populated
full:
for(FormRecord r : records) {
for(String cacheValue : searchCache.get(r.getID())) {
for(String piece : pieces) {
if(cacheValue.toLowerCase().contains(piece)) {
current.add(r);
continue full;
}
}
}
}
}
public void applyTextFilter(String query) {
filterValues(query);
for(DataSetObserver o : observers) {
o.onChanged();
}
}
/* (non-Javadoc)
* @see android.widget.Adapter#registerDataSetObserver(android.database.DataSetObserver)
*/
public void registerDataSetObserver(DataSetObserver observer) {
this.observers.add(observer);
}
/* (non-Javadoc)
* @see android.widget.Adapter#unregisterDataSetObserver(android.database.DataSetObserver)
*/
public void unregisterDataSetObserver(DataSetObserver observer) {
this.observers.remove(observer);
}
public void release() {
if(loader.getStatus() == Status.RUNNING) {
loader.cancel(false);
}
}
public boolean isValid(int i) {
if(!names.containsKey(current.get(i).getFormNamespace())) {
return false;
}
return true;
}
}