/*
 * Copyright (C) 2013 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 com.android.camera.ui;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.widget.LinearLayout;
import android.widget.ScrollView;

import com.android.camera.util.CameraUtil;
import com.android.camera.util.Gusterpolator;
import com.android.camera.widget.AnimationEffects;
import com.android.camera2.R;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * ModeListView class displays all camera modes and settings in the form
 * of a list. A swipe to the right will bring up this list. Then tapping on
 * any of the items in the list will take the user to that corresponding mode
 * with an animation. To dismiss this list, simply swipe left or select a mode.
 */
public class ModeListView extends ScrollView {

    private static final String TAG = "ModeListView";

    // Animation Durations
    private static final int DEFAULT_DURATION_MS = 200;
    private static final int FLY_IN_DURATION_MS = 850;
    private static final int HOLD_DURATION_MS = 0;
    private static final int FLY_OUT_DURATION_MS = 850;
    private static final int START_DELAY_MS = 100;
    private static final int TOTAL_DURATION_MS = FLY_IN_DURATION_MS + HOLD_DURATION_MS
            + FLY_OUT_DURATION_MS;

    private static final float ROWS_TO_SHOW_IN_LANDSCAPE = 4.5f;
    private static final int NO_ITEM_SELECTED = -1;

    // Scrolling states
    private static final int IDLE = 0;
    private static final int FULLY_SHOWN = 1;
    private static final int ACCORDION_ANIMATION = 2;
    private static final int SCROLLING = 3;
    private static final int MODE_SELECTED = 4;

    // Scrolling delay between non-focused item and focused item
    private static final int DELAY_MS = 25;
    // If the fling velocity exceeds this threshold, snap to full screen at a constant
    // speed. Unit: pixel/ms.
    private static final float VELOCITY_THRESHOLD = 2f;

    private final GestureDetector mGestureDetector;
    private final int mIconBlockWidth;

    private int mListBackgroundColor;
    private LinearLayout mListView;
    private int mState = IDLE;
    private int mTotalModes;
    private ModeSelectorItem[] mModeSelectorItems;
    private AnimatorSet mAnimatorSet;
    private int mFocusItem = NO_ITEM_SELECTED;
    private AnimationEffects mCurrentEffect;
    private ModeListOpenListener mModeListOpenListener;

    // Width and height of this view. They get updated in onLayout()
    // Unit for width and height are pixels.
    private int mWidth;
    private int mHeight;
    private float mScrollTrendX = 0f;
    private float mScrollTrendY = 0f;
    private ModeSwitchListener mModeSwitchListener = null;
    private ArrayList<Integer> mSupportedModes;
    private final LinkedList<TimeBasedPosition> mPositionHistory
            = new LinkedList<TimeBasedPosition>();
    private long mCurrentTime;
    private float mVelocityX; // Unit: pixel/ms.
    private final Animator.AnimatorListener mModeListAnimatorListener =
            new Animator.AnimatorListener() {

        @Override
        public void onAnimationStart(Animator animation) {
            setVisibility(VISIBLE);
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            mAnimatorSet = null;
            if (mState == ACCORDION_ANIMATION || mState == IDLE) {
                resetModeSelectors();
                setVisibility(INVISIBLE);
                mState = IDLE;
            }
        }

        @Override
        public void onAnimationCancel(Animator animation) {
        }

        @Override
        public void onAnimationRepeat(Animator animation) {

        }
    };

    public interface ModeSwitchListener {
        public void onModeSelected(int modeIndex);
    }

    public interface ModeListOpenListener {
        public void onOpenFullScreen();
    }

    /**
     * This class aims to help store time and position in pairs.
     */
    private static class TimeBasedPosition {
        private final float mPosition;
        private final long mTimeStamp;
        public TimeBasedPosition(float position, long time) {
            mPosition = position;
            mTimeStamp = time;
        }

        public float getPosition() {
            return mPosition;
        }

        public long getTimeStamp() {
            return mTimeStamp;
        }
    }

    /**
     * This is a highly customized interpolator. The purpose of having this subclass
     * is to encapsulate intricate animation timing, so that the actual animation
     * implementation can be re-used with other interpolators to achieve different
     * animation effects.
     *
     * The accordion animation consists of three stages:
     * 1) Animate into the screen within a pre-specified fly in duration.
     * 2) Hold in place for a certain amount of time (Optional).
     * 3) Animate out of the screen within the given time.
     *
     * The accordion animator is initialized with 3 parameter: 1) initial position,
     * 2) how far out the view should be before flying back out,  3) end position.
     * The interpolation output should be [0f, 0.5f] during animation between 1)
     * to 2), and [0.5f, 1f] for flying from 2) to 3).
     */
    private final TimeInterpolator mAccordionInterpolator = new TimeInterpolator() {
        @Override
        public float getInterpolation(float input) {

            float flyInDuration = (float) FLY_OUT_DURATION_MS / (float) TOTAL_DURATION_MS;
            float holdDuration = (float) (FLY_OUT_DURATION_MS + HOLD_DURATION_MS)
                    / (float) TOTAL_DURATION_MS;
            if (input == 0) {
                return 0;
            }else if (input < flyInDuration) {
                // Stage 1, project result to [0f, 0.5f]
                input /= flyInDuration;
                float result = Gusterpolator.INSTANCE.getInterpolation(input);
                return result * 0.5f;
            } else if (input < holdDuration) {
                // Stage 2
                return 0.5f;
            } else {
                // Stage 3, project result to [0.5f, 1f]
                input -= holdDuration;
                input /= (1 - holdDuration);
                float result = Gusterpolator.INSTANCE.getInterpolation(input);
                return 0.5f + result * 0.5f;
            }
        }
    };

    /**
     * The listener that is used to notify when gestures occur.
     * Here we only listen to a subset of gestures.
     */
    private final GestureDetector.OnGestureListener mOnGestureListener
            = new GestureDetector.SimpleOnGestureListener(){
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                float distanceX, float distanceY) {

            if (mState == ACCORDION_ANIMATION) {
                // Scroll happens during accordion animation.
                if (isRunningAccordionAnimation()) {
                    mAnimatorSet.cancel();
                }
                setVisibility(VISIBLE);
            }

            if (mState == IDLE) {
                resetModeSelectors();
                setVisibility(VISIBLE);
            }

            mState = SCROLLING;
            // Scroll based on the scrolling distance on the currently focused
            // item.
            scroll(mFocusItem, distanceX, distanceY);
            return true;
        }

        @Override
        public boolean onSingleTapUp(MotionEvent ev) {
            if (mState != FULLY_SHOWN) {
                // Only allows tap to choose mode when the list is fully shown
                return false;
            }
            int index = getFocusItem(ev.getX(), ev.getY());
            // Validate the selection
            if (index != NO_ITEM_SELECTED) {
                final int modeId = getModeIndex(index);
                mModeSelectorItems[index].highlight();
                mState = MODE_SELECTED;
                PeepholeAnimationEffect effect = new PeepholeAnimationEffect();
                effect.setSize(mWidth, mHeight);
                effect.setAnimationEndAction(new Runnable() {
                    @Override
                    public void run() {
                        setVisibility(INVISIBLE);
                        mCurrentEffect = null;
                        snapBack(false);
                    }
                });
                effect.setAnimationStartingPosition((int) ev.getX(), (int) ev.getY());
                mCurrentEffect = effect;

                // Post mode selection runnable to the end of the message queue
                // so that current UI changes can finish before mode initialization
                // clogs up UI thread.
                post(new Runnable() {
                    @Override
                    public void run() {
                        onModeSelected(modeId);
                    }
                });
            }
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            // Cache velocity in the unit pixel/ms.
            mVelocityX = velocityX / 1000f;
            return true;
        }
    };

    public ModeListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mGestureDetector = new GestureDetector(context, mOnGestureListener);
        mIconBlockWidth = getResources()
                .getDimensionPixelSize(R.dimen.mode_selector_icon_block_width);
        mListBackgroundColor = getResources().getColor(R.color.mode_list_background);
    }

    /**
     * Sets the alpha on the list background. This is called whenever the list
     * is scrolling or animating, so that background can adjust its dimness.
     *
     * @param alpha new alpha to be applied on list background color
     */
    private void setBackgroundAlpha(int alpha) {
        // Make sure alpha is valid.
        alpha = alpha & 0xFF;
        // Change alpha on the background color.
        mListBackgroundColor = mListBackgroundColor & 0xFFFFFF;
        mListBackgroundColor = mListBackgroundColor | (alpha << 24);
        // Set new color to list background.
        mListView.setBackgroundColor(mListBackgroundColor);
    }

    /**
     * Initialize mode list with a list of indices of supported modes.
     *
     * @param modeIndexList a list of indices of supported modes
     */
    public void init(List<Integer> modeIndexList) {
        int[] modeSequence = getResources()
                .getIntArray(R.array.camera_modes_in_nav_drawer_if_supported);
        int[] visibleModes = getResources()
                .getIntArray(R.array.camera_modes_always_visible);

        // Mark the supported modes in a boolean array to preserve the
        // sequence of the modes
        SparseArray<Boolean> modeIsSupported = new SparseArray<Boolean>();
        for (int i = 0; i < modeIndexList.size(); i++) {
            int mode = modeIndexList.get(i);
            modeIsSupported.put(mode, true);
        }
        for (int i = 0; i < visibleModes.length; i++) {
            int mode = visibleModes[i];
            modeIsSupported.put(mode, true);
        }

        // Put the indices of supported modes into an array preserving their
        // display order.
        mSupportedModes = new ArrayList<Integer>();
        for (int i = 0; i < modeSequence.length; i++) {
            int mode = modeSequence[i];
            if (modeIsSupported.get(mode, false)) {
                mSupportedModes.add(mode);
            }
        }
        mTotalModes = mSupportedModes.size();
        initializeModeSelectorItems();
    }

    private void initializeModeSelectorItems() {
        mModeSelectorItems = new ModeSelectorItem[mTotalModes];
        // Inflate the mode selector items and add them to a linear layout
        LayoutInflater inflater = (LayoutInflater) getContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mListView = (LinearLayout) findViewById(R.id.mode_list);
        for (int i = 0; i < mTotalModes; i++) {
            ModeSelectorItem selectorItem =
                    (ModeSelectorItem) inflater.inflate(R.layout.mode_selector, null);
            mListView.addView(selectorItem);
            // Set alternating background color for each mode selector in the list
            if (i % 2 == 0) {
                selectorItem.setDefaultBackgroundColor(getResources()
                        .getColor(R.color.mode_selector_background_light));
            } else {
                selectorItem.setDefaultBackgroundColor(getResources()
                        .getColor(R.color.mode_selector_background_dark));
            }
            int modeId = getModeIndex(i);
            selectorItem.setIconBackgroundColor(getResources()
                    .getColor(CameraUtil.getCameraThemeColorId(modeId, getContext())));

            // Set image
            selectorItem.setImageResource(CameraUtil.getCameraModeIconResId(modeId, getContext()));

            // Set text
            selectorItem.setText(CameraUtil.getCameraModeText(modeId, getContext()));

            // Set content description (for a11y)
            selectorItem.setContentDescription(CameraUtil
                    .getCameraModeContentDescription(modeId, getContext()));

            mModeSelectorItems[i] = selectorItem;
        }

        resetModeSelectors();
    }

    /**
     * Maps between the UI mode selector index to the actual mode id.
     *
     * @param modeSelectorIndex the index of the UI item
     * @return the index of the corresponding camera mode
     */
    private int getModeIndex(int modeSelectorIndex) {
        if (modeSelectorIndex < mTotalModes && modeSelectorIndex >= 0) {
            return mSupportedModes.get(modeSelectorIndex);
        }
        Log.e(TAG, "Invalid mode selector index: " + modeSelectorIndex + ", total modes: "
                + mTotalModes);
        return getResources().getInteger(R.integer.camera_mode_photo);
    }

    /** Notify ModeSwitchListener, if any, of the mode change. */
    private void onModeSelected(int modeIndex) {
        if (mModeSwitchListener != null) {
            mModeSwitchListener.onModeSelected(modeIndex);
        }
    }

    /**
     * Sets a listener that listens to receive mode switch event.
     *
     * @param listener a listener that gets notified when mode changes.
     */
    public void setModeSwitchListener(ModeSwitchListener listener) {
        mModeSwitchListener = listener;
    }

    /**
     * Sets a listener that gets notified when the mode list is open full screen.
     *
     * @param listener a listener that listens to mode list open events
     */
    public void setModeListOpenListener(ModeListOpenListener listener) {
        mModeListOpenListener = listener;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (mCurrentEffect != null) {
            return mCurrentEffect.onTouchEvent(ev);
        }

        super.onTouchEvent(ev);
        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
            mVelocityX = 0;
            if  (mState == ACCORDION_ANIMATION) {
                // Let taps go through to take a capture during the accordion
                return false;
            }
            getParent().requestDisallowInterceptTouchEvent(true);
            if (mState == FULLY_SHOWN) {
                mFocusItem = NO_ITEM_SELECTED;
                setSwipeMode(false);
            } else {
                mFocusItem = getFocusItem(ev.getX(), ev.getY());
                setSwipeMode(true);
            }
        } else if (mState == ACCORDION_ANIMATION) {
            // This is a swipe during accordion animation
            mFocusItem = getFocusItem(ev.getX(), ev.getY());
            setSwipeMode(true);

        }
        // Pass all touch events to gesture detector for gesture handling.
        mGestureDetector.onTouchEvent(ev);
        if (ev.getActionMasked() == MotionEvent.ACTION_UP ||
                ev.getActionMasked() == MotionEvent.ACTION_CANCEL) {
            snap();
            mFocusItem = NO_ITEM_SELECTED;
        }
        return true;
    }

    /**
     * Sets the swipe mode to indicate whether this is a swiping in
     * or out, and therefore we can have different animations.
     *
     * @param swipeIn indicates whether the swipe should reveal/hide the list.
     */
    private void setSwipeMode(boolean swipeIn) {
        for (int i = 0 ; i < mModeSelectorItems.length; i++) {
            mModeSelectorItems[i].onSwipeModeChanged(swipeIn);
        }
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        mWidth = right - left;
        mHeight = bottom - top - getPaddingTop() - getPaddingBottom();
        if (mCurrentEffect != null) {
            mCurrentEffect.setSize(mWidth, mHeight);
        }
    }

    /**
     * Here we calculate the children size based on the orientation, change
     * their layout parameters if needed before propagating onMeasure call
     * to the children, so the newly changed params will take effect in this
     * pass.
     *
     * @param widthMeasureSpec Horizontal space requirements as imposed by the
     *        parent
     * @param heightMeasureSpec Vertical space requirements as imposed by the
     *        parent
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        float height = MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop()
                - getPaddingBottom();

        Configuration config = getResources().getConfiguration();
        if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            height = height / ROWS_TO_SHOW_IN_LANDSCAPE;
            setVerticalScrollBarEnabled(true);
        } else {
            height = height / mTotalModes;
            setVerticalScrollBarEnabled(false);
        }
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(mWidth, 0);
        lp.width = LayoutParams.MATCH_PARENT;
        for (int i = 0; i < mTotalModes; i++) {
            // This is to avoid rounding that would cause the total height of the
            // list a few pixels off the height of the screen.
            int itemHeight = (int) (height * (i + 1)) - (int) (height * i);
            lp.height = itemHeight;
            mModeSelectorItems[i].setLayoutParams(lp);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    public void draw(Canvas canvas) {
        if (mCurrentEffect != null) {
            mCurrentEffect.drawBackground(canvas);
            super.draw(canvas);
            mCurrentEffect.drawForeground(canvas);
        } else {
            super.draw(canvas);
        }
    }

    /**
     * This starts the accordion animation, unless it's already running, in which
     * case the start animation call will be ignored.
     */
    public void startAccordionAnimation() {
        if (mState != IDLE) {
            return;
        }
        if (mAnimatorSet != null && mAnimatorSet.isRunning()) {
            return;
        }
        mState = ACCORDION_ANIMATION;
        resetModeSelectors();
        animateListToWidth(START_DELAY_MS, TOTAL_DURATION_MS, mAccordionInterpolator,
                0, mIconBlockWidth, 0);
    }

    /**
     * This starts the accordion animation with a delay.
     *
     * @param delay delay in milliseconds before starting animation
     */
    public void startAccordionAnimationWithDelay(int delay) {
        postDelayed(new Runnable() {
            @Override
            public void run() {
                startAccordionAnimation();
            }
        }, delay);
    }

    /**
     * Resets the visible width of all the mode selectors to 0.
     */
    private void resetModeSelectors() {
        for (int i = 0; i < mModeSelectorItems.length; i++) {
            mModeSelectorItems[i].setVisibleWidth(0);
            mModeSelectorItems[i].unHighlight();
        }
        // Visible width has been changed to 0
        onVisibleWidthChanged(0);
    }

    private boolean isRunningAccordionAnimation() {
        return mAnimatorSet != null && mAnimatorSet.isRunning();
    }

    /**
     * Calculate the mode selector item in the list that is at position (x, y).
     *
     * @param x horizontal position
     * @param y vertical position
     * @return index of the item that is at position (x, y)
     */
    private int getFocusItem(float x, float y) {
        // Take into account the scrolling offset
        x += getScrollX();
        y += getScrollY();

        for (int i = 0; i < mModeSelectorItems.length; i++) {
            if (mModeSelectorItems[i].getTop() <= y && mModeSelectorItems[i].getBottom() >= y) {
                return i;
            }
        }
        return NO_ITEM_SELECTED;
    }

    private void scroll(int itemId, float deltaX, float deltaY) {
        // Scrolling trend on X and Y axis, to track the trend by biasing
        // towards latest touch events.
        mScrollTrendX = mScrollTrendX * 0.3f + deltaX * 0.7f;
        mScrollTrendY = mScrollTrendY * 0.3f + deltaY * 0.7f;

        // TODO: Change how the curve is calculated below when UX finalize their design.
        mCurrentTime = SystemClock.uptimeMillis();
        float longestWidth;
        if (itemId != NO_ITEM_SELECTED) {
            longestWidth = mModeSelectorItems[itemId].getVisibleWidth() - deltaX;
        } else {
            longestWidth = mModeSelectorItems[0].getVisibleWidth() - deltaX;
        }
        insertNewPosition(longestWidth, mCurrentTime);

        for (int i = 0; i < mModeSelectorItems.length; i++) {
            mModeSelectorItems[i].setVisibleWidth(calculateVisibleWidthForItem(i,
                    (int) longestWidth));
        }
        if (longestWidth <= 0) {
            reset();
        }

        itemId = itemId == NO_ITEM_SELECTED ? 0 : itemId;
        onVisibleWidthChanged(mModeSelectorItems[itemId].getVisibleWidth());
    }

    /**
     * Calculate the width of a specified item based on its position relative to
     * the item with longest width.
     */
    private int calculateVisibleWidthForItem(int itemId, int longestWidth) {
        if (itemId == mFocusItem || mFocusItem == NO_ITEM_SELECTED) {
            return longestWidth;
        }

        int delay = Math.abs(itemId - mFocusItem) * DELAY_MS;
        return (int) getPosition(mCurrentTime - delay);
    }

    /**
     * Insert new position and time stamp into the history position list, and
     * remove stale position items.
     *
     * @param position latest position of the focus item
     * @param time  current time in milliseconds
     */
    private void insertNewPosition(float position, long time) {
        // TODO: Consider re-using stale position objects rather than
        // always creating new position objects.
        mPositionHistory.add(new TimeBasedPosition(position, time));

        // Positions that are from too long ago will not be of any use for
        // future position interpolation. So we need to remove those positions
        // from the list.
        long timeCutoff = time - (mTotalModes - 1) * DELAY_MS;
        while (mPositionHistory.size() > 0) {
            // Remove all the position items that are prior to the cutoff time.
            TimeBasedPosition historyPosition = mPositionHistory.getFirst();
            if (historyPosition.getTimeStamp() < timeCutoff) {
                mPositionHistory.removeFirst();
            } else {
                break;
            }
        }
    }

    /**
     * Gets the interpolated position at the specified time. This involves going
     * through the recorded positions until a {@link TimeBasedPosition} is found
     * such that the position the recorded before the given time, and the
     * {@link TimeBasedPosition} after that is recorded no earlier than the given
     * time. These two positions are then interpolated to get the position at the
     * specified time.
     */
    private float getPosition(long time) {
        int i;
        for (i = 0; i < mPositionHistory.size(); i++) {
            TimeBasedPosition historyPosition = mPositionHistory.get(i);
            if (historyPosition.getTimeStamp() > time) {
                // Found the winner. Now interpolate between position i and position i - 1
                if (i == 0) {
                    return historyPosition.getPosition();
                } else {
                    TimeBasedPosition prevTimeBasedPosition = mPositionHistory.get(i - 1);
                    // Start interpolation
                    float fraction = (float) (time - prevTimeBasedPosition.getTimeStamp()) /
                            (float) (historyPosition.getTimeStamp() - prevTimeBasedPosition.getTimeStamp());
                    float position = fraction * (historyPosition.getPosition()
                            - prevTimeBasedPosition.getPosition()) + prevTimeBasedPosition.getPosition();
                    return position;
                }
            }
        }
        // It should never get here.
        Log.e(TAG, "Invalid time input for getPosition(). time: " + time);
        if (mPositionHistory.size() == 0) {
            Log.e(TAG, "TimeBasedPosition history size is 0");
        } else {
            Log.e(TAG, "First position recorded at " + mPositionHistory.getFirst().getTimeStamp()
            + " , last position recorded at " + mPositionHistory.getLast().getTimeStamp());
        }
        assert (i < mPositionHistory.size());
        return i;
    }

    private void reset() {
        resetModeSelectors();
        mScrollTrendX = 0f;
        mScrollTrendY = 0f;
        mCurrentEffect = null;
        setVisibility(INVISIBLE);
    }

    /**
     * When visible width of list is changed, the background of the list needs
     * to darken/lighten correspondingly.
     */
    private void onVisibleWidthChanged(int focusItemWidth) {
        // Background alpha should be 0 before the icon block is entirely visible,
        // and when the longest mode item is entirely shown (across the screen), the
        // background should be 50% transparent.
        if (focusItemWidth <= mIconBlockWidth) {
            setBackgroundAlpha(0);
        } else {
            // Alpha should increase linearly when mode item goes beyond the icon block
            // till it reaches its max width
            int alpha = 127 * (focusItemWidth - mIconBlockWidth) / (mWidth - mIconBlockWidth);
            setBackgroundAlpha(alpha);
        }
    }

    @Override
    public void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);
        if (visibility != VISIBLE) {
            // Reset mode list if the window is no longer visible.
            reset();
            mState = IDLE;
        }
    }

    /**
     * The list view should either snap back or snap to full screen after a gesture.
     * This function is called when an up or cancel event is received, and then based
     * on the current position of the list and the gesture we can decide which way
     * to snap.
     */
    private void snap() {
        if (mState == SCROLLING) {
            int itemId = Math.max(0, mFocusItem);
            if (mModeSelectorItems[itemId].getVisibleWidth() < mIconBlockWidth) {
                snapBack();
            } else if (Math.abs(mScrollTrendX) > Math.abs(mScrollTrendY) && mScrollTrendX > 0) {
                snapBack();
            } else {
                snapToFullScreen();
            }
        }
    }

    /**
     * Snaps back out of the screen.
     *
     * @param withAnimation whether snapping back should be animated
     */
    public void snapBack(boolean withAnimation) {
        if (withAnimation) {
            animateListToWidth(0);
            mState = IDLE;
        } else {
            setVisibility(INVISIBLE);
            resetModeSelectors();
            mState = IDLE;
        }
    }

    /**
     * Snaps the mode list back out with animation.
     */
    private void snapBack() {
        snapBack(true);
    }

    private void snapToFullScreen() {
        if (mVelocityX <= VELOCITY_THRESHOLD) {
            animateListToWidth(mWidth);
        } else {
            // If the fling velocity exceeds this threshold, snap to full screen
            // at a constant speed.
            animateListToWidthAtVelocity(mVelocityX, mWidth);
        }
        mState = FULLY_SHOWN;
        if (mModeListOpenListener != null) {
            mModeListOpenListener.onOpenFullScreen();
        }
    }

    /**
     * Overloaded function to provide a simple way to start animation. Animation
     * will use default duration, and a value of <code>null</code> for interpolator
     * means linear interpolation will be used.
     *
     * @param width a set of values that the animation will animate between over time
     */
    private void animateListToWidth(int... width) {
        animateListToWidth(0, DEFAULT_DURATION_MS, null, width);
    }

    /**
     * Animate the mode list between the given set of visible width.
     *
     * @param delay start delay between consecutive mode item
     * @param duration duration for the animation of each mode item
     * @param interpolator interpolator to be used by the animation
     * @param width a set of values that the animation will animate between over time
     */
    private void animateListToWidth(int delay, int duration,
                                    TimeInterpolator interpolator, int... width) {
        if (mAnimatorSet != null && mAnimatorSet.isRunning()) {
            mAnimatorSet.end();
        }

        ArrayList<Animator> animators = new ArrayList<Animator>();
        int focusItem = mFocusItem == NO_ITEM_SELECTED ? 0 : mFocusItem;
        for (int i = 0; i < mTotalModes; i++) {
            ObjectAnimator animator = ObjectAnimator.ofInt(mModeSelectorItems[i],
                    "visibleWidth", width);
            animator.setDuration(duration);
            animator.setStartDelay(i * delay);
            animators.add(animator);
            if (i == focusItem) {
                animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        onVisibleWidthChanged((Integer) animation.getAnimatedValue());
                    }
                });
            }
        }

        mAnimatorSet = new AnimatorSet();
        mAnimatorSet.playTogether(animators);
        mAnimatorSet.setInterpolator(interpolator);
        mAnimatorSet.addListener(mModeListAnimatorListener);
        mAnimatorSet.start();
    }

    /**
     * Animate the mode list to the given width at a constant velocity.
     *
     * @param velocity the velocity that animation will be at
     * @param width final width of the list
     */
    private void animateListToWidthAtVelocity(float velocity, int width) {
        if (mAnimatorSet != null && mAnimatorSet.isRunning()) {
            mAnimatorSet.end();
        }

        ArrayList<Animator> animators = new ArrayList<Animator>();
        int focusItem = mFocusItem == NO_ITEM_SELECTED ? 0 : mFocusItem;
        for (int i = 0; i < mTotalModes; i++) {
            ObjectAnimator animator = ObjectAnimator.ofInt(mModeSelectorItems[i],
                    "visibleWidth", width);
            int duration = (int) ((float) width / velocity);
            animator.setDuration(duration);
            animators.add(animator);
            if (i == focusItem) {
                animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        onVisibleWidthChanged((Integer) animation.getAnimatedValue());
                    }
                });
            }
        }

        mAnimatorSet = new AnimatorSet();
        mAnimatorSet.playTogether(animators);
        mAnimatorSet.setInterpolator(null);
        mAnimatorSet.addListener(mModeListAnimatorListener);
        mAnimatorSet.start();
    }

    /**
     * Called when the back key is pressed.
     *
     * @return Whether the UI responded to the key event.
     */
    public boolean onBackPressed() {
        if (mState == FULLY_SHOWN) {
            snapBack();
            return true;
        } else {
            return false;
        }
    }

    public void startModeSelectionAnimation() {
        if (mState != MODE_SELECTED || mCurrentEffect == null) {
            setVisibility(INVISIBLE);
            snapBack(false);
            mCurrentEffect = null;
        } else {
            mCurrentEffect.startAnimation();
        }

    }

    private class PeepholeAnimationEffect extends AnimationEffects {

        private final static int UNSET = -1;
        private final static int PEEP_HOLE_ANIMATION_DURATION_MS = 650;

        private int mWidth;
        private int mHeight;

        private int mPeepHoleCenterX = UNSET;
        private int mPeepHoleCenterY = UNSET;
        private float mRadius = 0f;
        private ValueAnimator mPeepHoleAnimator;
        private Runnable mEndAction;
        private final Paint mMaskPaint = new Paint();

        public PeepholeAnimationEffect() {
            mMaskPaint.setAlpha(0);
            mMaskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        }

        @Override
        public void setSize(int width, int height) {
            mWidth = width;
            mHeight = height;
        }

        @Override
        public void drawForeground(Canvas canvas) {
            // Draw the circle in clear mode
            if (mPeepHoleAnimator != null) {
                // Draw a transparent circle using clear mode
                canvas.drawCircle(mPeepHoleCenterX, mPeepHoleCenterY, mRadius, mMaskPaint);
            }
        }

        public void setAnimationStartingPosition(int x, int y) {
            mPeepHoleCenterX = x;
            mPeepHoleCenterY = y;
        }

        @Override
        public void startAnimation() {
            if (mPeepHoleAnimator != null && mPeepHoleAnimator.isRunning()) {
                return;
            }
            if (mPeepHoleCenterY == UNSET || mPeepHoleCenterX == UNSET) {
                mPeepHoleCenterX = mWidth / 2;
                mPeepHoleCenterY = mHeight / 2;
            }

            int horizontalDistanceToFarEdge = Math.max(mPeepHoleCenterX, mWidth - mPeepHoleCenterX);
            int verticalDistanceToFarEdge = Math.max(mPeepHoleCenterY, mHeight - mPeepHoleCenterY);
            int endRadius = (int) (Math.sqrt(horizontalDistanceToFarEdge * horizontalDistanceToFarEdge
                    + verticalDistanceToFarEdge * verticalDistanceToFarEdge));

            mPeepHoleAnimator = ValueAnimator.ofFloat(0, endRadius);
            mPeepHoleAnimator.setDuration(PEEP_HOLE_ANIMATION_DURATION_MS);
            mPeepHoleAnimator.setInterpolator(Gusterpolator.INSTANCE);
            mPeepHoleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    // Modify mask by enlarging the hole
                    mRadius = (Float) mPeepHoleAnimator.getAnimatedValue();
                    invalidate();
                }
            });

            mPeepHoleAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {

                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    if (mEndAction != null) {
                        post(mEndAction);
                        mEndAction = null;
                        post(new Runnable() {
                            @Override
                            public void run() {
                                mPeepHoleAnimator = null;
                                mRadius = 0;
                                mPeepHoleCenterX = UNSET;
                                mPeepHoleCenterY = UNSET;
                            }
                        });
                    } else {
                        mPeepHoleAnimator = null;
                        mRadius = 0;
                        mPeepHoleCenterX = UNSET;
                        mPeepHoleCenterY = UNSET;
                    }
                }

                @Override
                public void onAnimationCancel(Animator animation) {

                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });
            mPeepHoleAnimator.start();
        }

        public void setAnimationEndAction(Runnable runnable) {
            mEndAction = runnable;
        }
    }
}
