/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package android.support.v17.leanback.widget;

import android.support.v4.util.CircularIntArray;
import android.util.Log;

import java.io.PrintWriter;

/**
 * A grid is representation of multiple row layout data structure and algorithm.
 * Grid is the base class for both staggered case or simple non-staggered case.
 * <p>
 * User calls Grid.createStaggeredMutipleRows() to create an staggered instance.
 * TODO add createNonStaggeredRows().
 * To use the Grid, user must implement a Provider to create or remove visible item.
 * Grid maintains a list of visible items.  Visible items are created when
 * user calls appendVisibleItems() or prependVisibleItems() with certain limitation
 * (e.g. a max edge that append up to).  Visible items are deleted when user calls
 * removeInvisibleItemsAtEnd() or removeInvisibleItemsAtFront().  Grid's algorithm
 * uses size of visible item returned from Provider.createItem() to decide which row
 * to add a new visible item and may cache the algorithm results.   User must call
 * invalidateItemsAfter() when it detects item size changed to ask Grid to remove cached
 * results.
 */
abstract class Grid {

    /**
     * A constant representing a default starting index, indicating that the
     * developer did not provide a start index.
     */
    public static final int START_DEFAULT = -1;

    /**
     * When user uses Grid,  he should provide count of items and
     * the method to create item and remove item.
     */
    public static interface Provider {

        /**
         * Return how many items (are in the adapter).
         */
        public abstract int getCount();

        /**
         * Create visible item and where the provider should measure it.
         * The call is always followed by addItem().
         * @param index     0-based index of the item in provider
         * @param append  True if new item is after last visible item, false if new item is
         *                before first visible item.
         * @param item    item[0] returns created item that will be passed in addItem() call.
         * @return length of the item.
         */
        public abstract int createItem(int index, boolean append, Object[] item);

        /**
         * add item to given row and given edge.  The call is always after createItem().
         * @param item      The object returned by createItem()
         * @param index     0-based index of the item in provider
         * @param length    The size of the object
         * @param rowIndex  Row index to put the item
         * @param edge      min_edge if not reversed or max_edge if reversed.
         */
        public abstract void addItem(Object item, int index, int length, int rowIndex, int edge);

        /**
         * Remove visible item at index.
         * @param index     0-based index of the item in provider
         */
        public abstract void removeItem(int index);

        /**
         * Get edge of an existing visible item. edge will be the min_edge
         * if not reversed or the max_edge if reversed.
         * @param index     0-based index of the item in provider
         */
        public abstract int getEdge(int index);

        /**
         * Get size of an existing visible item.
         * @param index     0-based index of the item in provider
         */
        public abstract int getSize(int index);
    }

    /**
     * Cached representation of an item in Grid.  May be subclassed.
     */
    public static class Location {
        /**
         * The index of the row for this Location.
         */
        public int row;

        public Location(int row) {
            this.row = row;
        }
    }

    protected Provider mProvider;
    protected boolean mReversedFlow;
    protected int mMargin;
    protected int mNumRows;
    protected int mFirstVisibleIndex = -1;
    protected int mLastVisibleIndex = -1;

    protected CircularIntArray[] mTmpItemPositionsInRows;

    // the first index that grid will layout
    protected int mStartIndex = START_DEFAULT;

    /**
     * Creates a multiple rows staggered grid.
     */
    public static Grid createStaggeredMultipleRows(int rows) {
        StaggeredGridDefault grid = new StaggeredGridDefault();
        grid.setNumRows(rows);
        return grid;
    }

    /**
     * Sets the margin between items in a row
     */
    public final void setMargin(int margin) {
        mMargin = margin;
    }

    /**
     * Sets if reversed flow (rtl)
     */
    public final void setReversedFlow(boolean reversedFlow) {
        mReversedFlow = reversedFlow;
    }

    /**
     * Returns true if reversed flow (rtl)
     */
    public boolean isReversedFlow() {
        return mReversedFlow;
    }

    /**
     * Sets the {@link Provider} for this grid.
     *
     * @param provider The provider for this grid.
     */
    public void setProvider(Provider provider) {
        mProvider = provider;
    }

    /**
     * Sets the first item index to create when there are no items.
     *
     * @param startIndex the index of the first item
     */
    public void setStart(int startIndex) {
        mStartIndex = startIndex;
    }

    /**
     * Returns the number of rows in the grid.
     */
    public int getNumRows() {
        return mNumRows;
    }

    /**
     * Sets number of rows to fill into. For views that represent a
     * horizontal list, this will be the rows of the view. For views that
     * represent a vertical list, this will be the columns.
     *
     * @param numRows numberOfRows
     */
    void setNumRows(int numRows) {
        if (numRows <= 0) {
            throw new IllegalArgumentException();
        }
        if (mNumRows == numRows) {
            return;
        }
        mNumRows = numRows;
        mTmpItemPositionsInRows = new CircularIntArray[mNumRows];
        for (int i = 0; i < mNumRows; i++) {
            mTmpItemPositionsInRows[i] = new CircularIntArray();
        }
    }

    /**
     * Returns index of first visible item in the staggered grid.  Returns negative value
     * if no visible item.
     */
    public final int getFirstVisibleIndex() {
        return mFirstVisibleIndex;
    }

    /**
     * Returns index of last visible item in the staggered grid.  Returns negative value
     * if no visible item.
     */
    public final int getLastVisibleIndex() {
        return mLastVisibleIndex;
    }

    /**
     * Reset visible indices and keep cache (if exists)
     */
    public void resetVisibleIndex() {
        mFirstVisibleIndex = mLastVisibleIndex = -1;
    }

    /**
     * Invalidate items after or equal to index. This will remove visible items
     * after that and invalidate cache of layout results after that.
     */
    public void invalidateItemsAfter(int index) {
        if (index < 0) {
            return;
        }
        if (mLastVisibleIndex < 0) {
            return;
        }
        while (mLastVisibleIndex >= index) {
            mProvider.removeItem(mLastVisibleIndex);
            mLastVisibleIndex--;
        }
        resetVisbileIndexIfEmpty();
        if (getFirstVisibleIndex() < 0) {
            setStart(index);
        }
    }

    /**
     * Gets the row index of item at given index.
     */
    public final int getRowIndex(int index) {
        return getLocation(index).row;
    }

    /**
     * Gets {@link Location} of item.  The return object is read only and temporarily.
     */
    public abstract Location getLocation(int index);

    /**
     * Finds the largest or smallest row min edge of visible items,
     * the row index is returned in indices[0], the item index is returned in indices[1].
     */
    public final int findRowMin(boolean findLarge, int[] indices) {
        return findRowMin(findLarge, mReversedFlow ? mLastVisibleIndex : mFirstVisibleIndex,
                indices);
    }

    /**
     * Finds the largest or smallest row min edge of visible items, starts searching from
     * indexLimit, the row index is returned in indices[0], the item index is returned in indices[1].
     */
    protected abstract int findRowMin(boolean findLarge, int indexLimit, int[] rowIndex);

    /**
     * Finds the largest or smallest row max edge of visible items, the row index is returned in
     * indices[0], the item index is returned in indices[1].
     */
    public final int findRowMax(boolean findLarge, int[] indices) {
        return findRowMax(findLarge, mReversedFlow ? mFirstVisibleIndex : mLastVisibleIndex,
                indices);
    }

    /**
     * Find largest or smallest row max edge of visible items, starts searching from indexLimit,
     * the row index is returned in indices[0], the item index is returned in indices[1].
     */
    protected abstract int findRowMax(boolean findLarge, int indexLimit, int[] indices);

    /**
     * Returns true if appending item has reached "toLimit"
     */
    protected final boolean checkAppendOverLimit(int toLimit) {
        if (mLastVisibleIndex < 0) {
            return false;
        }
        return mReversedFlow ? findRowMin(true, null) <= toLimit + mMargin :
                    findRowMax(false, null) >= toLimit - mMargin;
    }

    /**
     * Returns true if prepending item has reached "toLimit"
     */
    protected final boolean checkPrependOverLimit(int toLimit) {
        if (mLastVisibleIndex < 0) {
            return false;
        }
        return mReversedFlow ? findRowMax(false, null) >= toLimit + mMargin :
                    findRowMin(true, null) <= toLimit - mMargin;
    }

    /**
     * Return array of int array for all rows, each int array contains visible item positions
     * in pair on that row between startPos(included) and endPositions(included).
     * Returned value is read only, do not change it.
     * <p>
     * E.g. First row has 3,7,8, second row has 4,5,6.
     * getItemPositionsInRows(3, 8) returns { {3,3,7,8}, {4,6} }
     */
    public abstract CircularIntArray[] getItemPositionsInRows(int startPos, int endPos);

    /**
     * Return array of int array for all rows, each int array contains visible item positions
     * in pair on that row.
     * Returned value is read only, do not change it.
     * <p>
     * E.g. First row has 3,7,8, second row has 4,5,6  { {3,3,7,8}, {4,6} }
     */
    public final CircularIntArray[] getItemPositionsInRows() {
        return getItemPositionsInRows(getFirstVisibleIndex(), getLastVisibleIndex());
    }

    /**
     * Prepends items and stops after one column is filled.
     * (i.e. filled items from row 0 to row mNumRows - 1)
     * @return true if at least one item is filled.
     */
    public final boolean prependOneColumnVisibleItems() {
        return prependVisibleItems(mReversedFlow ? Integer.MIN_VALUE : Integer.MAX_VALUE, true);
    }

    /**
     * Prepends items until first item or reaches toLimit (min edge when not reversed or
     * max edge when reversed)
     */
    public final void prependVisibleItems(int toLimit) {
        prependVisibleItems(toLimit, false);
    }

    /**
     * Prepends items until first item or reaches toLimit (min edge when not reversed or
     * max edge when reversed).
     * @param oneColumnMode  true when fills one column and stops,  false
     * when checks if condition matches before filling first column.
     * @return true if at least one item is filled.
     */
    protected abstract boolean prependVisibleItems(int toLimit, boolean oneColumnMode);

    /**
     * Appends items and stops after one column is filled.
     * (i.e. filled items from row 0 to row mNumRows - 1)
     * @return true if at least one item is filled.
     */
    public boolean appendOneColumnVisibleItems() {
        return appendVisibleItems(mReversedFlow ? Integer.MAX_VALUE : Integer.MIN_VALUE, true);
    }

    /**
     * Append items until last item or reaches toLimit (max edge when not
     * reversed or min edge when reversed)
     */
    public final void appendVisibleItems(int toLimit) {
        appendVisibleItems(toLimit, false);
    }

    /**
     * Appends items until last or reaches toLimit (high edge when not
     * reversed or low edge when reversed).
     * @param oneColumnMode True when fills one column and stops,  false
     * when checks if condition matches before filling first column.
     * @return true if filled at least one item
     */
    protected abstract boolean appendVisibleItems(int toLimit, boolean oneColumnMode);

    /**
     * Removes invisible items from end until reaches item at aboveIndex or toLimit.
     */
    public void removeInvisibleItemsAtEnd(int aboveIndex, int toLimit) {
        while(mLastVisibleIndex >= mFirstVisibleIndex && mLastVisibleIndex > aboveIndex) {
            boolean offEnd = !mReversedFlow ? mProvider.getEdge(mLastVisibleIndex) >= toLimit
                    : mProvider.getEdge(mLastVisibleIndex) <= toLimit;
            if (offEnd) {
                mProvider.removeItem(mLastVisibleIndex);
                mLastVisibleIndex--;
            } else {
                break;
            }
        }
        resetVisbileIndexIfEmpty();
    }

    /**
     * Removes invisible items from front until reaches item at belowIndex or toLimit.
     */
    public void removeInvisibleItemsAtFront(int belowIndex, int toLimit) {
        while(mLastVisibleIndex >= mFirstVisibleIndex && mFirstVisibleIndex < belowIndex) {
            boolean offFront = !mReversedFlow ? mProvider.getEdge(mFirstVisibleIndex)
                    + mProvider.getSize(mFirstVisibleIndex) <= toLimit
                    : mProvider.getEdge(mFirstVisibleIndex)
                            - mProvider.getSize(mFirstVisibleIndex) >= toLimit;
            if (offFront) {
                mProvider.removeItem(mFirstVisibleIndex);
                mFirstVisibleIndex++;
            } else {
                break;
            }
        }
        resetVisbileIndexIfEmpty();
    }

    private void resetVisbileIndexIfEmpty() {
        if (mLastVisibleIndex < mFirstVisibleIndex) {
            resetVisibleIndex();
        }
    }

    public abstract void debugPrint(PrintWriter pw);
}
