package by.istin.android.xcore.fragment;
import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.Loader;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import by.istin.android.xcore.error.IErrorHandler;
import by.istin.android.xcore.fragment.CursorLoaderFragmentHelper.ICursorLoaderFragmentHelper;
import by.istin.android.xcore.model.CursorModel;
import by.istin.android.xcore.service.DataSourceService;
import by.istin.android.xcore.service.StatusResultReceiver;
import by.istin.android.xcore.source.DataSourceRequest;
import by.istin.android.xcore.source.impl.http.HttpAndroidDataSource;
import by.istin.android.xcore.utils.AppUtils;
import by.istin.android.xcore.utils.CursorUtils;
import by.istin.android.xcore.utils.ResponderUtils;
import by.istin.android.xcore.utils.StringUtil;
public abstract class XFragment extends Fragment implements IRefresh, ICursorLoaderFragmentHelper,IDataSourceHelper,
DataSourceExecuteHelper.IDataSourceListener {
@Override
public int getLoaderId() {
return getUri().hashCode();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(getViewLayout(), container, false);
onViewCreated(view);
return view;
}
@Override
public void setServiceWork(boolean isWork) {
}
@Override
public void onError(Exception e, DataSourceRequest dataSourceRequest) {
}
@Override
public void onReceiverOnCached(Bundle resultData) {
}
@Override
public void onReceiverOnDone(Bundle resultData) {
}
@Override
public DataSourceExecuteHelper.IDataSourceListener getDataSourceListener() {
return this;
}
public void onViewCreated(View view) {
}
public abstract int getViewLayout();
public String getSelection() {
return null;
}
public String getOrder() {
return null;
}
public String[] getSelectionArgs() {
return null;
}
public String[] getProjection() {
return null;
}
public abstract Uri getUri();
public abstract String getUrl();
public abstract String getProcessorKey();
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return CursorLoaderFragmentHelper.onCreateLoader(this, id, args);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
FragmentActivity activity = getActivity();
if (activity == null) {
return;
}
onLoadFinished(cursor);
View view = getView();
if (view == null) {
return;
}
if (isServiceWork) {
hideEmptyView(view);
}
if (CursorUtils.isEmpty(cursor)) {
return;
}
cursor.moveToFirst();
int[] adapterControlIds = getAdapterControlIds();
String[] adapterColumns = getAdapterColumns();
final int count = adapterControlIds.length;
for (int i = 0; i < count; i++) {
final View v = view.findViewById(adapterControlIds[i]);
if (v != null) {
String text = CursorUtils.getString(adapterColumns[i], cursor);
if (text == null) {
text = "";
}
if (v instanceof TextView) {
setViewText((TextView) v, text);
} else if (v instanceof ImageView) {
setViewImage((ImageView) v, text);
} else {
throw new IllegalStateException(v.getClass().getName() + " is not a " +
" view that can be bounds by this SimpleCursorAdapter");
}
}
}
}
protected void setViewImage(ImageView v, String text) {
//TODO plugins
}
protected void setViewText(TextView v, String text) {
if (StringUtil.isEmpty(text)) {
v.setText(StringUtil.EMPTY);
} else {
v.setText(text);
}
}
protected abstract void onLoadFinished(Cursor cursor);
protected abstract String[] getAdapterColumns();
protected abstract int[] getAdapterControlIds();
private boolean isServiceWork = false;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
CursorLoaderFragmentHelper.onActivityCreated(this, savedInstanceState);
String url = getUrl();
if (!StringUtil.isEmpty(url)) {
loadData(getActivity(), url, isForceUpdateData());
}
}
public void refresh() {
loadData(getActivity(), getUrl(), true);
}
protected void loadData(Activity activity, String url) {
loadData(activity, url, isForceUpdateData());
}
@Override
public void dataSourceExecute(Context context, final DataSourceRequest dataSourceRequest) {
String processorKey = getProcessorKey();
String dataSourceKey = getDataSourceKey();
dataSourceExecute(context, dataSourceRequest, processorKey, dataSourceKey);
}
protected void dataSourceExecute(Context context, final DataSourceRequest dataSourceRequest, String processorKey, String dataSourceKey) {
DataSourceService.execute(context, dataSourceRequest, processorKey, dataSourceKey, new StatusResultReceiver(new Handler(Looper.getMainLooper())) {
@Override
public void onStart(Bundle resultData) {
isServiceWork = true;
}
@Override
public void onError(Exception exception) {
isServiceWork = false;
exception.printStackTrace();
FragmentActivity activity = getActivity();
if (activity == null) {
return;
}
IErrorHandler errorHandler = AppUtils.get(activity, IErrorHandler.SYSTEM_SERVICE_KEY);
if (errorHandler != null) {
errorHandler.onError(activity, XFragment.this, dataSourceRequest, exception);
} else {
Toast.makeText(activity, exception.getMessage(), Toast.LENGTH_SHORT).show();
}
hideProgress();
}
@Override
public void onDone(Bundle resultData) {
isServiceWork = false;
FragmentActivity fragmentActivity = getActivity();
if (fragmentActivity == null) {
return;
}
hideProgress();
onReceiverOnDone(resultData);
}
@Override
protected void onCached(Bundle resultData) {
isServiceWork = false;
onReceiverOnCached(resultData);
super.onCached(resultData);
hideProgress();
}
});
}
protected void loadData(Activity activity, String url, Boolean isForceUpdate) {
final DataSourceRequest dataSourceRequest = new DataSourceRequest(url);
loadData(activity, isForceUpdate, dataSourceRequest);
}
protected void loadData(Activity activity, Boolean isForceUpdate, DataSourceRequest dataSourceRequest) {
dataSourceRequest.setCacheable(isCacheable());
dataSourceRequest.setCacheExpiration(getCacheExpiration());
dataSourceRequest.setForceUpdateData(isForceUpdate);
dataSourceExecute(activity, dataSourceRequest);
}
protected boolean isForceUpdateData() {
return false;
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
if (getView() != null) {
onLoaderReset();
hideProgress();
}
}
protected abstract void onLoaderReset();
public String getDataSourceKey() {
return HttpAndroidDataSource.SYSTEM_SERVICE_KEY;
}
public long getCacheExpiration() {
return DateUtils.HOUR_IN_MILLIS;
}
public boolean isCacheable() {
return true;
}
@Override
public void hideProgress() {
View view = getView();
if (view == null) {
return;
}
View progressView = view.findViewById(android.R.id.progress);
if (progressView != null) {
progressView.setVisibility(View.GONE);
}
}
@Override
public void showProgress() {
View view = getView();
if (view == null) {
return;
}
View progressView = view.findViewById(android.R.id.progress);
if (progressView != null) {
progressView.setVisibility(View.VISIBLE);
}
hideEmptyView(view);
}
public void hideEmptyView(View view) {
if (view == null) return;
View emptyView = view.findViewById(android.R.id.empty);
if (emptyView != null) {
emptyView.setVisibility(View.GONE);
}
}
@Override
public CursorModel.CursorModelCreator getCursorModelCreator() {
return CursorModel.CursorModelCreator.DEFAULT;
}
protected <T> T findFirstResponderFor(Class<T> clazz) {
return ResponderUtils.findFirstResponderFor(this, clazz);
}
}