// Path: video-list-player/src/main/java/com/waynell/videolist/visibility/items/ListItem.java
// public interface ListItem {
// 
//     /**
//      * When view visibility become bigger than "current active" view visibility then the new view becomes active.
//      * This method is called
//      */
//     void setActive(View newActiveView, int newActiveViewPosition);
// 
//     /**
//      * There might be a case when not only new view becomes active, but also when no view is active.
//      * When view should stop being active this method is called
//      */
//     void deactivate(View currentView, int position);
// }
// 
// Path: video-list-player/src/main/java/com/waynell/videolist/visibility/items/ListItemData.java
// public class ListItemData {
// 
//     private Integer mIndexInAdapter;
//     private View mView;
//     private ListItem mListItem;
// 
//     private boolean mIsVisibleItemChanged;
// 
//     public int getIndex() {
//         return mIndexInAdapter;
//     }
// 
//     public View getView() {
//         return mView;
//     }
// 
//     public ListItem getListItem() {
//         return mListItem;
//     }
// 
//     public ListItemData fillWithData(int indexInAdapter, View view, ListItem item) {
//         mIndexInAdapter = indexInAdapter;
//         mView = view;
//         mListItem = item;
//         return this;
//     }
// 
//     public boolean isIndexValid() {
//         return mIndexInAdapter != null;
//     }
// 
//     public boolean isAvailable() {
//         return mIndexInAdapter != null && mView != null && mListItem != null;
//     }
// 
//     public void setVisibleItemChanged(boolean isDataChanged) {
//         mIsVisibleItemChanged = isDataChanged;
//     }
// 
//     public boolean isVisibleItemChanged() {
//         return mIsVisibleItemChanged;
//     }
// 
//     @Override
//     public String toString() {
//         return "ListItemData{" +
//                 "mIndexInAdapter=" + mIndexInAdapter +
//                 ", mView=" + mView +
//                 ", mListItem=" + mListItem +
//                 ", mIsVisibleItemChanged=" + mIsVisibleItemChanged +
//                 '}';
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         ListItemData that = (ListItemData) o;
// 
//         return (mIndexInAdapter != null ? mIndexInAdapter.equals(that.mIndexInAdapter) : that.mIndexInAdapter == null)
//                 && (mView != null ? mView.equals(that.mView) : that.mView == null);
// 
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = mIndexInAdapter != null ? mIndexInAdapter.hashCode() : 0;
//         result = 31 * result + (mView != null ? mView.hashCode() : 0);
//         return result;
//     }
// }
// 
// Path: video-list-player/src/main/java/com/waynell/videolist/visibility/scroll/ItemsPositionGetter.java
// public interface ItemsPositionGetter {
//     View getChildAt(int position);
// 
//     int indexOfChild(View view);
// 
//     int getChildCount();
// 
//     int getLastVisiblePosition();
// 
//     int getFirstVisiblePosition();
// }
// 
// Path: video-list-player/src/main/java/com/waynell/videolist/visibility/scroll/ItemsProvider.java
// public interface ItemsProvider {
// 
//     ListItem getListItem(int position);
// 
//     int listItemSize();
// 
// }


import android.util.Log;
import android.view.View;
import com.waynell.videolist.visibility.items.ListItem;
import com.waynell.videolist.visibility.items.ListItemData;
import com.waynell.videolist.visibility.scroll.ItemsPositionGetter;
import com.waynell.videolist.visibility.scroll.ItemsProvider;
package com.waynell.videolist.visibility.calculator;



/**
 * A utility that tracks current {@link ListItem} visibility.
 * Current ListItem is an item defined by calling {@link #setCurrentItem(ListItemData)}.
 * Or it might be mock current item created in method {@link #getMockCurrentItem}
 *
 * The logic is following: when current view is going out of screen (up or down) by {@link #INACTIVE_LIST_ITEM_VISIBILITY_PERCENTS} or more then neighbour item become "active" by calling {@link Callback#activateNewCurrentItem}
 * "Going out of screen" is calculated when {@link #onStateTouchScroll} is called from super class {@link BaseItemsVisibilityCalculator}
 *
 * Method {@link ListItemsVisibilityCalculator#onScrollStateIdle} should be called only when scroll state become idle. // TODO: test it
 * When it's called we look for new current item that eventually will be set as "active" by calling {@link #setCurrentItem(ListItemData)}
 * Regarding the {@link #mScrollDirection} new current item is calculated from top to bottom (if DOWN) or from bottom to top (if UP).
 * The first(or last) visible item is set to current. It's visibility percentage is calculated. Then we are going though all visible items and find the one that is the most visible.
 *
 * Method {@link #onStateLost} is calling {@link Callback#deactivateCurrentItem}
 *
 * @author Wayne
 */
public class SingleListViewItemActiveCalculator extends BaseItemsVisibilityCalculator {

    private static final String TAG = "ListViewItemActiveCal";
    private static final boolean SHOW_LOGS = false;

    private static final int INACTIVE_LIST_ITEM_VISIBILITY_PERCENTS = 70;

    private final Callback<ListItem> mCallback;
    private final ItemsProvider mItemsProvider;

    /**
     * The data of this member will be changing all the time
     */
    private final ListItemData mCurrentItem = new ListItemData();

    private final ListItemData mPreActiveItem = new ListItemData();

// Path: video-list-player/src/main/java/com/waynell/videolist/visibility/items/ListItem.java
// public interface ListItem {
// 
//     /**
//      * When view visibility become bigger than "current active" view visibility then the new view becomes active.
//      * This method is called
//      */
//     void setActive(View newActiveView, int newActiveViewPosition);
// 
//     /**
//      * There might be a case when not only new view becomes active, but also when no view is active.
//      * When view should stop being active this method is called
//      */
//     void deactivate(View currentView, int position);
// }
// 
// Path: video-list-player/src/main/java/com/waynell/videolist/visibility/items/ListItemData.java
// public class ListItemData {
// 
//     private Integer mIndexInAdapter;
//     private View mView;
//     private ListItem mListItem;
// 
//     private boolean mIsVisibleItemChanged;
// 
//     public int getIndex() {
//         return mIndexInAdapter;
//     }
// 
//     public View getView() {
//         return mView;
//     }
// 
//     public ListItem getListItem() {
//         return mListItem;
//     }
// 
//     public ListItemData fillWithData(int indexInAdapter, View view, ListItem item) {
//         mIndexInAdapter = indexInAdapter;
//         mView = view;
//         mListItem = item;
//         return this;
//     }
// 
//     public boolean isIndexValid() {
//         return mIndexInAdapter != null;
//     }
// 
//     public boolean isAvailable() {
//         return mIndexInAdapter != null && mView != null && mListItem != null;
//     }
// 
//     public void setVisibleItemChanged(boolean isDataChanged) {
//         mIsVisibleItemChanged = isDataChanged;
//     }
// 
//     public boolean isVisibleItemChanged() {
//         return mIsVisibleItemChanged;
//     }
// 
//     @Override
//     public String toString() {
//         return "ListItemData{" +
//                 "mIndexInAdapter=" + mIndexInAdapter +
//                 ", mView=" + mView +
//                 ", mListItem=" + mListItem +
//                 ", mIsVisibleItemChanged=" + mIsVisibleItemChanged +
//                 '}';
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         ListItemData that = (ListItemData) o;
// 
//         return (mIndexInAdapter != null ? mIndexInAdapter.equals(that.mIndexInAdapter) : that.mIndexInAdapter == null)
//                 && (mView != null ? mView.equals(that.mView) : that.mView == null);
// 
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = mIndexInAdapter != null ? mIndexInAdapter.hashCode() : 0;
//         result = 31 * result + (mView != null ? mView.hashCode() : 0);
//         return result;
//     }
// }
// 
// Path: video-list-player/src/main/java/com/waynell/videolist/visibility/scroll/ItemsPositionGetter.java
// public interface ItemsPositionGetter {
//     View getChildAt(int position);
// 
//     int indexOfChild(View view);
// 
//     int getChildCount();
// 
//     int getLastVisiblePosition();
// 
//     int getFirstVisiblePosition();
// }
// 
// Path: video-list-player/src/main/java/com/waynell/videolist/visibility/scroll/ItemsProvider.java
// public interface ItemsProvider {
// 
//     ListItem getListItem(int position);
// 
//     int listItemSize();
// 
// }


// Path: video-list-player/src/main/java/com/waynell/videolist/visibility/calculator/SingleListViewItemActiveCalculator.java
import android.util.Log;
import android.view.View;
import com.waynell.videolist.visibility.items.ListItem;
import com.waynell.videolist.visibility.items.ListItemData;
import com.waynell.videolist.visibility.scroll.ItemsPositionGetter;
import com.waynell.videolist.visibility.scroll.ItemsProvider;

package com.waynell.videolist.visibility.calculator;



/**
 * A utility that tracks current {@link ListItem} visibility.
 * Current ListItem is an item defined by calling {@link #setCurrentItem(ListItemData)}.
 * Or it might be mock current item created in method {@link #getMockCurrentItem}
 *
 * The logic is following: when current view is going out of screen (up or down) by {@link #INACTIVE_LIST_ITEM_VISIBILITY_PERCENTS} or more then neighbour item become "active" by calling {@link Callback#activateNewCurrentItem}
 * "Going out of screen" is calculated when {@link #onStateTouchScroll} is called from super class {@link BaseItemsVisibilityCalculator}
 *
 * Method {@link ListItemsVisibilityCalculator#onScrollStateIdle} should be called only when scroll state become idle. // TODO: test it
 * When it's called we look for new current item that eventually will be set as "active" by calling {@link #setCurrentItem(ListItemData)}
 * Regarding the {@link #mScrollDirection} new current item is calculated from top to bottom (if DOWN) or from bottom to top (if UP).
 * The first(or last) visible item is set to current. It's visibility percentage is calculated. Then we are going though all visible items and find the one that is the most visible.
 *
 * Method {@link #onStateLost} is calling {@link Callback#deactivateCurrentItem}
 *
 * @author Wayne
 */
public class SingleListViewItemActiveCalculator extends BaseItemsVisibilityCalculator {

    private static final String TAG = "ListViewItemActiveCal";
    private static final boolean SHOW_LOGS = false;

    private static final int INACTIVE_LIST_ITEM_VISIBILITY_PERCENTS = 70;

    private final Callback<ListItem> mCallback;
    private final ItemsProvider mItemsProvider;

    /**
     * The data of this member will be changing all the time
     */
    private final ListItemData mCurrentItem = new ListItemData();

    private final ListItemData mPreActiveItem = new ListItemData();

    public SingleListViewItemActiveCalculator(ItemsProvider itemsProvider, ItemsPositionGetter itemsPositionGetter) {