public class ChangeListFragment extends Fragment {

  private static final String TAG = ChangeListFragment.class.getSimpleName();
  /**
   * The {@link android.support.v4.view.PagerAdapter} that will provide fragments for each of the
   * sections.
   */
  private SectionsPagerAdapter mSectionsPagerAdapter;

  private ViewPager mViewPager;
  private FragmentActivity mParent;
  private ArrayList<CharSequence> mTitles;
  private EventBus mEventBus;

  // This should be set to the status corresponding to the initially selected tab
  private String mSelectedStatus = JSONCommit.Status.NEW.toString();

  @Override
  public View onCreateView(
      LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.change_list, container, false);
  }

  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    setupTabs();
  }

  /** MUST BE CALLED ON MAIN THREAD */
  private void setupTabs() {

    mParent = getActivity();

    mEventBus = EventBus.getDefault();

    // Create the adapter that will return a fragment for each of the three
    // primary sections of the app.
    mSectionsPagerAdapter = new SectionsPagerAdapter(mParent.getSupportFragmentManager());

    // Set up the ViewPager with the sections adapter.
    /** The {@link android.support.v4.view.ViewPager} that will host the section contents. */
    mViewPager = (ViewPager) this.getView();
    mViewPager.setAdapter(mSectionsPagerAdapter);

    // When swiping between different sections, select the corresponding
    // tab. We can also use ActionBar.Tab#select() to do this if we have
    // a reference to the Tab.
    mViewPager.addOnPageChangeListener(
        new ViewPager.SimpleOnPageChangeListener() {
          @Override
          public void onPageSelected(int position) {
            String status = mSectionsPagerAdapter.getStatusAtPostion(position);

            mEventBus.post(new StatusSelected(status));
            mSelectedStatus = status;
            CardsFragment fragment = mSectionsPagerAdapter.getFragment(position);
            if (fragment == null) {
              // It may just have not been instantiated yet
              fragment = (CardsFragment) mSectionsPagerAdapter.getItem(position);
              if (fragment == null) {
                Log.e(
                    TAG,
                    String.format("Cannot refresh the page selected at position %d", position));
                return; // We cannot do any more here
              }
            }
            fragment.refresh(false);
          }
        });

    mTitles = new ArrayList<>();
    for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++)
      mTitles.add(mSectionsPagerAdapter.getPageTitle(i));
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    mViewPager.clearOnPageChangeListeners();
  }

  public void refreshTabs() {
    mSectionsPagerAdapter.refreshTabs();
  }

  public CardsFragment getCurrentFragment() {
    return mSectionsPagerAdapter.getCurrentFragment();
  }

  public String getStatus() {
    return mSelectedStatus;
  }

  /**
   * A {@link android.support.v4.app.FragmentStatePagerAdapter} that returns a fragment
   * corresponding to one of the sections/tabs/pages.
   */
  class SectionsPagerAdapter extends FragmentStatePagerAdapter {
    public int mPageCount = 3;

    ReviewTab mReviewTab = null;
    MergedTab mMergedTab = null;
    AbandonedTab mAbandonedTab = null;

    SectionsPagerAdapter(FragmentManager fm) {
      super(fm);
    }

    public String getStatusAtPostion(int position) {
      switch (position) {
        case 0:
          return JSONCommit.KEY_STATUS_OPEN;
        case 1:
          return JSONCommit.KEY_STATUS_MERGED;
        case 2:
          return JSONCommit.KEY_STATUS_ABANDONED;
        default:
          return null;
      }
    }

    @Override
    /**
     * Called to instantiate the fragment for the given page. IMPORTANT: Do not use this to monitor
     * the currently selected page as it is used to load neighbouring tabs that may not be selected.
     */
    public Fragment getItem(int position) {
      CardsFragment fragment;

      switch (position) {
        case 0:
          fragment = new ReviewTab();
          mReviewTab = (ReviewTab) fragment;
          break;
        case 1:
          fragment = new MergedTab();
          mMergedTab = (MergedTab) fragment;
          break;
        case 2:
          fragment = new AbandonedTab();
          mAbandonedTab = (AbandonedTab) fragment;
          break;
        default:
          return null;
      }

      return fragment;
    }

    // The ViewPager monitors the current tab position so we can get the
    //  ViewPager from the enclosing class and use the fragment recording
    //  to get the current fragment
    @Nullable
    public CardsFragment getCurrentFragment() {
      int pos = mViewPager.getCurrentItem();
      return getFragment(pos);
    }

    public CardsFragment getFragment(int pos) {
      switch (pos) {
        case 0:
          return mReviewTab;
        case 1:
          return mMergedTab;
        case 2:
          return mAbandonedTab;
        default:
          return null;
      }
    }

    @Override
    /** Return the number of views available. */
    public int getCount() {
      return mPageCount;
    }

    @Override
    /** Called by the ViewPager to obtain a title string to describe the specified page. */
    public CharSequence getPageTitle(int position) {
      switch (position) {
        case 0:
          return getString(R.string.reviewable);
        case 1:
          return getString(R.string.merged);
        case 2:
          return getString(R.string.abandoned);
      }
      return null;
    }

    private void refreshTabs() {
      if (mReviewTab != null) mReviewTab.markDirty();
      if (mMergedTab != null) mMergedTab.markDirty();
      if (mAbandonedTab != null) mAbandonedTab.markDirty();
      // Its possible the current fragment may be null... if that happens
      // reload the page
      CardsFragment currentFragment = getCurrentFragment();
      if (currentFragment == null) {
        onCreate(null);
      } else {
        currentFragment.refresh(true);
      }
    }
  }
}
  private void init() {
    View currentFragment = this.getView();

    ExpandableListView mListView =
        (ExpandableListView) currentFragment.findViewById(R.id.commit_cards);
    disconnectedView = currentFragment.findViewById(R.id.disconnected_view);

    sIsLegacyVersion = !Config.isDiffSupported(mParent);

    mAdapter = new CommitDetailsAdapter(mParent);
    mListView.setAdapter(mAdapter);

    // Child click listeners (relevant for the changes cards)
    mListView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
    mFilesCAB = new FilesCAB(mParent, !sIsLegacyVersion);
    mAdapter.setContextualActionBar(mFilesCAB);
    mListView.setOnItemLongClickListener(
        new AdapterView.OnItemLongClickListener() {
          @Override
          public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            ExpandableListView listView = (ExpandableListView) parent;
            long pos = listView.getExpandableListPosition(position);
            int groupPos = ExpandableListView.getPackedPositionGroup(pos);
            int childPos = ExpandableListView.getPackedPositionChild(pos);

            if (!mAdapter.isLongClickSupported(groupPos, childPos)) {
              return false;
            }

            // In case this is a group view and does not have the change number tagged
            view.setTag(R.id.changeID, mSelectedChange);
            FilesCAB.TagHolder holder =
                new FilesCAB.TagHolder(view, mContext, groupPos, childPos >= 0);

            // Set the title to be shown in the action bar
            if (holder.filePath != null) {
              mFilesCAB.setTitle(holder.filePath);
            } else {
              String s = mParent.getResources().getString(R.string.change_detail_heading);
              mFilesCAB.setTitle(String.format(s, holder.changeNumber.intValue()));
            }

            mFilesCAB.setActionMode(getActivity().startActionMode(mFilesCAB));
            ActionMode actionMode = mFilesCAB.getActionMode();

            // Call requires API 14 (ICS)
            actionMode.setTag(holder);
            view.setSelected(true);
            return true;
          }
        });
    mListView.setOnChildClickListener(
        new ExpandableListView.OnChildClickListener() {
          @Override
          public boolean onChildClick(
              ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
            // This is only valid for the changed files group
            int childItemType = mAdapter.getChildType(groupPosition, childPosition);
            if (childItemType != CommitDetailsAdapter.Cards.CHANGED_FILES.ordinal()) {
              return false;
            }
            // View the diff and close the CAB if a change diff could be viewed
            boolean diffLaunched = PatchSetChangesCard.onViewClicked(mParent, v);
            if (diffLaunched) {
              ActionMode mode = mFilesCAB.getActionMode();
              if (mode != null) mode.finish();
            }
            return diffLaunched;
          }
        });

    // Remember to expand the groups which don't have a header otherwise they will not be shown
    mListView.expandGroup(0);

    Button retryButton = (Button) currentFragment.findViewById(R.id.btn_retry);
    retryButton.setOnClickListener(
        new View.OnClickListener() {
          @Override
          public void onClick(View v) {
            sendRequest(GerritService.DataType.CommitDetails);
          }
        });

    if (getArguments() == null) {
      /** This should be the default value of {@link ChangeListFragment.mSelectedStatus } */
      setStatus(JSONCommit.Status.NEW.toString());
      loadChange(true);
    } else {
      Bundle args = getArguments();
      setStatus(args.getString(STATUS));
      String changeid = args.getString(CHANGE_ID);
      mChangeNumber = args.getInt(CHANGE_NO);

      if (changeid != null && !changeid.isEmpty()) {
        loadChange(changeid);
      }
    }

    mEventBus = EventBus.getDefault();
  }