/*
 * DragSortRecycler
 *
 * Added drag and drop functionality to your RecyclerView
 *
 *
 * Copyright 2014 Emile Belanger.
 *
 * 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 com.yoavst.quickapps.tools;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.support.annotation.Nullable;

import java.lang.reflect.Modifier;


public class DragSortRecycler extends RecyclerView.ItemDecoration implements RecyclerView.OnItemTouchListener {

    final String TAG = "DragSortRecycler";

    final boolean DEBUG = false;

    private int dragHandleWidth = 0;

    private int selectedDragItemPos = -1;

    private int fingerAnchorY;

    private int fingerY;

    private int fingerOffsetInViewY;

    private float autoScrollWindow = 0.1f;
    private float autoScrollSpeed  = 0.5f;

    private BitmapDrawable floatingItem;
    private Rect           floatingItemStatingBounds;
    private Rect           floatingItemBounds;


    private float floatingItemAlpha = 0.5f;
    private int   floatingItemBgColor = 0;

    private int viewHandleId = -1;


    OnItemMovedListener moveInterface;

    private boolean isDragging;
    @Nullable
    OnDragStateChangedListener dragStateChangedListener;



    public interface OnItemMovedListener
    {
        public void onItemMoved(int from, int to);
    }

    public interface OnDragStateChangedListener {
        public void onDragStart();
        public void onDragStop();
    }

    private void debugLog(String log)
    {
        if (DEBUG)
            Log.d(TAG, log);
    }

    public RecyclerView.OnScrollListener getScrollListener()
    {
        return scrollListener;
    }

    /*
     * Set the item move interface
     */
    public void setOnItemMovedListener(OnItemMovedListener swif)
    {
        moveInterface = swif;
    }

    public void setViewHandleId(int id)
    {
        viewHandleId = id;
    }

    public void setLeftDragArea(int w)
    {
        dragHandleWidth = w;
    }

    public void setFloatingAlpha(float a)
    {
        floatingItemAlpha = a;
    }

    public void setFloatingBgColor(int c)
    {
        floatingItemBgColor = c;
    }
    /*
     Set the window at top and bottom of list, must be between 0 and 0.5
     For example 0.1 uses the top and bottom 10% of the lists for scrolling
     */
    public void setAutoScrollWindow(float w)
    {
        autoScrollWindow = w;
    }

    /*
    Set the autoscroll speed, default is 0.5
     */
    public void setAutoScrollSpeed(float speed)
    {
        autoScrollSpeed = speed;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView rv, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, rv, state);

        debugLog("getItemOffsets");

        debugLog("View top = " + view.getTop());
        if (selectedDragItemPos != -1)
        {
            int itemPos =  rv.getChildPosition(view);
            debugLog("itemPos =" + itemPos);

            if(!canDragOver(itemPos)) {
                return;
            }

            //Movement of finger
            float totalMovement = fingerY-fingerAnchorY;

            if (itemPos == selectedDragItemPos)
            {
                view.setVisibility(View.INVISIBLE);
            }
            else
            {
                //Make view visible incase invisible
                view.setVisibility(View.VISIBLE);

                //Find middle of the floatingItem
                float floatMiddleY = floatingItemBounds.top + floatingItemBounds.height()/2;

                //Moving down the list
                //These will auto-animate if the device continually sends touch motion events
                // if (totalMovment>0)
                {
                    if ((itemPos > selectedDragItemPos) && (view.getTop() < floatMiddleY))
                    {
                        float amountUp = (floatMiddleY - view.getTop()) / (float)view.getHeight();
                        //  amountUp *= 0.5f;
                        if (amountUp > 1)
                            amountUp = 1;

                        outRect.top = -(int)(floatingItemBounds.height()*amountUp);
                        outRect.bottom = (int)(floatingItemBounds.height()*amountUp);
                    }

                }//Moving up the list
                // else if (totalMovment < 0)
                {
                    if((itemPos < selectedDragItemPos) && (view.getBottom() > floatMiddleY))
                    {
                        float amountDown = ((float)view.getBottom() - floatMiddleY) / (float)view.getHeight();
                        //  amountDown *= 0.5f;
                        if (amountDown > 1)
                            amountDown = 1;

                        outRect.top = (int)(floatingItemBounds.height()*amountDown);
                        outRect.bottom = -(int)(floatingItemBounds.height()*amountDown);
                    }
                }
            }
        }
        else
        {
            outRect.top = 0;
            outRect.bottom = 0;
            //Make view visible incase invisible
            view.setVisibility(View.VISIBLE);
        }
    }

    /**
     * Find the new position by scanning through the items on
     * screen and finding the positional relationship.
     * This *seems* to work, another method would be to use
     * getItemOffsets, but I think that could miss items?..
     */
    private int getNewPostion(RecyclerView rv)
    {
        int itemsOnScreen = rv.getLayoutManager().getChildCount();

        float floatMiddleY = floatingItemBounds.top + floatingItemBounds.height()/2;

        int above=0;
        int below = Integer.MAX_VALUE;
        for (int n=0;n < itemsOnScreen;n++) //Scan though items on screen, however they may not
        {                                   // be in order!

            View view = rv.getLayoutManager().getChildAt(n);

            if (view.getVisibility() != View.VISIBLE)
                continue;

            int itemPos = rv.getChildPosition(view);

            if (itemPos == selectedDragItemPos) //Don't check against itself!
                continue;

            float viewMiddleY = view.getTop() + view.getHeight()/2;
            if (floatMiddleY > viewMiddleY) //Is above this item
            {
                if (itemPos > above)
                    above = itemPos;
            }
            else if (floatMiddleY <= viewMiddleY) //Is below this item
            {
                if (itemPos < below)
                    below = itemPos;
            }
        }
        debugLog("above = " + above + " below = " + below);

        if (below != Integer.MAX_VALUE) {
            if (below < selectedDragItemPos) //Need to count itself
                below++;
            return below - 1;
        }
        else
        {
            if (above < selectedDragItemPos)
                above++;

            return above;
        }
    }


    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        debugLog("onInterceptTouchEvent");

        //if (e.getAction() == MotionEvent.ACTION_DOWN)
        {
            View itemView = rv.findChildViewUnder(e.getX(), e.getY());

            if (itemView==null)
                return false;

            boolean dragging = false;

            if ((dragHandleWidth > 0 ) && (e.getX() < dragHandleWidth))
            {
                dragging = true;
            }
            else if (viewHandleId != -1)
            {
                //Find the handle in the list item
                View handleView = itemView.findViewById(viewHandleId);

                if (handleView == null)
                {
                    Log.e(TAG, "The view ID " + viewHandleId + " was not found in the RecycleView item");
                    return false;
                }

                //View should be visible to drag
                if(handleView.getVisibility()!=View.VISIBLE) {
                    return false;
                }

                //We need to find the relative position of the handle to the parent view
                //Then we can work out if the touch is within the handle
                int[] parentItemPos = new int[2];
                itemView.getLocationInWindow(parentItemPos);

                int[] handlePos = new int[2];
                handleView.getLocationInWindow(handlePos);

                int xRel = handlePos[0] - parentItemPos[0];
                int yRel = handlePos[1] - parentItemPos[1];

                Rect touchBounds = new Rect(itemView.getLeft() + xRel, itemView.getTop() + yRel,
                        itemView.getLeft() + xRel + handleView.getWidth(),
                        itemView.getTop() + yRel  + handleView.getHeight()
                );

                if (touchBounds.contains((int)e.getX(), (int)e.getY()))
                    dragging = true;

                debugLog("parentItemPos = " + parentItemPos[0] + " " + parentItemPos[1]);
                debugLog("handlePos = " + handlePos[0] + " " + handlePos[1]);
            }


            if (dragging)
            {
                debugLog("Started Drag");

                setIsDragging(true);

                floatingItem = createFloatingBitmap(itemView);

                fingerAnchorY = (int)e.getY();
                fingerOffsetInViewY = fingerAnchorY - itemView.getTop();
                fingerY = fingerAnchorY;

                selectedDragItemPos = rv.getChildPosition(itemView);
                debugLog("selectedDragItemPos = " + selectedDragItemPos);

                return true;
            }
        }
        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
        debugLog("onTouchEvent");

        if ((e.getAction() == MotionEvent.ACTION_UP) ||
                (e.getAction() == MotionEvent.ACTION_CANCEL))
        {
            if ((e.getAction() == MotionEvent.ACTION_UP) && selectedDragItemPos != -1)
            {
                int newPos = getNewPostion(rv);
                if (moveInterface != null)
                    moveInterface.onItemMoved(selectedDragItemPos, newPos);
            }

            setIsDragging(false);
            selectedDragItemPos = -1;
            floatingItem = null;
            rv.invalidateItemDecorations();
            return;
        }


        fingerY = (int)e.getY();

        if (floatingItem!=null)
        {
            floatingItemBounds.top = fingerY - fingerOffsetInViewY;

            if (floatingItemBounds.top < -floatingItemStatingBounds.height()/2) //Allow half the view out the top
                floatingItemBounds.top = -floatingItemStatingBounds.height()/2;

            floatingItemBounds.bottom = floatingItemBounds.top + floatingItemStatingBounds.height();

            floatingItem.setBounds(floatingItemBounds);
        }

        //Do auto scrolling at end of list
        float scrollAmount=0;
        if (fingerY > (rv.getHeight() * (1-autoScrollWindow)))
        {
            scrollAmount = (fingerY - (rv.getHeight() * (1-autoScrollWindow)));
        }
        else if (fingerY < (rv.getHeight() * autoScrollWindow))
        {
            scrollAmount = (fingerY - (rv.getHeight() * autoScrollWindow));
        }
        debugLog("Scroll: " + scrollAmount);

        scrollAmount *= autoScrollSpeed;
        rv.scrollBy(0, (int)scrollAmount);

        rv.invalidateItemDecorations();// Redraw
    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
        //FIXME
    }

    private void setIsDragging(final boolean dragging) {
        if(dragging != isDragging) {
            isDragging = dragging;
            if(dragStateChangedListener != null) {
                if (isDragging) {
                    dragStateChangedListener.onDragStart();
                } else {
                    dragStateChangedListener.onDragStop();
                }
            }
        }
    }

    public void setOnDragStateChangedListener(final OnDragStateChangedListener dragStateChangedListener) {
        this.dragStateChangedListener = dragStateChangedListener;
    }


    Paint bgColor = new Paint();
    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (floatingItem != null) {
            floatingItem.setAlpha((int)(255 * floatingItemAlpha));
            bgColor.setColor(floatingItemBgColor);
            c.drawRect(floatingItemBounds,bgColor);
            floatingItem.draw(c);
        }
    }

    RecyclerView.OnScrollListener scrollListener = new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            debugLog("Scrolled: " + dx + " " + dy);
            fingerAnchorY -= dy;
        }
    };

    /**
     *
     *
     * @param position
     * @return True if we can drag the item over this position, False if not.
     */
    protected boolean canDragOver(int position) {
        return true;
    }


    private BitmapDrawable createFloatingBitmap(View v)
    {
        floatingItemStatingBounds = new Rect(v.getLeft(), v.getTop(),v.getRight(), v.getBottom());
        floatingItemBounds = new Rect(floatingItemStatingBounds);

        Bitmap bitmap = Bitmap.createBitmap(floatingItemStatingBounds.width(),
                floatingItemStatingBounds.height(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        v.draw(canvas);

        BitmapDrawable retDrawable = new BitmapDrawable(v.getResources(), bitmap);
        retDrawable.setBounds(floatingItemBounds);

        return retDrawable;
    }
}

// else if (totalMovment < 0)
/*
 * DragSortRecycler
 *
 * Added drag and drop functionality to your RecyclerView
 *
 *
 * Copyright 2014 Emile Belanger.
 *
 * 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 com.yoavst.quickapps.tools;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.support.annotation.Nullable;

import java.lang.reflect.Modifier;


public class DragSortRecycler extends RecyclerView.ItemDecoration implements RecyclerView.OnItemTouchListener {

    final String TAG = "DragSortRecycler";

    final boolean DEBUG = false;

    private int dragHandleWidth = 0;

    private int selectedDragItemPos = -1;

    private int fingerAnchorY;

    private int fingerY;

    private int fingerOffsetInViewY;

    private float autoScrollWindow = 0.1f;
    private float autoScrollSpeed  = 0.5f;

    private BitmapDrawable floatingItem;
    private Rect           floatingItemStatingBounds;
    private Rect           floatingItemBounds;


    private float floatingItemAlpha = 0.5f;
    private int   floatingItemBgColor = 0;

    private int viewHandleId = -1;


    OnItemMovedListener moveInterface;

    private boolean isDragging;
    @Nullable
    OnDragStateChangedListener dragStateChangedListener;



    public interface OnItemMovedListener
    {
        public void onItemMoved(int from, int to);
    }

    public interface OnDragStateChangedListener {
        public void onDragStart();
        public void onDragStop();
    }

    private void debugLog(String log)
    {
        if (DEBUG)
            Log.d(TAG, log);
    }

    public RecyclerView.OnScrollListener getScrollListener()
    {
        return scrollListener;
    }

    /*
     * Set the item move interface
     */
    public void setOnItemMovedListener(OnItemMovedListener swif)
    {
        moveInterface = swif;
    }

    public void setViewHandleId(int id)
    {
        viewHandleId = id;
    }

    public void setLeftDragArea(int w)
    {
        dragHandleWidth = w;
    }

    public void setFloatingAlpha(float a)
    {
        floatingItemAlpha = a;
    }

    public void setFloatingBgColor(int c)
    {
        floatingItemBgColor = c;
    }
    /*
     Set the window at top and bottom of list, must be between 0 and 0.5
     For example 0.1 uses the top and bottom 10% of the lists for scrolling
     */
    public void setAutoScrollWindow(float w)
    {
        autoScrollWindow = w;
    }

    /*
    Set the autoscroll speed, default is 0.5
     */
    public void setAutoScrollSpeed(float speed)
    {
        autoScrollSpeed = speed;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView rv, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, rv, state);

        debugLog("getItemOffsets");

        debugLog("View top = " + view.getTop());
        if (selectedDragItemPos != -1)
        {
            int itemPos =  rv.getChildPosition(view);
            debugLog("itemPos =" + itemPos);

            if(!canDragOver(itemPos)) {
                return;
            }

            //Movement of finger
            float totalMovement = fingerY-fingerAnchorY;

            if (itemPos == selectedDragItemPos)
            {
                view.setVisibility(View.INVISIBLE);
            }
            else
            {
                //Make view visible incase invisible
                view.setVisibility(View.VISIBLE);

                //Find middle of the floatingItem
                float floatMiddleY = floatingItemBounds.top + floatingItemBounds.height()/2;

                //Moving down the list
                //These will auto-animate if the device continually sends touch motion events
                // if (totalMovment>0)
                {
                    if ((itemPos > selectedDragItemPos) && (view.getTop() < floatMiddleY))
                    {
                        float amountUp = (floatMiddleY - view.getTop()) / (float)view.getHeight();
                        //  amountUp *= 0.5f;
                        if (amountUp > 1)
                            amountUp = 1;

                        outRect.top = -(int)(floatingItemBounds.height()*amountUp);
                        outRect.bottom = (int)(floatingItemBounds.height()*amountUp);
                    }

                }//Moving up the list
                // else if<SUF>
                {
                    if((itemPos < selectedDragItemPos) && (view.getBottom() > floatMiddleY))
                    {
                        float amountDown = ((float)view.getBottom() - floatMiddleY) / (float)view.getHeight();
                        //  amountDown *= 0.5f;
                        if (amountDown > 1)
                            amountDown = 1;

                        outRect.top = (int)(floatingItemBounds.height()*amountDown);
                        outRect.bottom = -(int)(floatingItemBounds.height()*amountDown);
                    }
                }
            }
        }
        else
        {
            outRect.top = 0;
            outRect.bottom = 0;
            //Make view visible incase invisible
            view.setVisibility(View.VISIBLE);
        }
    }

    /**
     * Find the new position by scanning through the items on
     * screen and finding the positional relationship.
     * This *seems* to work, another method would be to use
     * getItemOffsets, but I think that could miss items?..
     */
    private int getNewPostion(RecyclerView rv)
    {
        int itemsOnScreen = rv.getLayoutManager().getChildCount();

        float floatMiddleY = floatingItemBounds.top + floatingItemBounds.height()/2;

        int above=0;
        int below = Integer.MAX_VALUE;
        for (int n=0;n < itemsOnScreen;n++) //Scan though items on screen, however they may not
        {                                   // be in order!

            View view = rv.getLayoutManager().getChildAt(n);

            if (view.getVisibility() != View.VISIBLE)
                continue;

            int itemPos = rv.getChildPosition(view);

            if (itemPos == selectedDragItemPos) //Don't check against itself!
                continue;

            float viewMiddleY = view.getTop() + view.getHeight()/2;
            if (floatMiddleY > viewMiddleY) //Is above this item
            {
                if (itemPos > above)
                    above = itemPos;
            }
            else if (floatMiddleY <= viewMiddleY) //Is below this item
            {
                if (itemPos < below)
                    below = itemPos;
            }
        }
        debugLog("above = " + above + " below = " + below);

        if (below != Integer.MAX_VALUE) {
            if (below < selectedDragItemPos) //Need to count itself
                below++;
            return below - 1;
        }
        else
        {
            if (above < selectedDragItemPos)
                above++;

            return above;
        }
    }


    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        debugLog("onInterceptTouchEvent");

        //if (e.getAction() == MotionEvent.ACTION_DOWN)
        {
            View itemView = rv.findChildViewUnder(e.getX(), e.getY());

            if (itemView==null)
                return false;

            boolean dragging = false;

            if ((dragHandleWidth > 0 ) && (e.getX() < dragHandleWidth))
            {
                dragging = true;
            }
            else if (viewHandleId != -1)
            {
                //Find the handle in the list item
                View handleView = itemView.findViewById(viewHandleId);

                if (handleView == null)
                {
                    Log.e(TAG, "The view ID " + viewHandleId + " was not found in the RecycleView item");
                    return false;
                }

                //View should be visible to drag
                if(handleView.getVisibility()!=View.VISIBLE) {
                    return false;
                }

                //We need to find the relative position of the handle to the parent view
                //Then we can work out if the touch is within the handle
                int[] parentItemPos = new int[2];
                itemView.getLocationInWindow(parentItemPos);

                int[] handlePos = new int[2];
                handleView.getLocationInWindow(handlePos);

                int xRel = handlePos[0] - parentItemPos[0];
                int yRel = handlePos[1] - parentItemPos[1];

                Rect touchBounds = new Rect(itemView.getLeft() + xRel, itemView.getTop() + yRel,
                        itemView.getLeft() + xRel + handleView.getWidth(),
                        itemView.getTop() + yRel  + handleView.getHeight()
                );

                if (touchBounds.contains((int)e.getX(), (int)e.getY()))
                    dragging = true;

                debugLog("parentItemPos = " + parentItemPos[0] + " " + parentItemPos[1]);
                debugLog("handlePos = " + handlePos[0] + " " + handlePos[1]);
            }


            if (dragging)
            {
                debugLog("Started Drag");

                setIsDragging(true);

                floatingItem = createFloatingBitmap(itemView);

                fingerAnchorY = (int)e.getY();
                fingerOffsetInViewY = fingerAnchorY - itemView.getTop();
                fingerY = fingerAnchorY;

                selectedDragItemPos = rv.getChildPosition(itemView);
                debugLog("selectedDragItemPos = " + selectedDragItemPos);

                return true;
            }
        }
        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
        debugLog("onTouchEvent");

        if ((e.getAction() == MotionEvent.ACTION_UP) ||
                (e.getAction() == MotionEvent.ACTION_CANCEL))
        {
            if ((e.getAction() == MotionEvent.ACTION_UP) && selectedDragItemPos != -1)
            {
                int newPos = getNewPostion(rv);
                if (moveInterface != null)
                    moveInterface.onItemMoved(selectedDragItemPos, newPos);
            }

            setIsDragging(false);
            selectedDragItemPos = -1;
            floatingItem = null;
            rv.invalidateItemDecorations();
            return;
        }


        fingerY = (int)e.getY();

        if (floatingItem!=null)
        {
            floatingItemBounds.top = fingerY - fingerOffsetInViewY;

            if (floatingItemBounds.top < -floatingItemStatingBounds.height()/2) //Allow half the view out the top
                floatingItemBounds.top = -floatingItemStatingBounds.height()/2;

            floatingItemBounds.bottom = floatingItemBounds.top + floatingItemStatingBounds.height();

            floatingItem.setBounds(floatingItemBounds);
        }

        //Do auto scrolling at end of list
        float scrollAmount=0;
        if (fingerY > (rv.getHeight() * (1-autoScrollWindow)))
        {
            scrollAmount = (fingerY - (rv.getHeight() * (1-autoScrollWindow)));
        }
        else if (fingerY < (rv.getHeight() * autoScrollWindow))
        {
            scrollAmount = (fingerY - (rv.getHeight() * autoScrollWindow));
        }
        debugLog("Scroll: " + scrollAmount);

        scrollAmount *= autoScrollSpeed;
        rv.scrollBy(0, (int)scrollAmount);

        rv.invalidateItemDecorations();// Redraw
    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
        //FIXME
    }

    private void setIsDragging(final boolean dragging) {
        if(dragging != isDragging) {
            isDragging = dragging;
            if(dragStateChangedListener != null) {
                if (isDragging) {
                    dragStateChangedListener.onDragStart();
                } else {
                    dragStateChangedListener.onDragStop();
                }
            }
        }
    }

    public void setOnDragStateChangedListener(final OnDragStateChangedListener dragStateChangedListener) {
        this.dragStateChangedListener = dragStateChangedListener;
    }


    Paint bgColor = new Paint();
    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (floatingItem != null) {
            floatingItem.setAlpha((int)(255 * floatingItemAlpha));
            bgColor.setColor(floatingItemBgColor);
            c.drawRect(floatingItemBounds,bgColor);
            floatingItem.draw(c);
        }
    }

    RecyclerView.OnScrollListener scrollListener = new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            debugLog("Scrolled: " + dx + " " + dy);
            fingerAnchorY -= dy;
        }
    };

    /**
     *
     *
     * @param position
     * @return True if we can drag the item over this position, False if not.
     */
    protected boolean canDragOver(int position) {
        return true;
    }


    private BitmapDrawable createFloatingBitmap(View v)
    {
        floatingItemStatingBounds = new Rect(v.getLeft(), v.getTop(),v.getRight(), v.getBottom());
        floatingItemBounds = new Rect(floatingItemStatingBounds);

        Bitmap bitmap = Bitmap.createBitmap(floatingItemStatingBounds.width(),
                floatingItemStatingBounds.height(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        v.draw(canvas);

        BitmapDrawable retDrawable = new BitmapDrawable(v.getResources(), bitmap);
        retDrawable.setBounds(floatingItemBounds);

        return retDrawable;
    }
}
