package com.xda.one.ui;
import com.squareup.otto.Subscribe;
import com.xda.one.R;
import com.xda.one.api.inteface.PrivateMessageClient;
import com.xda.one.api.model.interfaces.Message;
import com.xda.one.api.retrofit.RetrofitPrivateMessageClient;
import com.xda.one.event.message.MessageDeletedEvent;
import com.xda.one.event.message.MessageSentEvent;
import com.xda.one.event.message.MessageStatusToggledEvent;
import com.xda.one.loader.MessageLoader;
import com.xda.one.model.augmented.AugmentedMessage;
import com.xda.one.model.augmented.container.AugmentedMessageContainer;
import com.xda.one.ui.listener.AvatarClickListener;
import com.xda.one.ui.listener.InfiniteRecyclerLoadHelper;
import com.xda.one.ui.widget.XDARefreshLayout;
import com.xda.one.util.UIUtils;
import com.xda.one.util.Utils;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.XDALinerLayoutManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import static com.xda.one.ui.ViewMessageFragment.ViewMessageResult;
public class MessageFragment extends Fragment implements LoaderManager
.LoaderCallbacks<AugmentedMessageContainer> {
private static final String CURRENT_PAGE_LOADER_ARGUMENT = "current_page";
private static final String MESSAGE_FRAGMENT_TYPE = "message_fragment_type";
private static final String MESSAGES_SAVED_STATE = "messages_saved_state";
private static final String PAGES_SAVED_STATE = "total_pages_state";
private static final int VIEW_MESSAGE_REQUEST_CODE = 100;
private final Object mEventHandler = new Object() {
@Subscribe
public void onMessageDeleted(final MessageDeletedEvent event) {
Toast.makeText(getActivity(), R.string.message_delete_successful, Toast.LENGTH_LONG)
.show();
mAdapter.remove(event.message);
}
@Subscribe
public void onMessageSent(final MessageSentEvent event) {
reloadTheFirstPage();
}
@Subscribe
public void onMessageStatusToggled(final MessageStatusToggledEvent event) {
mRefreshLayout.setRefreshing(true);
mAdapter.update(event.message);
}
};
// Global helpers
private PrivateMessageClient mPrivateMessageClient;
// Views
private RecyclerView mRecyclerView;
private XDARefreshLayout mRefreshLayout;
private MessageAdapter mAdapter;
// Helpers
private InfiniteRecyclerLoadHelper mInfiniteScrollListener;
// Data
private MessagePagerFragment.MessageContainerType mMessageContainerType;
private int mTotalPages;
public static MessageFragment getInstance(final MessagePagerFragment
.MessageContainerType type) {
final Bundle bundle = new Bundle();
bundle.putSerializable(MESSAGE_FRAGMENT_TYPE, type);
final MessageFragment fragment = new MessageFragment();
fragment.setArguments(bundle);
return fragment;
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPrivateMessageClient = RetrofitPrivateMessageClient.getClient(getActivity());
// Get the arguments
mMessageContainerType = (MessagePagerFragment.MessageContainerType) getArguments()
.getSerializable(MESSAGE_FRAGMENT_TYPE);
// Create the adapter
mAdapter = new MessageAdapter(getActivity(), new MessageClickListener(),
new AvatarClickListener(getActivity()));
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
final Bundle savedInstanceState) {
return inflater.inflate(R.layout.message_fragment, container, false);
}
@Override
public void onViewCreated(final View view, final Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mRefreshLayout = (XDARefreshLayout) view.findViewById(R.id.swipe_refresh_layout);
mRefreshLayout.setXDAColourScheme();
mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
UIUtils.updateEmptyViewState(getView(), mRecyclerView, mAdapter.getItemCount());
reloadTheFirstPage();
}
});
mRecyclerView = (RecyclerView) view.findViewById(android.R.id.list);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setLayoutManager(new XDALinerLayoutManager(getActivity()));
ViewCompat.setOverScrollMode(mRecyclerView, ViewCompat.OVER_SCROLL_NEVER);
// If the listener already exists then tell it about the new recycler view
if (mInfiniteScrollListener != null) {
mInfiniteScrollListener.updateRecyclerView(mRecyclerView);
}
if (!mAdapter.isEmpty()) {
return;
}
if (savedInstanceState == null) {
loadTheFirstPage();
} else {
final List<AugmentedMessage> messages = savedInstanceState
.getParcelableArrayList(MESSAGES_SAVED_STATE);
if (Utils.isCollectionEmpty(messages)) {
// messages being empty implies a save state call came through when we were loading
// our data for the first time
loadTheFirstPage();
} else {
// This should give a non-zero integer
mTotalPages = savedInstanceState.getInt(PAGES_SAVED_STATE);
mInfiniteScrollListener = new InfiniteRecyclerLoadHelper(mRecyclerView,
new InfiniteLoadCallback(), mTotalPages, null);
addDataToAdapter(messages);
}
}
}
@Override
public void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
final ArrayList<Parcelable> list = new ArrayList<Parcelable>(mAdapter.getMessages());
outState.putParcelableArrayList(MESSAGES_SAVED_STATE, list);
outState.putInt(PAGES_SAVED_STATE, mTotalPages);
}
@Override
public void onResume() {
super.onResume();
mPrivateMessageClient.getBus().register(mEventHandler);
}
@Override
public void onPause() {
super.onPause();
mPrivateMessageClient.getBus().unregister(mEventHandler);
}
@Override
public Loader<AugmentedMessageContainer> onCreateLoader(final int id, final Bundle args) {
final int page = args.getInt(CURRENT_PAGE_LOADER_ARGUMENT);
return new MessageLoader(getActivity(), page, mMessageContainerType);
}
@Override
public void onLoadFinished(final Loader<AugmentedMessageContainer> loader,
final AugmentedMessageContainer data) {
if (data == null) {
// TODO - we need to tailor this to lack of connection/other network issue
addDataToAdapter(null);
return;
}
if (mInfiniteScrollListener != null && !mInfiniteScrollListener.isLoading()
&& !mRefreshLayout.isRefreshing()) {
// This may happen when we are coming back from posts fragment to threads. For some
// reason loadFinished gets called. However, we may have new data about the thread -
// don't disturb this data.
UIUtils.updateEmptyViewState(getView(), mRecyclerView, false);
mRecyclerView.setOnScrollListener(mInfiniteScrollListener);
return;
} else if (data.getCurrentPage() == 1 || mInfiniteScrollListener == null) {
mAdapter.clear();
mTotalPages = data.getTotalPages();
mInfiniteScrollListener = new InfiniteRecyclerLoadHelper(mRecyclerView,
new InfiniteLoadCallback(), mTotalPages, null);
}
mInfiniteScrollListener.onLoadFinished();
addDataToAdapter(data.getMessages());
if (!mInfiniteScrollListener.hasMoreData()) {
mAdapter.removeFooter();
}
}
@Override
public void onLoaderReset(final Loader<AugmentedMessageContainer> loader) {
}
@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == VIEW_MESSAGE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
final Bundle arguments = data.getBundleExtra(ViewMessageFragment
.ACTIVITY_RESULT_BUNDLE_ARGUMENTS);
final AugmentedMessage message = arguments
.getParcelable(ViewMessageFragment.MESSAGE_ARGUMENT);
ViewMessageResult result = (ViewMessageResult) arguments
.getSerializable(ViewMessageFragment.ACTIVITY_RESULT_BUNDLE_ARGUMENTS_RESULT);
if (result == null) {
result = ViewMessageResult.CHANGED;
}
switch (result) {
case CHANGED:
mAdapter.update(message);
break;
case DELETED:
mAdapter.remove(message);
break;
}
}
}
private void addDataToAdapter(final List<? extends Message> data) {
UIUtils.updateEmptyViewState(getView(), mRecyclerView, data == null ? 0 : data.size());
// Let's actually add the items now
mAdapter.addAll(data);
mRefreshLayout.setRefreshing(false);
}
private void loadTheFirstPage() {
final Bundle bundle = new Bundle();
bundle.putInt(CURRENT_PAGE_LOADER_ARGUMENT, 1);
getLoaderManager().initLoader(0, bundle, MessageFragment.this);
}
private void reloadTheFirstPage() {
final Bundle bundle = new Bundle();
bundle.putInt(CURRENT_PAGE_LOADER_ARGUMENT, 1);
getLoaderManager().restartLoader(0, bundle, MessageFragment.this);
}
private class InfiniteLoadCallback implements InfiniteRecyclerLoadHelper.Callback {
@Override
public void loadMoreData(final int page) {
final Bundle bundle = new Bundle();
bundle.putInt(CURRENT_PAGE_LOADER_ARGUMENT, page);
getLoaderManager().restartLoader(0, bundle, MessageFragment.this);
}
}
private class MessageClickListener implements View.OnClickListener {
@Override
public void onClick(View view) {
final int position = mRecyclerView.getChildPosition(view);
if (position == RecyclerView.NO_POSITION) {
return;
}
final Message message = mAdapter.getMessage(position);
final Intent intent = new Intent(getActivity(), ViewMessageActivity.class);
intent.putExtra(ViewMessageFragment.MESSAGE_ARGUMENT, message);
getParentFragment().startActivityForResult(intent, VIEW_MESSAGE_REQUEST_CODE);
}
}
}