content: /*
   * Created by LuaView.
   * Copyright (c) 2017, Alibaba Group. All rights reserved.
   *
   * This source code is licensed under the MIT.
   * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
   */
  
  package com.taobao.luaview.view.viewpager;
  
  import android.content.Context;
  import android.support.v4.view.PagerAdapter;
  import android.support.v4.view.ViewPager;
  
  import com.taobao.luaview.util.LogUtil;
  import com.taobao.luaview.view.adapter.LVLoopPagerAdapter;
  
  /**
   * A ViewPager subclass enabling infinte scrolling of the viewPager elements
   * <p/>
   * When used for paginating views (in opposite to fragments), no code changes
   * should be needed only change xml's from <android.support.v4.view.ViewPager>
   * to <com.imbryk.viewPager.LoopViewPager>
   * <p/>
   * If "blinking" can be seen when paginating to first or last view, simply call
   * seBoundaryCaching( true ), or change DEFAULT_BOUNDARY_CASHING to true
   * <p/>
   * When using a FragmentPagerAdapter or FragmentStatePagerAdapter,
   * additional changes in the adapter must be done.
   * The adapter must be prepared to create 2 extra items e.g.:
   * <p/>
   * The original adapter creates 4 items: [0,1,2,3]
   * The modified adapter will have to create 6 items [0,1,2,3,4,5]
   * with mapping realPosition=(position-1)%count
   * [0->3, 1->0, 2->1, 3->2, 4->3, 5->0]
   */
  public class LoopViewPager extends ViewPager {
      private OnPageChangeListener mOuterPageChangeListener;
      private LVLoopPagerAdapter mAdapter;
  
      private float mPreviousOffset = -1;
      private float mPreviousRealPosition = -1;
  
      public LoopViewPager(Context context) {
          super(context);
          init();
      }
  
      @Override
      public void setAdapter(PagerAdapter adapter) {
          mAdapter = (LVLoopPagerAdapter) adapter;
          super.setAdapter(mAdapter);
          setCurrentItem(0, false);
      }
  
      @Override
      public PagerAdapter getAdapter() {
          return mAdapter;
      }
  
      public int getRealCount() {
          return mAdapter != null ? mAdapter.getRealCount() : 0;
      }
  
      public int getCount() {
          return mAdapter != null ? mAdapter.getCount() : 0;
      }
  
      public void setLooping(boolean looping) {
          if (mAdapter != null && mAdapter.isLooping() != looping) {
              final int currentPosition = super.getCurrentItem();
              super.setAdapter(null);
              mAdapter.setLooping(looping);
              super.setAdapter(mAdapter);
              if (looping) {
                  super.setCurrentItem(mAdapter.toFakePosition(currentPosition), false);
              }
              mPreviousRealPosition = -1;
              mPreviousOffset = -1;
          }
      }
  
      public boolean isLooping() {
          return mAdapter != null && mAdapter.isLooping();
      }
  
      @Override
      public int getCurrentItem() {
          return mAdapter != null ? mAdapter.toRealPosition(super.getCurrentItem()) : super.getCurrentItem();
      }
  
      @Override
      public void setCurrentItem(int item) {
          setCurrentItem(item, false);
      }
  
      public void setCurrentItem(int realItem, boolean smoothScroll) {
          final int fakeItem = mAdapter.toFakePosition(realItem);
          final int currentFakeItem = super.getCurrentItem();
  //        LogUtil.d("yesong", "setCurrentItem", fakeItem, currentFakeItem);
          if (fakeItem != currentFakeItem) {
              super.setCurrentItem(fakeItem, smoothScroll);
          }
      }
  
      @Override
      public void setOnPageChangeListener(OnPageChangeListener listener) {
          mOuterPageChangeListener = listener;
      }
  
      private boolean isBoundaryPosition(int position) {
          return position == 0 || (position == getCount() - 1);
      }
  
      private void init() {
          super.setOnPageChangeListener(new OnPageChangeListener() {
              @Override
              public void onPageSelected(int position) {
  //                LogUtil.d("yesong", "onPageSelected", position);
                  if (mAdapter != null && mAdapter.shouldLooping()) {
                      int fakePosition = position;
                      int realPosition = mAdapter.toRealPosition(fakePosition);
                      if (mPreviousRealPosition != realPosition) {
                          mPreviousRealPosition = realPosition;
                          if (mOuterPageChangeListener != null) {
                              mOuterPageChangeListener.onPageSelected(realPosition);
                          }
                      }
                  } else {
                      mPreviousRealPosition = position;
                      if (mOuterPageChangeListener != null) {
                          mOuterPageChangeListener.onPageSelected(position);
                      }
                  }
              }
  
              @Override
              public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
  //                LogUtil.d("yesong", "onPageScrolled－offset", position, positionOffset, positionOffsetPixels);
  
                  if (mAdapter != null && mAdapter.shouldLooping()) {
                      final int fakePosition = position;
                      final int realPosition = mAdapter.toRealPosition(fakePosition);
                      if (positionOffset == 0 && mPreviousOffset == 0 && isBoundaryPosition(fakePosition)) {
  //                        LogUtil.d("yesong", "onPageScrolled", fakePosition, realPosition);
                          setCurrentItem(realPosition, false);
                      }
                      mPreviousOffset = positionOffset;
                      if (mOuterPageChangeListener != null) {
                          if (realPosition == mAdapter.getRealCount() - 1) {
                              if (positionOffset > 0.5) {
                                  mOuterPageChangeListener.onPageScrolled(0, 0, 0);
                              } else {
                                  mOuterPageChangeListener.onPageScrolled(realPosition, 0, 0);
                              }
                          } else {
                              mOuterPageChangeListener.onPageScrolled(realPosition, positionOffset, positionOffsetPixels);
                          }
                      }
                  } else {
                      if (mOuterPageChangeListener != null) {
                          mOuterPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
                      }
                  }
              }
  
              @Override
              public void onPageScrollStateChanged(int state) {
  //                LogUtil.d("yesong", "onPageScrollStateChanged", state);
                  if (mAdapter != null && mAdapter.shouldLooping()) {
                      int fakePosition = LoopViewPager.super.getCurrentItem();
                      int realPosition = mAdapter.toRealPosition(fakePosition);
  
                      if (state == ViewPager.SCROLL_STATE_IDLE && isBoundaryPosition(fakePosition)) {
  //                        LogUtil.d("yesong", "onPageScrollStateChanged", fakePosition, realPosition);
                          setCurrentItem(realPosition, false);
                      }
                  }
                  if (mOuterPageChangeListener != null) {
                      mOuterPageChangeListener.onPageScrollStateChanged(state);
                  }
              }
          });
      }
  
  }