package what.whatandroid.forums.thread;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.ViewPager;
import android.util.SparseArray;
import android.view.ViewGroup;
import api.forum.thread.ForumThread;
import api.soup.MySoup;
import what.whatandroid.callbacks.LoadingListener;
import what.whatandroid.callbacks.OnLoggedInCallback;
import what.whatandroid.views.MovableFragmentStatePagerAdapter;
/**
* Adapter for swiping through the pages of a thread
*/
public class ThreadPagerAdapter extends MovableFragmentStatePagerAdapter implements OnLoggedInCallback, LoadingListener<ForumThread> {
private LoadingListener<ForumThread> listener;
private SparseArray<ThreadListFragment> fragments = new SparseArray<ThreadListFragment>();
/**
* The number of pages in the thread, the thread being viewed,
* the post id to jump to (if any) and the page that post is on
*/
private int pages, thread, postId, postPage;
/**
* View pager we're given when trying to refresh posts and jump to the last one
* also used to track if we're refreshing posts to show our new reply as it
* will only be non-null if we're doing that
*/
private ViewPager viewPager;
/**
* Create a fragment pager view displaying the paged lists of posts in the thread
*
* @param pages number of pages to display initially. Will be updated to the total
* amount after loading the first page
* @param thread thread id to display
* @param postId post id to jump to, or -1 to ignore
*/
public ThreadPagerAdapter(FragmentManager fm, int pages, int thread, int postId){
super(fm);
this.pages = pages;
this.thread = thread;
this.postId = postId;
this.postPage = -1;
}
@Override
public Fragment getItem(int position){
//Page numbers start at 1 but positions are 0-indexed
if (position == 0 && postId != -1){
return ThreadListFragment.newInstancePost(thread, postId);
}
return ThreadListFragment.newInstance(thread, position + 1);
}
@Override
public CharSequence getPageTitle(int position){
return pages == 0 ? "Loading" : "page " + (position + 1) + " of " + pages;
}
@Override
public int getCount(){
return pages == 0 ? 1 : pages;
}
@Override
public Object instantiateItem(ViewGroup container, int position){
ThreadListFragment f = (ThreadListFragment)super.instantiateItem(container, position);
if (MySoup.isLoggedIn()){
f.onLoggedIn();
}
f.setListener(this);
fragments.put(position, f);
return f;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object){
super.destroyItem(container, position, object);
fragments.remove(position);
}
@Override
public void onLoggedIn(){
for (int i = 0; i < fragments.size(); ++i){
fragments.valueAt(i).onLoggedIn();
}
}
public void refresh() {
for (int i = 0; i < fragments.size(); ++i) {
fragments.valueAt(i).refresh();
}
}
public void setLoadingListener(LoadingListener<ForumThread> listener){
this.listener = listener;
}
@Override
public int getItemPosition(Object object){
if (hasMovedPages() && object == fragments.get(0)){
fragments.put(postPage, fragments.get(0));
return postPage;
}
return POSITION_UNCHANGED;
}
@Override
public boolean hasMovedPages(){
return postPage != -1;
}
@Override
public void onPagesMoved(){
postPage = -1;
}
/**
* Update the view pager to show all pages in the thread, now that we know how many
* there are
*
* @param data the loaded data
*/
@Override
public void onLoadingComplete(ForumThread data){
//If this is the first page we've loaded update the listener and jump to a post if desired
if (pages == 0){
pages = data.getPages();
//If we're jumping to a post get the page that it's on so we can jump to it
if (postId != -1){
postPage = data.getPage() - 1;
postId = -1;
}
notifyDataSetChanged();
listener.onLoadingComplete(data);
}
//If we're jumping to the last post after making one and our new post has
//added a new page on the thread jump to this new page
else if (viewPager != null && viewPager.getCurrentItem() == data.getPage() - 1 && data.hasNextPage()){
pages = data.getPages();
notifyDataSetChanged();
viewPager.setCurrentItem(pages - 1);
fragments.get(viewPager.getCurrentItem()).reloadPosts();
viewPager = null;
}
}
/**
* Jump the adapter to the last post in the thread and refresh the last page
* This should be used when adding a new post to the thread and we want
* to update the last page to see any new posts (including our own)
*
* @param pager The viewpager showing the data from the adapter, we need
* this to be able to update the selected page appropriately
*/
public void getNewPosts(ViewPager pager){
viewPager = pager;
//Jump to the last page we know of, note that we may need to go one more page
//if the new post created a new page. This is handled in our loading listener
if (pages > 0 && viewPager.getCurrentItem() != pages - 1){
viewPager.setCurrentItem(pages - 1);
}
fragments.get(viewPager.getCurrentItem()).reloadPosts();
}
}