/*
 * Copyright (C) 2012 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.keyguard;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.TimeInterpolator;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.util.Slog;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.TextClock;

import com.android.internal.widget.LockPatternUtils;

import java.util.ArrayList;
import java.util.TimeZone;

public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwitchListener,
        OnLongClickListener, ChallengeLayout.OnBouncerStateChangedListener {

    ZInterpolator mZInterpolator = new ZInterpolator(0.5f);
    private static float CAMERA_DISTANCE = 10000;
    protected static float OVERSCROLL_MAX_ROTATION = 30;
    private static final boolean PERFORM_OVERSCROLL_ROTATION = true;

    private static final int FLAG_HAS_LOCAL_HOUR = 0x1;
    private static final int FLAG_HAS_LOCAL_MINUTE = 0x2;

    protected KeyguardViewStateManager mViewStateManager;
    private LockPatternUtils mLockPatternUtils;

    // Related to the fading in / out background outlines
    public static final int CHILDREN_OUTLINE_FADE_OUT_DURATION = 375;
    public static final int CHILDREN_OUTLINE_FADE_IN_DURATION = 100;
    protected AnimatorSet mChildrenOutlineFadeAnimation;
    protected int mScreenCenter;
    private boolean mHasMeasure = false;
    boolean showHintsAfterLayout = false;

    private static final long CUSTOM_WIDGET_USER_ACTIVITY_TIMEOUT = 30000;
    private static final String TAG = "KeyguardWidgetPager";
    private boolean mCenterSmallWidgetsVertically;

    private int mPage = 0;
    private Callbacks mCallbacks;

    private int mWidgetToResetAfterFadeOut;
    protected boolean mShowingInitialHints = false;

    // A temporary handle to the Add-Widget view
    private View mAddWidgetView;
    private int mLastWidthMeasureSpec;
    private int mLastHeightMeasureSpec;

    // Bouncer
    private int mBouncerZoomInOutDuration = 250;
    private float BOUNCER_SCALE_FACTOR = 0.67f;

    // Background worker thread: used here for persistence, also made available to widget frames
    private final HandlerThread mBackgroundWorkerThread;
    private final Handler mBackgroundWorkerHandler;
    private boolean mCameraEventInProgress;

    public KeyguardWidgetPager(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public KeyguardWidgetPager(Context context) {
        this(null, null, 0);
    }

    public KeyguardWidgetPager(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
            setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
        }

        setPageSwitchListener(this);

        mBackgroundWorkerThread = new HandlerThread("KeyguardWidgetPager Worker");
        mBackgroundWorkerThread.start();
        mBackgroundWorkerHandler = new Handler(mBackgroundWorkerThread.getLooper());
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();

        // Clean up the worker thread
        mBackgroundWorkerThread.quit();
    }

    public void setViewStateManager(KeyguardViewStateManager viewStateManager) {
        mViewStateManager = viewStateManager;
    }

    public void setLockPatternUtils(LockPatternUtils l) {
        mLockPatternUtils = l;
    }

    @Override
    public void onPageSwitching(View newPage, int newPageIndex) {
        if (mViewStateManager != null) {
            mViewStateManager.onPageSwitching(newPage, newPageIndex);
        }
    }

    @Override
    public void onPageSwitched(View newPage, int newPageIndex) {
        boolean showingClock = false;
        if (newPage instanceof ViewGroup) {
            ViewGroup vg = (ViewGroup) newPage;
            if (vg.getChildAt(0) instanceof KeyguardStatusView) {
                showingClock = true;
            }
        }

        if (newPage != null &&
                findClockInHierarchy(newPage) == (FLAG_HAS_LOCAL_HOUR | FLAG_HAS_LOCAL_MINUTE)) {
            showingClock = true;
        }

        // Disable the status bar clock if we're showing the default status widget
        if (showingClock) {
            setSystemUiVisibility(getSystemUiVisibility() | View.STATUS_BAR_DISABLE_CLOCK);
        } else {
            setSystemUiVisibility(getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_CLOCK);
        }

        // Extend the display timeout if the user switches pages
        if (mPage != newPageIndex) {
            int oldPageIndex = mPage;
            mPage = newPageIndex;
            userActivity();
            KeyguardWidgetFrame oldWidgetPage = getWidgetPageAt(oldPageIndex);
            if (oldWidgetPage != null) {
                oldWidgetPage.onActive(false);
            }
            KeyguardWidgetFrame newWidgetPage = getWidgetPageAt(newPageIndex);
            if (newWidgetPage != null) {
                newWidgetPage.onActive(true);
                newWidgetPage.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
                newWidgetPage.requestAccessibilityFocus();
            }
            if (mParent != null && AccessibilityManager.getInstance(mContext).isEnabled()) {
                AccessibilityEvent event = AccessibilityEvent.obtain(
                        AccessibilityEvent.TYPE_VIEW_SCROLLED);
                onInitializeAccessibilityEvent(event);
                onPopulateAccessibilityEvent(event);
                mParent.requestSendAccessibilityEvent(this, event);
            }
        }
        if (mViewStateManager != null) {
            mViewStateManager.onPageSwitched(newPage, newPageIndex);
        }
    }

    @Override
    public void onPageBeginWarp() {
        showOutlinesAndSidePages();
        mViewStateManager.onPageBeginWarp();
    }

    @Override
    public void onPageEndWarp() {
        // if we're moving to the warp page, then immediately hide the other widgets.
        int duration = getPageWarpIndex() == getNextPage() ? 0 : -1;
        animateOutlinesAndSidePages(false, duration);
        mViewStateManager.onPageEndWarp();
    }

    @Override
    public void sendAccessibilityEvent(int eventType) {
        if (eventType != AccessibilityEvent.TYPE_VIEW_SCROLLED || isPageMoving()) {
            super.sendAccessibilityEvent(eventType);
        }
    }

    private void updateWidgetFramesImportantForAccessibility() {
        final int pageCount = getPageCount();
        for (int i = 0; i < pageCount; i++) {
            KeyguardWidgetFrame frame = getWidgetPageAt(i);
            updateWidgetFrameImportantForAccessibility(frame);
        }
    }

    private void updateWidgetFrameImportantForAccessibility(KeyguardWidgetFrame frame) {
        if (frame.getContentAlpha() <= 0) {
            frame.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
        } else {
            frame.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
        }
    }

    private void userActivity() {
        if (mCallbacks != null) {
            mCallbacks.onUserActivityTimeoutChanged();
            mCallbacks.userActivity();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return captureUserInteraction(ev) || super.onTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return captureUserInteraction(ev) || super.onInterceptTouchEvent(ev);
    }

    private boolean captureUserInteraction(MotionEvent ev) {
        KeyguardWidgetFrame currentWidgetPage = getWidgetPageAt(getCurrentPage());
        return currentWidgetPage != null && currentWidgetPage.onUserInteraction(ev);
    }

    public void showPagingFeedback() {
        // Nothing yet.
    }

    public long getUserActivityTimeout() {
        View page = getPageAt(mPage);
        if (page instanceof ViewGroup) {
            ViewGroup vg = (ViewGroup) page;
            View view = vg.getChildAt(0);
            if (!(view instanceof KeyguardStatusView)
                    && !(view instanceof KeyguardMultiUserSelectorView)) {
                return CUSTOM_WIDGET_USER_ACTIVITY_TIMEOUT;
            }
        }
        return -1;
    }

    public void setCallbacks(Callbacks callbacks) {
        mCallbacks = callbacks;
    }

    public interface Callbacks {
        public void userActivity();
        public void onUserActivityTimeoutChanged();
        public void onAddView(View v);
        public void onRemoveView(View v, boolean deletePermanently);
        public void onRemoveViewAnimationCompleted();
    }

    public void addWidget(View widget) {
        addWidget(widget, -1);
    }

    public void onRemoveView(View v, final boolean deletePermanently) {
        final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId();
        if (mCallbacks != null) {
            mCallbacks.onRemoveView(v, deletePermanently);
        }
        mBackgroundWorkerHandler.post(new Runnable() {
            @Override
            public void run() {
                mLockPatternUtils.removeAppWidget(appWidgetId);
            }
        });
    }

    @Override
    public void onRemoveViewAnimationCompleted() {
        if (mCallbacks != null) {
            mCallbacks.onRemoveViewAnimationCompleted();
        }
    }

    public void onAddView(View v, final int index) {
        final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId();
        final int[] pagesRange = new int[mTempVisiblePagesRange.length];
        getVisiblePages(pagesRange);
        boundByReorderablePages(true, pagesRange);
        if (mCallbacks != null) {
            mCallbacks.onAddView(v);
        }
        // Subtract from the index to take into account pages before the reorderable
        // pages (e.g. the "add widget" page)
        mBackgroundWorkerHandler.post(new Runnable() {
            @Override
            public void run() {
                mLockPatternUtils.addAppWidget(appWidgetId, index - pagesRange[0]);
            }
        });
    }

    /*
     * We wrap widgets in a special frame which handles drawing the over scroll foreground.
     */
    public void addWidget(View widget, int pageIndex) {
        KeyguardWidgetFrame frame;
        // All views contained herein should be wrapped in a KeyguardWidgetFrame
        if (!(widget instanceof KeyguardWidgetFrame)) {
            frame = new KeyguardWidgetFrame(getContext());
            FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
                    LayoutParams.MATCH_PARENT);
            lp.gravity = Gravity.TOP;

            // The framework adds a default padding to AppWidgetHostView. We don't need this padding
            // for the Keyguard, so we override it to be 0.
            widget.setPadding(0,  0, 0, 0);
            frame.addView(widget, lp);

            // We set whether or not this widget supports vertical resizing.
            if (widget instanceof AppWidgetHostView) {
                AppWidgetHostView awhv = (AppWidgetHostView) widget;
                AppWidgetProviderInfo info = awhv.getAppWidgetInfo();
                if ((info.resizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0) {
                    frame.setWidgetLockedSmall(false);
                } else {
                    // Lock the widget to be small.
                    frame.setWidgetLockedSmall(true);
                    if (mCenterSmallWidgetsVertically) {
                        lp.gravity = Gravity.CENTER;
                    }
                }
            }
        } else {
            frame = (KeyguardWidgetFrame) widget;
        }

        ViewGroup.LayoutParams pageLp = new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        frame.setOnLongClickListener(this);
        frame.setWorkerHandler(mBackgroundWorkerHandler);

        if (pageIndex == -1) {
            addView(frame, pageLp);
        } else {
            addView(frame, pageIndex, pageLp);
        }

        // Update the frame content description.
        View content = (widget == frame) ?  frame.getContent() : widget;
        if (content != null) {
            String contentDescription = mContext.getString(
                R.string.keyguard_accessibility_widget,
                content.getContentDescription());
            frame.setContentDescription(contentDescription);
        }
        updateWidgetFrameImportantForAccessibility(frame);
    }

    /**
     * Use addWidget() instead.
     * @deprecated
     */
    @Override
    public void addView(View child, int index) {
        enforceKeyguardWidgetFrame(child);
        super.addView(child, index);
    }

    /**
     * Use addWidget() instead.
     * @deprecated
     */
    @Override
    public void addView(View child, int width, int height) {
        enforceKeyguardWidgetFrame(child);
        super.addView(child, width, height);
    }

    /**
     * Use addWidget() instead.
     * @deprecated
     */
    @Override
    public void addView(View child, LayoutParams params) {
        enforceKeyguardWidgetFrame(child);
        super.addView(child, params);
    }

    /**
     * Use addWidget() instead.
     * @deprecated
     */
    @Override
    public void addView(View child, int index, LayoutParams params) {
        enforceKeyguardWidgetFrame(child);
        super.addView(child, index, params);
    }

    private void enforceKeyguardWidgetFrame(View child) {
        if (!(child instanceof KeyguardWidgetFrame)) {
            throw new IllegalArgumentException(
                    "KeyguardWidgetPager children must be KeyguardWidgetFrames");
        }
    }

    public KeyguardWidgetFrame getWidgetPageAt(int index) {
        // This is always a valid cast as we've guarded the ability to
        return (KeyguardWidgetFrame) getChildAt(index);
    }

    protected void onUnhandledTap(MotionEvent ev) {
        showPagingFeedback();
    }

    @Override
    protected void onPageBeginMoving() {
        if (mViewStateManager != null) {
            mViewStateManager.onPageBeginMoving();
        }
        if (!isReordering(false)) {
            showOutlinesAndSidePages();
        }
        userActivity();
    }

    @Override
    protected void onPageEndMoving() {
        if (mViewStateManager != null) {
            mViewStateManager.onPageEndMoving();
        }

        // In the reordering case, the pages will be faded appropriately on completion
        // of the zoom in animation.
        if (!isReordering(false)) {
            hideOutlinesAndSidePages();
        }
    }

    protected void enablePageContentLayers() {
        int children = getChildCount();
        for (int i = 0; i < children; i++) {
            getWidgetPageAt(i).enableHardwareLayersForContent();
        }
    }

    protected void disablePageContentLayers() {
        int children = getChildCount();
        for (int i = 0; i < children; i++) {
            getWidgetPageAt(i).disableHardwareLayersForContent();
        }
    }

    /*
     * This interpolator emulates the rate at which the perceived scale of an object changes
     * as its distance from a camera increases. When this interpolator is applied to a scale
     * animation on a view, it evokes the sense that the object is shrinking due to moving away
     * from the camera.
     */
    static class ZInterpolator implements TimeInterpolator {
        private float focalLength;

        public ZInterpolator(float foc) {
            focalLength = foc;
        }

        public float getInterpolation(float input) {
            return (1.0f - focalLength / (focalLength + input)) /
                (1.0f - focalLength / (focalLength + 1.0f));
        }
    }

    @Override
    protected void overScroll(float amount) {
        acceleratedOverScroll(amount);
    }

    float backgroundAlphaInterpolator(float r) {
        return Math.min(1f, r);
    }

    private void updatePageAlphaValues(int screenCenter) {
    }

    public float getAlphaForPage(int screenCenter, int index, boolean showSidePages) {
        if (isWarping()) {
            return index == getPageWarpIndex() ? 1.0f : 0.0f;
        }
        if (showSidePages) {
            return 1f;
        } else {
            return index == mCurrentPage ? 1.0f : 0f;
        }
    }

    public float getOutlineAlphaForPage(int screenCenter, int index, boolean showSidePages) {
        if (showSidePages) {
            return getAlphaForPage(screenCenter, index, showSidePages)
                    * KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER;
        } else {
            return 0f;
        }
    }

    protected boolean isOverScrollChild(int index, float scrollProgress) {
        boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
        return (isInOverscroll && (index == 0 && scrollProgress < 0 ||
                index == getChildCount() - 1 && scrollProgress > 0));
    }

    @Override
    protected void screenScrolled(int screenCenter) {
        mScreenCenter = screenCenter;
        updatePageAlphaValues(screenCenter);
        for (int i = 0; i < getChildCount(); i++) {
            KeyguardWidgetFrame v = getWidgetPageAt(i);
            if (v == mDragView) continue;
            if (v != null) {
                float scrollProgress = getScrollProgress(screenCenter, v, i);

                v.setCameraDistance(mDensity * CAMERA_DISTANCE);

                if (isOverScrollChild(i, scrollProgress) && PERFORM_OVERSCROLL_ROTATION) {
                    float pivotX = v.getMeasuredWidth() / 2;
                    float pivotY = v.getMeasuredHeight() / 2;
                    v.setPivotX(pivotX);
                    v.setPivotY(pivotY);
                    v.setRotationY(- OVERSCROLL_MAX_ROTATION * scrollProgress);
                    v.setOverScrollAmount(Math.abs(scrollProgress), scrollProgress < 0);
                } else {
                    v.setRotationY(0f);
                    v.setOverScrollAmount(0, false);
                }

                float alpha = v.getAlpha();
                // If the view has 0 alpha, we set it to be invisible so as to prevent
                // it from accepting touches
                if (alpha == 0) {
                    v.setVisibility(INVISIBLE);
                } else if (v.getVisibility() != VISIBLE) {
                    v.setVisibility(VISIBLE);
                }
            }
        }
    }

    public boolean isWidgetPage(int pageIndex) {
        if (pageIndex < 0 || pageIndex >= getChildCount()) {
            return false;
        }
        View v = getChildAt(pageIndex);
        if (v != null && v instanceof KeyguardWidgetFrame) {
            KeyguardWidgetFrame kwf = (KeyguardWidgetFrame) v;
            return kwf.getContentAppWidgetId() != AppWidgetManager.INVALID_APPWIDGET_ID;
        }
        return false;
    }

    /**
     * Returns the bounded set of pages that are re-orderable.  The range is fully inclusive.
     */
    @Override
    void boundByReorderablePages(boolean isReordering, int[] range) {
        if (isReordering) {
            // Remove non-widget pages from the range
            while (range[1] >= range[0] && !isWidgetPage(range[1])) {
                range[1]--;
            }
            while (range[0] <= range[1] && !isWidgetPage(range[0])) {
                range[0]++;
            }
        }
    }

    protected void reorderStarting() {
        showOutlinesAndSidePages();
    }

    @Override
    protected void onStartReordering() {
        super.onStartReordering();
        enablePageContentLayers();
        reorderStarting();
    }

    @Override
    protected void onEndReordering() {
        super.onEndReordering();
        hideOutlinesAndSidePages();
    }

    void showOutlinesAndSidePages() {
        animateOutlinesAndSidePages(true);
    }

    void hideOutlinesAndSidePages() {
        animateOutlinesAndSidePages(false);
    }

    void updateChildrenContentAlpha(float sidePageAlpha) {
        int count = getChildCount();
        for (int i = 0; i < count; i++) {
            KeyguardWidgetFrame child = getWidgetPageAt(i);
            if (i != mCurrentPage) {
                child.setBackgroundAlpha(sidePageAlpha);
                child.setContentAlpha(0f);
            } else {
                child.setBackgroundAlpha(0f);
                child.setContentAlpha(1f);
            }
        }
    }

    public void showInitialPageHints() {
        mShowingInitialHints = true;
        updateChildrenContentAlpha(KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER);
    }

    @Override
    void setCurrentPage(int currentPage) {
        super.setCurrentPage(currentPage);
        updateChildrenContentAlpha(0.0f);
        updateWidgetFramesImportantForAccessibility();
    }

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        mHasMeasure = false;
    }

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        mLastWidthMeasureSpec = widthMeasureSpec;
        mLastHeightMeasureSpec = heightMeasureSpec;

        int maxChallengeTop = -1;
        View parent = (View) getParent();
        boolean challengeShowing = false;
        // Widget pages need to know where the top of the sliding challenge is so that they
        // now how big the widget should be when the challenge is up. We compute it here and
        // then propagate it to each of our children.
        if (parent.getParent() instanceof SlidingChallengeLayout) {
            SlidingChallengeLayout scl = (SlidingChallengeLayout) parent.getParent();
            int top = scl.getMaxChallengeTop();

            // This is a bit evil, but we need to map a coordinate relative to the SCL into a
            // coordinate relative to our children, hence we subtract the top padding.s
            maxChallengeTop = top - getPaddingTop();
            challengeShowing = scl.isChallengeShowing();

            int count = getChildCount();
            for (int i = 0; i < count; i++) {
                KeyguardWidgetFrame frame = getWidgetPageAt(i);
                frame.setMaxChallengeTop(maxChallengeTop);
                // On the very first measure pass, if the challenge is showing, we need to make sure
                // that the widget on the current page is small.
                if (challengeShowing && i == mCurrentPage && !mHasMeasure) {
                    frame.shrinkWidget(true);
                }
            }
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mHasMeasure = true;
    }

    void animateOutlinesAndSidePages(final boolean show) {
        animateOutlinesAndSidePages(show, -1);
    }

    public void setWidgetToResetOnPageFadeOut(int widget) {
        mWidgetToResetAfterFadeOut = widget;
    }

    public int getWidgetToResetOnPageFadeOut() {
        return mWidgetToResetAfterFadeOut;
    }

    void animateOutlinesAndSidePages(final boolean show, int duration) {
        if (mChildrenOutlineFadeAnimation != null) {
            mChildrenOutlineFadeAnimation.cancel();
            mChildrenOutlineFadeAnimation = null;
        }
        int count = getChildCount();
        PropertyValuesHolder alpha;
        ArrayList<Animator> anims = new ArrayList<Animator>();

        if (duration == -1) {
            duration = show ? CHILDREN_OUTLINE_FADE_IN_DURATION :
                CHILDREN_OUTLINE_FADE_OUT_DURATION;
        }

        int curPage = getNextPage();
        for (int i = 0; i < count; i++) {
            float finalContentAlpha;
            if (show) {
                finalContentAlpha = getAlphaForPage(mScreenCenter, i, true);
            } else if (!show && i == curPage) {
                finalContentAlpha = 1f;
            } else {
                finalContentAlpha = 0f;
            }
            KeyguardWidgetFrame child = getWidgetPageAt(i);

            alpha = PropertyValuesHolder.ofFloat("contentAlpha", finalContentAlpha);
            ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha);
            anims.add(a);

            float finalOutlineAlpha = show ? getOutlineAlphaForPage(mScreenCenter, i, true) : 0f;
            child.fadeFrame(this, show, finalOutlineAlpha, duration);
        }

        mChildrenOutlineFadeAnimation = new AnimatorSet();
        mChildrenOutlineFadeAnimation.playTogether(anims);

        mChildrenOutlineFadeAnimation.setDuration(duration);
        mChildrenOutlineFadeAnimation.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                if (show) {
                    enablePageContentLayers();
                }
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (!show) {
                    disablePageContentLayers();
                    KeyguardWidgetFrame frame = getWidgetPageAt(mWidgetToResetAfterFadeOut);
                    if (frame != null && !(frame == getWidgetPageAt(mCurrentPage) &&
                            mViewStateManager.isChallengeOverlapping())) {
                        frame.resetSize();
                    }
                    mWidgetToResetAfterFadeOut = -1;
                    mShowingInitialHints = false;
                }
                updateWidgetFramesImportantForAccessibility();
            }
        });
        mChildrenOutlineFadeAnimation.start();
    }

    @Override
    public boolean onLongClick(View v) {
        // Disallow long pressing to reorder if the challenge is showing
        boolean isChallengeOverlapping = mViewStateManager.isChallengeShowing() &&
                mViewStateManager.isChallengeOverlapping();
        if (!isChallengeOverlapping && startReordering()) {
            return true;
        }
        return false;
    }

    public void removeWidget(View view) {
        if (view instanceof KeyguardWidgetFrame) {
            removeView(view);
        } else {
            // Assume view was wrapped by a KeyguardWidgetFrame in KeyguardWidgetPager#addWidget().
            // This supports legacy hard-coded "widgets" like KeyguardTransportControlView.
            int pos = getWidgetPageIndex(view);
            if (pos != -1) {
                KeyguardWidgetFrame frame = (KeyguardWidgetFrame) getChildAt(pos);
                frame.removeView(view);
                removeView(frame);
            } else {
                Slog.w(TAG, "removeWidget() can't find:" + view);
            }
        }
    }

    public int getWidgetPageIndex(View view) {
        if (view instanceof KeyguardWidgetFrame) {
            return indexOfChild(view);
        } else {
            // View was wrapped by a KeyguardWidgetFrame by KeyguardWidgetPager#addWidget()
            return indexOfChild((KeyguardWidgetFrame)view.getParent());
        }
    }

    @Override
    protected void setPageHoveringOverDeleteDropTarget(int viewIndex, boolean isHovering) {
        KeyguardWidgetFrame child = getWidgetPageAt(viewIndex);
        child.setIsHoveringOverDeleteDropTarget(isHovering);
    }

    // ChallengeLayout.OnBouncerStateChangedListener
    @Override
    public void onBouncerStateChanged(boolean bouncerActive) {
        if (bouncerActive) {
            zoomOutToBouncer();
        } else {
            zoomInFromBouncer();
        }
    }

    void setBouncerAnimationDuration(int duration) {
        mBouncerZoomInOutDuration = duration;
    }

    // Zoom in after the bouncer is dismissed
    void zoomInFromBouncer() {
        if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) {
            mZoomInOutAnim.cancel();
        }
        final View currentPage = getPageAt(getCurrentPage());
        if (currentPage.getScaleX() < 1f || currentPage.getScaleY() < 1f) {
            mZoomInOutAnim = new AnimatorSet();
            mZoomInOutAnim.playTogether(
                    ObjectAnimator.ofFloat(currentPage, "scaleX", 1f),
                    ObjectAnimator.ofFloat(currentPage , "scaleY", 1f));
            mZoomInOutAnim.setDuration(mBouncerZoomInOutDuration);
            mZoomInOutAnim.setInterpolator(new DecelerateInterpolator(1.5f));
            mZoomInOutAnim.start();
        }
        if (currentPage instanceof KeyguardWidgetFrame) {
            ((KeyguardWidgetFrame)currentPage).onBouncerShowing(false);
        }
    }

    // Zoom out after the bouncer is initiated
    void zoomOutToBouncer() {
        if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) {
            mZoomInOutAnim.cancel();
        }
        int curPage = getCurrentPage();
        View currentPage = getPageAt(curPage);
        if (shouldSetTopAlignedPivotForWidget(curPage)) {
            currentPage.setPivotY(0);
            // Note: we are working around the issue that setting the x-pivot to the same value as it
            //       was does not actually work.
            currentPage.setPivotX(0);
            currentPage.setPivotX(currentPage.getMeasuredWidth() / 2);
        }
        if (!(currentPage.getScaleX() < 1f || currentPage.getScaleY() < 1f)) {
            mZoomInOutAnim = new AnimatorSet();
            mZoomInOutAnim.playTogether(
                    ObjectAnimator.ofFloat(currentPage, "scaleX", BOUNCER_SCALE_FACTOR),
                    ObjectAnimator.ofFloat(currentPage, "scaleY", BOUNCER_SCALE_FACTOR));
            mZoomInOutAnim.setDuration(mBouncerZoomInOutDuration);
            mZoomInOutAnim.setInterpolator(new DecelerateInterpolator(1.5f));
            mZoomInOutAnim.start();
        }
        if (currentPage instanceof KeyguardWidgetFrame) {
            ((KeyguardWidgetFrame)currentPage).onBouncerShowing(true);
        }
    }

    void setAddWidgetEnabled(boolean enabled) {
        if (mAddWidgetView != null && enabled) {
            addView(mAddWidgetView, 0);
            // We need to force measure the PagedView so that the calls to update the scroll
            // position below work
            measure(mLastWidthMeasureSpec, mLastHeightMeasureSpec);
            // Bump up the current page to account for the addition of the new page
            setCurrentPage(mCurrentPage + 1);
            mAddWidgetView = null;
        } else if (mAddWidgetView == null && !enabled) {
            View addWidget = findViewById(R.id.keyguard_add_widget);
            if (addWidget != null) {
                mAddWidgetView = addWidget;
                removeView(addWidget);
            }
        }
    }

    boolean isAddPage(int pageIndex) {
        View v = getChildAt(pageIndex);
        return v != null && v.getId() == R.id.keyguard_add_widget;
    }

    boolean isCameraPage(int pageIndex) {
        View v = getChildAt(pageIndex);
        return v != null && v instanceof CameraWidgetFrame;
    }

    @Override
    protected boolean shouldSetTopAlignedPivotForWidget(int childIndex) {
        return !isCameraPage(childIndex) && super.shouldSetTopAlignedPivotForWidget(childIndex);
    }

    /**
     * Search given {@link View} hierarchy for {@link TextClock} instances that
     * show various time components. Returns combination of
     * {@link #FLAG_HAS_LOCAL_HOUR} and {@link #FLAG_HAS_LOCAL_MINUTE}.
     */
    private static int findClockInHierarchy(View view) {
        if (view instanceof TextClock) {
            return getClockFlags((TextClock) view);
        } else if (view instanceof ViewGroup) {
            int flags = 0;
            final ViewGroup group = (ViewGroup) view;
            final int size = group.getChildCount();
            for (int i = 0; i < size; i++) {
                flags |= findClockInHierarchy(group.getChildAt(i));
            }
            return flags;
        } else {
            return 0;
        }
    }

    /**
     * Return combination of {@link #FLAG_HAS_LOCAL_HOUR} and
     * {@link #FLAG_HAS_LOCAL_MINUTE} describing the time represented described
     * by the given {@link TextClock}.
     */
    private static int getClockFlags(TextClock clock) {
        int flags = 0;

        final String timeZone = clock.getTimeZone();
        if (timeZone != null && !TimeZone.getDefault().equals(TimeZone.getTimeZone(timeZone))) {
            // Ignore clocks showing another timezone
            return 0;
        }

        final CharSequence format = clock.getFormat();
        final char hour = clock.is24HourModeEnabled() ? DateFormat.HOUR_OF_DAY
                : DateFormat.HOUR;

        if (DateFormat.hasDesignator(format, hour)) {
            flags |= FLAG_HAS_LOCAL_HOUR;
        }
        if (DateFormat.hasDesignator(format, DateFormat.MINUTE)) {
            flags |= FLAG_HAS_LOCAL_MINUTE;
        }

        return flags;
    }

    public void handleExternalCameraEvent(MotionEvent event) {
        beginCameraEvent();
        int cameraPage = getPageCount() - 1;
        boolean endWarp = false;
        if (isCameraPage(cameraPage) || mCameraEventInProgress) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    // Once we start dispatching camera events, we must continue to do so
                    // to keep event dispatch happy.
                    mCameraEventInProgress = true;
                    userActivity();
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    mCameraEventInProgress = false;
                    break;
            }
            dispatchTouchEvent(event);
        }
        endCameraEvent();
    }

}
