/*
 * Copyright (C) 2016 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.systemui.statusbar.notification.row;

import static android.provider.Settings.Secure.SHOW_NOTIFICATION_SNOOZE;

import static com.android.systemui.SwipeHelper.SWIPED_FAR_ENOUGH_SIZE_FRACTION;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
import android.app.Notification;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.FrameLayout.LayoutParams;

import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.AlphaOptimizedImageView;
import com.android.systemui.statusbar.notification.row.NotificationGuts.GutsContent;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnClickListener,
        ExpandableNotificationRow.LayoutListener {

    private static final boolean DEBUG = false;
    private static final String TAG = "swipe";

    // Notification must be swiped at least this fraction of a single menu item to show menu
    private static final float SWIPED_FAR_ENOUGH_MENU_FRACTION = 0.25f;
    private static final float SWIPED_FAR_ENOUGH_MENU_UNCLEARABLE_FRACTION = 0.15f;

    // When the menu is displayed, the notification must be swiped within this fraction of a single
    // menu item to snap back to menu (else it will cover the menu or it'll be dismissed)
    private static final float SWIPED_BACK_ENOUGH_TO_COVER_FRACTION = 0.2f;

    private static final int ICON_ALPHA_ANIM_DURATION = 200;
    private static final long SHOW_MENU_DELAY = 60;

    private ExpandableNotificationRow mParent;

    private Context mContext;
    private FrameLayout mMenuContainer;
    private NotificationMenuItem mInfoItem;
    private MenuItem mAppOpsItem;
    private MenuItem mSnoozeItem;
    private ArrayList<MenuItem> mLeftMenuItems;
    private ArrayList<MenuItem> mRightMenuItems;
    private final Map<View, MenuItem> mMenuItemsByView = new ArrayMap<>();
    private OnMenuEventListener mMenuListener;
    private boolean mDismissRtl;
    private boolean mIsForeground;
    private final boolean mIsUsingBidirectionalSwipe;

    private ValueAnimator mFadeAnimator;
    private boolean mAnimating;
    private boolean mMenuFadedIn;

    private boolean mOnLeft;
    private boolean mIconsPlaced;

    private boolean mDismissing;
    private boolean mSnapping;
    private float mTranslation;

    private int[] mIconLocation = new int[2];
    private int[] mParentLocation = new int[2];

    private int mHorizSpaceForIcon = -1;
    private int mVertSpaceForIcons = -1;
    private int mIconPadding = -1;
    private int mSidePadding;

    private float mAlpha = 0f;

    private CheckForDrag mCheckForDrag;
    private Handler mHandler;

    private boolean mMenuSnapped;
    private boolean mMenuSnappedOnLeft;
    private boolean mShouldShowMenu;

    private boolean mIsUserTouching;

    public NotificationMenuRow(Context context) {
        //TODO: (b/131242807) not using bidirectional swipe for now
        this(context, false);
    }

    // Only needed for testing until we want to turn bidirectional swipe back on
    @VisibleForTesting
    NotificationMenuRow(Context context, boolean isUsingBidirectionalSwipe) {
        mContext = context;
        mShouldShowMenu = context.getResources().getBoolean(R.bool.config_showNotificationGear);
        mHandler = new Handler(Looper.getMainLooper());
        mLeftMenuItems = new ArrayList<>();
        mRightMenuItems = new ArrayList<>();
        mIsUsingBidirectionalSwipe = isUsingBidirectionalSwipe;
    }

    @Override
    public ArrayList<MenuItem> getMenuItems(Context context) {
        return mOnLeft ? mLeftMenuItems : mRightMenuItems;
    }

    @Override
    public MenuItem getLongpressMenuItem(Context context) {
        return mInfoItem;
    }

    @Override
    public MenuItem getAppOpsMenuItem(Context context) {
        return mAppOpsItem;
    }

    @Override
    public MenuItem getSnoozeMenuItem(Context context) {
        return mSnoozeItem;
    }

    @VisibleForTesting
    protected ExpandableNotificationRow getParent() {
        return mParent;
    }

    @VisibleForTesting
    protected boolean isMenuOnLeft() {
        return mOnLeft;
    }

    @VisibleForTesting
    protected boolean isMenuSnappedOnLeft() {
        return mMenuSnappedOnLeft;
    }

    @VisibleForTesting
    protected boolean isMenuSnapped() {
        return mMenuSnapped;
    }

    @VisibleForTesting
    protected boolean isDismissing() {
        return mDismissing;
    }

    @VisibleForTesting
    protected boolean isSnapping() {
        return mSnapping;
    }

    @Override
    public void setMenuClickListener(OnMenuEventListener listener) {
        mMenuListener = listener;
    }

    @Override
    public void createMenu(ViewGroup parent, StatusBarNotification sbn) {
        mParent = (ExpandableNotificationRow) parent;
        createMenuViews(true /* resetState */,
                sbn != null && (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE)
                        != 0);
    }

    @Override
    public boolean isMenuVisible() {
        return mAlpha > 0;
    }

    @VisibleForTesting
    protected boolean isUserTouching() {
        return mIsUserTouching;
    }

    @Override
    public boolean shouldShowMenu() {
        return mShouldShowMenu;
    }

    @Override
    public View getMenuView() {
        return mMenuContainer;
    }

    @VisibleForTesting
    protected float getTranslation() {
        return mTranslation;
    }

    @Override
    public void resetMenu() {
        resetState(true);
    }

    @Override
    public void onTouchEnd() {
        mIsUserTouching = false;
    }

    @Override
    public void onNotificationUpdated(StatusBarNotification sbn) {
        if (mMenuContainer == null) {
            // Menu hasn't been created yet, no need to do anything.
            return;
        }
        createMenuViews(!isMenuVisible() /* resetState */,
                (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0);
    }

    @Override
    public void onConfigurationChanged() {
        mParent.setLayoutListener(this);
    }

    @Override
    public void onLayout() {
        mIconsPlaced = false; // Force icons to be re-placed
        setMenuLocation();
        mParent.removeListener();
    }

    private void createMenuViews(boolean resetState, final boolean isForeground) {
        mIsForeground = isForeground;

        final Resources res = mContext.getResources();
        mHorizSpaceForIcon = res.getDimensionPixelSize(R.dimen.notification_menu_icon_size);
        mVertSpaceForIcons = res.getDimensionPixelSize(R.dimen.notification_min_height);
        mLeftMenuItems.clear();
        mRightMenuItems.clear();

        boolean showSnooze = Settings.Secure.getInt(mContext.getContentResolver(),
                SHOW_NOTIFICATION_SNOOZE, 0) == 1;

        // Construct the menu items based on the notification
        if (!isForeground && showSnooze) {
            // Only show snooze for non-foreground notifications, and if the setting is on
            mSnoozeItem = createSnoozeItem(mContext);
        }
        mAppOpsItem = createAppOpsItem(mContext);
        if (mIsUsingBidirectionalSwipe) {
            mInfoItem = createInfoItem(mContext, !mParent.getEntry().isHighPriority());
        } else {
            mInfoItem = createInfoItem(mContext);
        }

        if (!mIsUsingBidirectionalSwipe) {
            if (!isForeground && showSnooze) {
                mRightMenuItems.add(mSnoozeItem);
            }
            mRightMenuItems.add(mInfoItem);
            mRightMenuItems.add(mAppOpsItem);
            mLeftMenuItems.addAll(mRightMenuItems);
        } else {
            ArrayList<MenuItem> menuItems = mDismissRtl ? mLeftMenuItems : mRightMenuItems;
            menuItems.add(mInfoItem);
        }

        populateMenuViews();
        if (resetState) {
            resetState(false /* notify */);
        } else {
            mIconsPlaced = false;
            setMenuLocation();
            if (!mIsUserTouching) {
                onSnapOpen();
            }
        }
    }

    private void populateMenuViews() {
        if (mMenuContainer != null) {
            mMenuContainer.removeAllViews();
            mMenuItemsByView.clear();
        } else {
            mMenuContainer = new FrameLayout(mContext);
        }
        List<MenuItem> menuItems = mOnLeft ? mLeftMenuItems : mRightMenuItems;
        for (int i = 0; i < menuItems.size(); i++) {
            addMenuView(menuItems.get(i), mMenuContainer);
        }
    }

    private void resetState(boolean notify) {
        setMenuAlpha(0f);
        mIconsPlaced = false;
        mMenuFadedIn = false;
        mAnimating = false;
        mSnapping = false;
        mDismissing = false;
        mMenuSnapped = false;
        setMenuLocation();
        if (mMenuListener != null && notify) {
            mMenuListener.onMenuReset(mParent);
        }
    }

    @Override
    public void onTouchMove(float delta) {
        mSnapping = false;

        if (!isTowardsMenu(delta) && isMenuLocationChange()) {
            // Don't consider it "snapped" if location has changed.
            mMenuSnapped = false;

            // Changed directions, make sure we check to fade in icon again.
            if (!mHandler.hasCallbacks(mCheckForDrag)) {
                // No check scheduled, set null to schedule a new one.
                mCheckForDrag = null;
            } else {
                // Check scheduled, reset alpha and update location; check will fade it in
                setMenuAlpha(0f);
                setMenuLocation();
            }
        }
        if (mShouldShowMenu
                && !NotificationStackScrollLayout.isPinnedHeadsUp(getParent())
                && !mParent.areGutsExposed()
                && !mParent.showingPulsing()
                && (mCheckForDrag == null || !mHandler.hasCallbacks(mCheckForDrag))) {
            // Only show the menu if we're not a heads up view and guts aren't exposed.
            mCheckForDrag = new CheckForDrag();
            mHandler.postDelayed(mCheckForDrag, SHOW_MENU_DELAY);
        }
    }

    @VisibleForTesting
    protected void beginDrag() {
        mSnapping = false;
        if (mFadeAnimator != null) {
            mFadeAnimator.cancel();
        }
        mHandler.removeCallbacks(mCheckForDrag);
        mCheckForDrag = null;
        mIsUserTouching = true;
    }

    @Override
    public void onTouchStart() {
       beginDrag();
    }

    @Override
    public void onSnapOpen() {
        mMenuSnapped = true;
        mMenuSnappedOnLeft = isMenuOnLeft();
        if (mAlpha == 0f && mParent != null) {
            fadeInMenu(mParent.getWidth());
        }
        if (mMenuListener != null) {
            mMenuListener.onMenuShown(getParent());
        }
    }

    @Override
    public void onSnapClosed() {
        cancelDrag();
        mMenuSnapped = false;
        mSnapping = true;
    }

    @Override
    public void onDismiss() {
        cancelDrag();
        mMenuSnapped = false;
        mDismissing = true;
    }

    @VisibleForTesting
    protected void cancelDrag() {
        if (mFadeAnimator != null) {
            mFadeAnimator.cancel();
        }
        mHandler.removeCallbacks(mCheckForDrag);
    }

    @VisibleForTesting
    protected float getMinimumSwipeDistance() {
        final float multiplier = getParent().canViewBeDismissed()
                ? SWIPED_FAR_ENOUGH_MENU_FRACTION
                : SWIPED_FAR_ENOUGH_MENU_UNCLEARABLE_FRACTION;
        return mHorizSpaceForIcon * multiplier;
    }

    @VisibleForTesting
    protected float getMaximumSwipeDistance() {
        return mHorizSpaceForIcon * SWIPED_BACK_ENOUGH_TO_COVER_FRACTION;
    }

    /**
     * Returns whether the gesture is towards the menu location or not.
     */
    @Override
    public boolean isTowardsMenu(float movement) {
        return isMenuVisible()
                && ((isMenuOnLeft() && movement <= 0)
                        || (!isMenuOnLeft() && movement >= 0));
    }

    @Override
    public void setAppName(String appName) {
        if (appName == null) {
            return;
        }
        setAppName(appName, mLeftMenuItems);
        setAppName(appName, mRightMenuItems);
    }

    private void setAppName(String appName,
            ArrayList<MenuItem> menuItems) {
        Resources res = mContext.getResources();
        final int count = menuItems.size();
        for (int i = 0; i < count; i++) {
            MenuItem item = menuItems.get(i);
            String description = String.format(
                    res.getString(R.string.notification_menu_accessibility),
                    appName, item.getContentDescription());
            View menuView = item.getMenuView();
            if (menuView != null) {
                menuView.setContentDescription(description);
            }
        }
    }

    @Override
    public void onParentHeightUpdate() {
        if (mParent == null
                || (mLeftMenuItems.isEmpty() && mRightMenuItems.isEmpty())
                || mMenuContainer == null) {
            return;
        }
        int parentHeight = mParent.getActualHeight();
        float translationY;
        if (parentHeight < mVertSpaceForIcons) {
            translationY = (parentHeight / 2) - (mHorizSpaceForIcon / 2);
        } else {
            translationY = (mVertSpaceForIcons - mHorizSpaceForIcon) / 2;
        }
        mMenuContainer.setTranslationY(translationY);
    }

    @Override
    public void onParentTranslationUpdate(float translation) {
        mTranslation = translation;
        if (mAnimating || !mMenuFadedIn) {
            // Don't adjust when animating, or if the menu hasn't been shown yet.
            return;
        }
        final float fadeThreshold = mParent.getWidth() * 0.3f;
        final float absTrans = Math.abs(translation);
        float desiredAlpha = 0;
        if (absTrans == 0) {
            desiredAlpha = 0;
        } else if (absTrans <= fadeThreshold) {
            desiredAlpha = 1;
        } else {
            desiredAlpha = 1 - ((absTrans - fadeThreshold) / (mParent.getWidth() - fadeThreshold));
        }
        setMenuAlpha(desiredAlpha);
    }

    @Override
    public void onClick(View v) {
        if (mMenuListener == null) {
            // Nothing to do
            return;
        }
        v.getLocationOnScreen(mIconLocation);
        mParent.getLocationOnScreen(mParentLocation);
        final int centerX = mHorizSpaceForIcon / 2;
        final int centerY = v.getHeight() / 2;
        final int x = mIconLocation[0] - mParentLocation[0] + centerX;
        final int y = mIconLocation[1] - mParentLocation[1] + centerY;
        if (mMenuItemsByView.containsKey(v)) {
            mMenuListener.onMenuClicked(mParent, x, y, mMenuItemsByView.get(v));
        }
    }

    private boolean isMenuLocationChange() {
        boolean onLeft = mTranslation > mIconPadding;
        boolean onRight = mTranslation < -mIconPadding;
        if ((isMenuOnLeft() && onRight) || (!isMenuOnLeft() && onLeft)) {
            return true;
        }
        return false;
    }

    private void setMenuLocation() {
        boolean showOnLeft = mTranslation > 0;
        if ((mIconsPlaced && showOnLeft == isMenuOnLeft()) || isSnapping() || mMenuContainer == null
                || !mMenuContainer.isAttachedToWindow()) {
            // Do nothing
            return;
        }
        boolean wasOnLeft = mOnLeft;
        mOnLeft = showOnLeft;
        if (wasOnLeft != showOnLeft) {
            populateMenuViews();
        }
        final int count = mMenuContainer.getChildCount();
        for (int i = 0; i < count; i++) {
            final View v = mMenuContainer.getChildAt(i);
            final float left = i * mHorizSpaceForIcon;
            final float right = mParent.getWidth() - (mHorizSpaceForIcon * (i + 1));
            v.setX(showOnLeft ? left : right);
        }
        mIconsPlaced = true;
    }

    @VisibleForTesting
    protected void setMenuAlpha(float alpha) {
        mAlpha = alpha;
        if (mMenuContainer == null) {
            return;
        }
        if (alpha == 0) {
            mMenuFadedIn = false; // Can fade in again once it's gone.
            mMenuContainer.setVisibility(View.INVISIBLE);
        } else {
            mMenuContainer.setVisibility(View.VISIBLE);
        }
        final int count = mMenuContainer.getChildCount();
        for (int i = 0; i < count; i++) {
            mMenuContainer.getChildAt(i).setAlpha(mAlpha);
        }
    }

    /**
     * Returns the horizontal space in pixels required to display the menu.
     */
    @VisibleForTesting
    protected int getSpaceForMenu() {
        return mHorizSpaceForIcon * mMenuContainer.getChildCount();
    }

    private final class CheckForDrag implements Runnable {
        @Override
        public void run() {
            final float absTransX = Math.abs(mTranslation);
            final float bounceBackToMenuWidth = getSpaceForMenu();
            final float notiThreshold = mParent.getWidth() * 0.4f;
            if ((!isMenuVisible() || isMenuLocationChange())
                    && absTransX >= bounceBackToMenuWidth * 0.4
                    && absTransX < notiThreshold) {
                fadeInMenu(notiThreshold);
            }
        }
    }

    private void fadeInMenu(final float notiThreshold) {
        if (mDismissing || mAnimating) {
            return;
        }
        if (isMenuLocationChange()) {
            setMenuAlpha(0f);
        }
        final float transX = mTranslation;
        final boolean fromLeft = mTranslation > 0;
        setMenuLocation();
        mFadeAnimator = ValueAnimator.ofFloat(mAlpha, 1);
        mFadeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                final float absTrans = Math.abs(transX);

                boolean pastMenu = (fromLeft && transX <= notiThreshold)
                        || (!fromLeft && absTrans <= notiThreshold);
                if (pastMenu && !mMenuFadedIn) {
                    setMenuAlpha((float) animation.getAnimatedValue());
                }
            }
        });
        mFadeAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                mAnimating = true;
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                // TODO should animate back to 0f from current alpha
                setMenuAlpha(0f);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                mAnimating = false;
                mMenuFadedIn = mAlpha == 1;
            }
        });
        mFadeAnimator.setInterpolator(Interpolators.ALPHA_IN);
        mFadeAnimator.setDuration(ICON_ALPHA_ANIM_DURATION);
        mFadeAnimator.start();
    }

    @Override
    public void setMenuItems(ArrayList<MenuItem> items) {
        // Do nothing we use our own for now.
        // TODO -- handle / allow custom menu items!
    }

    @Override
    public boolean shouldShowGutsOnSnapOpen() {
        return mIsUsingBidirectionalSwipe;
    }

    @Override
    public MenuItem menuItemToExposeOnSnap() {
        return mIsUsingBidirectionalSwipe ? mInfoItem : null;
    }

    @Override
    public Point getRevealAnimationOrigin() {
        View v = mInfoItem.getMenuView();
        int menuX = v.getLeft() + v.getPaddingLeft() + (v.getWidth() / 2);
        int menuY = v.getTop() + v.getPaddingTop() + (v.getHeight() / 2);
        if (isMenuOnLeft()) {
            return new Point(menuX, menuY);
        } else {
            menuX = mParent.getRight() - menuX;
            return new Point(menuX, menuY);
        }
    }

    static MenuItem createSnoozeItem(Context context) {
        Resources res = context.getResources();
        NotificationSnooze content = (NotificationSnooze) LayoutInflater.from(context)
                .inflate(R.layout.notification_snooze, null, false);
        String snoozeDescription = res.getString(R.string.notification_menu_snooze_description);
        MenuItem snooze = new NotificationMenuItem(context, snoozeDescription, content,
                R.drawable.ic_snooze);
        return snooze;
    }

    static NotificationMenuItem createInfoItem(Context context) {
        Resources res = context.getResources();
        String infoDescription = res.getString(R.string.notification_menu_gear_description);
        NotificationInfo infoContent = (NotificationInfo) LayoutInflater.from(context).inflate(
                R.layout.notification_info, null, false);
        return new NotificationMenuItem(context, infoDescription, infoContent,
                R.drawable.ic_settings);
    }

    static NotificationMenuItem createInfoItem(Context context, boolean isCurrentlySilent) {
        Resources res = context.getResources();
        String infoDescription = res.getString(R.string.notification_menu_gear_description);
        NotificationInfo infoContent = (NotificationInfo) LayoutInflater.from(context).inflate(
                R.layout.notification_info, null, false);
        int iconResId = isCurrentlySilent
                ? R.drawable.ic_notifications_silence
                : R.drawable.ic_notifications_alert;
        return new NotificationMenuItem(context, infoDescription, infoContent, iconResId);
    }

    static MenuItem createAppOpsItem(Context context) {
        AppOpsInfo appOpsContent = (AppOpsInfo) LayoutInflater.from(context).inflate(
                R.layout.app_ops_info, null, false);
        MenuItem info = new NotificationMenuItem(context, null, appOpsContent,
                -1 /*don't show in slow swipe menu */);
        return info;
    }

    private void addMenuView(MenuItem item, ViewGroup parent) {
        View menuView = item.getMenuView();
        if (menuView != null) {
            menuView.setAlpha(mAlpha);
            parent.addView(menuView);
            menuView.setOnClickListener(this);
            FrameLayout.LayoutParams lp = (LayoutParams) menuView.getLayoutParams();
            lp.width = mHorizSpaceForIcon;
            lp.height = mHorizSpaceForIcon;
            menuView.setLayoutParams(lp);
        }
        mMenuItemsByView.put(menuView, item);
    }

    @VisibleForTesting
    /**
     * Determine the minimum offset below which the menu should snap back closed.
     */
    protected float getSnapBackThreshold() {
        return getSpaceForMenu() - getMaximumSwipeDistance();
    }

    /**
     * Determine the maximum offset above which the parent notification should be dismissed.
     * @return
     */
    @VisibleForTesting
    protected float getDismissThreshold() {
        return getParent().getWidth() * SWIPED_FAR_ENOUGH_SIZE_FRACTION;
    }

    @Override
    public boolean isWithinSnapMenuThreshold() {
        float translation = getTranslation();
        float snapBackThreshold = getSnapBackThreshold();
        float targetRight = getDismissThreshold();
        return isMenuOnLeft()
                ? translation > snapBackThreshold && translation < targetRight
                : translation < -snapBackThreshold && translation > -targetRight;
    }

    @Override
    public boolean isSwipedEnoughToShowMenu() {
        final float minimumSwipeDistance = getMinimumSwipeDistance();
        final float translation = getTranslation();
        return isMenuVisible() && (isMenuOnLeft() ?
                translation > minimumSwipeDistance
                : translation < -minimumSwipeDistance);
    }

    @Override
    public int getMenuSnapTarget() {
        return isMenuOnLeft() ? getSpaceForMenu() : -getSpaceForMenu();
    }

    @Override
    public boolean shouldSnapBack() {
        float translation = getTranslation();
        float targetLeft = getSnapBackThreshold();
        return isMenuOnLeft() ? translation < targetLeft : translation > -targetLeft;
    }

    @Override
    public boolean isSnappedAndOnSameSide() {
        return isMenuSnapped() && isMenuVisible()
                && isMenuSnappedOnLeft() == isMenuOnLeft();
    }

    @Override
    public boolean canBeDismissed() {
        return getParent().canViewBeDismissed();
    }

    @Override
    public void setDismissRtl(boolean dismissRtl) {
        mDismissRtl = dismissRtl;
        if (mMenuContainer != null) {
            createMenuViews(true, mIsForeground);
        }
    }

    public static class NotificationMenuItem implements MenuItem {
        View mMenuView;
        GutsContent mGutsContent;
        String mContentDescription;

        /**
         * Add a new 'guts' panel. If iconResId < 0 it will not appear in the slow swipe menu
         * but can still be exposed via other affordances.
         */
        public NotificationMenuItem(Context context, String contentDescription, GutsContent content,
                int iconResId) {
            Resources res = context.getResources();
            int padding = res.getDimensionPixelSize(R.dimen.notification_menu_icon_padding);
            int tint = res.getColor(R.color.notification_gear_color);
            if (iconResId >= 0) {
                AlphaOptimizedImageView iv = new AlphaOptimizedImageView(context);
                iv.setPadding(padding, padding, padding, padding);
                Drawable icon = context.getResources().getDrawable(iconResId);
                iv.setImageDrawable(icon);
                iv.setColorFilter(tint);
                iv.setAlpha(1f);
                mMenuView = iv;
            }
            mContentDescription = contentDescription;
            mGutsContent = content;
        }

        @Override
        @Nullable
        public View getMenuView() {
            return mMenuView;
        }

        @Override
        public View getGutsView() {
            return mGutsContent.getContentView();
        }

        @Override
        public String getContentDescription() {
            return mContentDescription;
        }
    }
}
