package org.ovirt.mobile.movirt.ui.listfragment;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.content.Loader;
import android.support.v4.widget.SwipeRefreshLayout;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Spinner;
import com.melnykov.fab.FloatingActionButton;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Background;
import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.EFragment;
import org.androidannotations.annotations.InstanceState;
import org.androidannotations.annotations.ItemClick;
import org.androidannotations.annotations.UiThread;
import org.androidannotations.annotations.ViewById;
import org.ovirt.mobile.movirt.R;
import org.ovirt.mobile.movirt.facade.EntityFacade;
import org.ovirt.mobile.movirt.facade.EntityFacadeLocator;
import org.ovirt.mobile.movirt.model.base.OVirtEntity;
import org.ovirt.mobile.movirt.provider.ProviderFacade;
import org.ovirt.mobile.movirt.provider.SortOrder;
import org.ovirt.mobile.movirt.sync.SyncUtils;
import org.ovirt.mobile.movirt.ui.EndlessScrollListener;
import org.ovirt.mobile.movirt.ui.HasLoader;
import org.ovirt.mobile.movirt.ui.ProgressBarResponse;
import org.ovirt.mobile.movirt.ui.RefreshableLoaderFragment;
import org.ovirt.mobile.movirt.ui.listfragment.spinner.CustomSort;
import org.ovirt.mobile.movirt.ui.listfragment.spinner.SortEntry;
import org.ovirt.mobile.movirt.ui.listfragment.spinner.SortOrderType;
import org.ovirt.mobile.movirt.util.CursorAdapterLoader;
import org.springframework.util.StringUtils;
import java.util.List;
import static org.ovirt.mobile.movirt.provider.OVirtContract.NamedEntity.NAME;
@EFragment(R.layout.fragment_base_entity_list)
public abstract class BaseEntityListFragment<E extends OVirtEntity> extends RefreshableLoaderFragment
implements HasLoader {
private static final int ITEMS_PER_PAGE = 20;
private static final int ASCENDING_INDEX = 0, DESCENDING_INDEX = 1; // order spinner indexes
@Bean
protected SyncUtils syncUtils;
@ViewById(android.R.id.list)
protected ListView listView;
@ViewById
protected EditText searchText;
@ViewById
protected Spinner orderBySpinner;
@ViewById
protected Spinner orderSpinner;
@ViewById
protected SwipeRefreshLayout swipeContainer;
@Bean
protected ProviderFacade provider;
@Bean
protected EntityFacadeLocator entityFacadeLocator;
@ViewById
public ListView list;
@ViewById
public FloatingActionButton fab;
@ViewById
public LinearLayout searchbox;
@ViewById
public LinearLayout orderingLayout;
@InstanceState
public boolean searchtoggle;
@InstanceState
public int orderBySpinnerPosition;
@InstanceState
public int orderSpinnerPosition;
protected EntityFacade<E> entityFacade;
private final Class<E> entityClass;
private final TextWatcher textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
}
@Override
public void afterTextChanged(Editable editable) {
resetListViewPosition();
restartLoader();
}
};
protected final EndlessScrollListener endlessScrollListener = new EndlessScrollListener() {
@Override
public void onLoadMore(int page, int totalItemsCount) {
loadMoreData(page);
}
};
protected int page = 1;
protected CursorAdapterLoader cursorAdapterLoader;
protected BaseEntityListFragment(Class<E> clazz) {
this.entityClass = clazz;
}
public void loadMoreData(int page) {
this.page = page;
restartLoader();
}
protected void resetListViewPosition() {
page = 1;
listView.smoothScrollToPosition(0);
endlessScrollListener.resetListener();
}
public void setOrderingSpinners(String orderBy, SortOrder order) {
if (order == null || orderBy == null) {
return;
}
for (int i = 0; i < orderBySpinner.getCount(); i++) {
SortEntry sortEntry = (SortEntry) orderBySpinner.getItemAtPosition(i);
if (sortEntry.getItemName().getColumnName().equals(orderBy)) {
orderSpinnerPosition = (order == SortOrder.ASCENDING) ? ASCENDING_INDEX : DESCENDING_INDEX;
orderSpinner.setSelection(AdapterView.INVALID_POSITION); // gets reset by orderBySpinner
orderBySpinner.setSelection(i);
break;
}
}
}
class OrderItemSelectedListener implements AdapterView.OnItemSelectedListener {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
orderSpinnerPosition = i;
resetListViewPosition();
restartLoader();
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
}
class OrderByItemSelectedListener implements AdapterView.OnItemSelectedListener {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
orderBySpinnerPosition = i;
int orderPosition = orderSpinner.getSelectedItemPosition();
if (orderPosition == AdapterView.INVALID_POSITION) {
orderPosition = orderSpinnerPosition;
}
final SortEntry orderBy = (SortEntry) adapterView.getSelectedItem();
final SortOrderType sortOrderType = orderBy.getSortOrder();
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(getActivity(),
android.R.layout.simple_spinner_item, new String[]{
sortOrderType.getAscDisplayName(), // ASCENDING_INDEX
sortOrderType.getDescDisplayName() // DESCENDING_INDEX
});
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
orderSpinner.setAdapter(spinnerArrayAdapter);
orderSpinner.setSelection(orderPosition); // refreshes loader
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
}
@Override
protected SwipeRefreshLayout getSwipeRefreshLayout() {
return swipeContainer;
}
@AfterViews
protected void init() {
entityFacade = entityFacadeLocator.getFacade(entityClass);
initSpinners();
initAdapters();
initListeners();
}
private void initSpinners() {
if (getCustomSort() == null) {
ArrayAdapter<SortEntry> spinnerArrayAdapter = new ArrayAdapter<>(getActivity(),
android.R.layout.simple_spinner_item, getSortEntries());
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
orderBySpinner.setAdapter(spinnerArrayAdapter);
orderBySpinner.setSelection(orderBySpinnerPosition); // initializes orderSpinner
} else {
orderingLayout.setVisibility(View.GONE);
}
}
protected void initAdapters() {
final CursorAdapter cursorAdapter = createCursorAdapter();
listView.setAdapter(cursorAdapter);
listView.setEmptyView(getActivity().findViewById(android.R.id.empty));
listView.setTextFilterEnabled(true);
cursorAdapterLoader = new CursorAdapterLoader(cursorAdapter) {
@Override
public synchronized Loader<Cursor> onCreateLoader(int id, Bundle args) {
ProviderFacade.QueryBuilder<E> query = provider.query(entityClass);
appendQuery(query);
String searchNameString = searchText.getText().toString();
if (!StringUtils.isEmpty(searchNameString)) {
query.whereLike(NAME, "%" + searchNameString + "%");
}
final CustomSort customSort = getCustomSort();
if (customSort == null) {
final SortEntry orderBy = (SortEntry) orderBySpinner.getSelectedItem();
final SortOrder order = SortOrderType.getSortOrder((String) orderSpinner.getSelectedItem());
query.orderBy(orderBy.getItemName().getColumnName(), order);
} else {
for (CustomSort.CustomSortEntry entry : customSort.getSortEntries()) {
query.orderBy(entry.getColumnName(), entry.getSortOrder());
}
}
return query.limit(page * ITEMS_PER_PAGE).asLoader();
}
};
getLoaderManager().initLoader(0, null, cursorAdapterLoader);
}
protected void appendQuery(ProviderFacade.QueryBuilder<E> query) {
// left intentionally empty
}
protected void initListeners() {
listView.setOnScrollListener(endlessScrollListener);
searchText.removeTextChangedListener(textWatcher);
searchText.addTextChangedListener(textWatcher);
orderBySpinner.setOnItemSelectedListener(new OrderByItemSelectedListener());
orderSpinner.setOnItemSelectedListener(new OrderItemSelectedListener());
fab.setColorPressed(Color.parseColor("#80cbc4"));
fab.setColorRipple(getResources().getColor(R.color.abc_search_url_text_selected));
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
toggleSearchBoxVisibility();
}
});
}
public CustomSort getCustomSort() {
return null;
}
public SortEntry[] getSortEntries() {
return new SortEntry[]{};
}
@UiThread(propagation = UiThread.Propagation.REUSE)
public void setSearchBoxVisibility(boolean visible) {
if (visible) {
searchbox.setVisibility(View.VISIBLE);
} else {
searchbox.setVisibility(View.GONE);
}
}
public void toggleSearchBoxVisibility() {
searchtoggle = !searchtoggle;
setSearchBoxVisibility(searchtoggle);
}
@UiThread(propagation = UiThread.Propagation.REUSE)
@Override
public void restartLoader() {
getLoaderManager().restartLoader(0, null, cursorAdapterLoader);
}
@Override
public void destroyLoader() {
getLoaderManager().destroyLoader(0);
}
@Override
public void onResume() {
super.onResume();
restartLoader();
setSearchBoxVisibility(searchtoggle);
}
@Override
public void onPause() {
super.onPause();
}
@ItemClick(android.R.id.list)
protected void itemClicked(Cursor cursor) {
if (entityFacade != null) {
E entity = entityFacade.mapFromCursor(cursor);
Intent intent = entityFacade.getDetailIntent(entity, getActivity());
if (intent != null) {
startActivity(intent);
}
}
}
@Override
@Background
public void onRefresh() {
if (entityFacade != null) {
entityFacade.syncAll(new ProgressBarResponse<List<E>>(this));
}
}
protected abstract CursorAdapter createCursorAdapter();
}