/*
 * Copyright (C) 2015 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.internal.widget;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.drawable.ColorDrawable;
import android.text.TextUtils;
import android.util.Size;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.Transformation;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;

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

import com.android.internal.R;
import com.android.internal.util.Preconditions;

/**
 * A floating toolbar for showing contextual menu items.
 * This view shows as many menu item buttons as can fit in the horizontal toolbar and the
 * the remaining menu items in a vertical overflow view when the overflow button is clicked.
 * The horizontal toolbar morphs into the vertical overflow view.
 */
public final class FloatingToolbar {

    // This class is responsible for the public API of the floating toolbar.
    // It delegates rendering operations to the FloatingToolbarPopup.

    private static final MenuItem.OnMenuItemClickListener NO_OP_MENUITEM_CLICK_LISTENER =
            new MenuItem.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    return false;
                }
            };

    private final Context mContext;
    private final FloatingToolbarPopup mPopup;

    private final Rect mContentRect = new Rect();
    private final Rect mPreviousContentRect = new Rect();

    private Menu mMenu;
    private List<Object> mShowingMenuItems = new ArrayList<Object>();
    private MenuItem.OnMenuItemClickListener mMenuItemClickListener = NO_OP_MENUITEM_CLICK_LISTENER;

    private int mSuggestedWidth;
    private boolean mWidthChanged = true;

    private final ComponentCallbacks mOrientationChangeHandler = new ComponentCallbacks() {
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            if (mPopup.isShowing() && mPopup.viewPortHasChanged()) {
                mWidthChanged = true;
                updateLayout();
            }
        }

        @Override
        public void onLowMemory() {}
    };

    /**
     * Initializes a floating toolbar.
     */
    public FloatingToolbar(Context context, Window window) {
        Preconditions.checkNotNull(context);
        Preconditions.checkNotNull(window);
        mContext = applyDefaultTheme(context);
        mPopup = new FloatingToolbarPopup(mContext, window.getDecorView());
    }

    /**
     * Sets the menu to be shown in this floating toolbar.
     * NOTE: Call {@link #updateLayout()} or {@link #show()} to effect visual changes to the
     * toolbar.
     */
    public FloatingToolbar setMenu(Menu menu) {
        mMenu = Preconditions.checkNotNull(menu);
        return this;
    }

    /**
     * Sets the custom listener for invocation of menu items in this floating toolbar.
     */
    public FloatingToolbar setOnMenuItemClickListener(
            MenuItem.OnMenuItemClickListener menuItemClickListener) {
        if (menuItemClickListener != null) {
            mMenuItemClickListener = menuItemClickListener;
        } else {
            mMenuItemClickListener = NO_OP_MENUITEM_CLICK_LISTENER;
        }
        return this;
    }

    /**
     * Sets the content rectangle. This is the area of the interesting content that this toolbar
     * should avoid obstructing.
     * NOTE: Call {@link #updateLayout()} or {@link #show()} to effect visual changes to the
     * toolbar.
     */
    public FloatingToolbar setContentRect(Rect rect) {
        mContentRect.set(Preconditions.checkNotNull(rect));
        return this;
    }

    /**
     * Sets the suggested width of this floating toolbar.
     * The actual width will be about this size but there are no guarantees that it will be exactly
     * the suggested width.
     * NOTE: Call {@link #updateLayout()} or {@link #show()} to effect visual changes to the
     * toolbar.
     */
    public FloatingToolbar setSuggestedWidth(int suggestedWidth) {
        // Check if there's been a substantial width spec change.
        int difference = Math.abs(suggestedWidth - mSuggestedWidth);
        mWidthChanged = difference > (mSuggestedWidth * 0.2);

        mSuggestedWidth = suggestedWidth;
        return this;
    }

    /**
     * Shows this floating toolbar.
     */
    public FloatingToolbar show() {
        mContext.unregisterComponentCallbacks(mOrientationChangeHandler);
        mContext.registerComponentCallbacks(mOrientationChangeHandler);
        List<MenuItem> menuItems = getVisibleAndEnabledMenuItems(mMenu);
        if (!isCurrentlyShowing(menuItems) || mWidthChanged) {
            mPopup.dismiss();
            mPopup.layoutMenuItems(menuItems, mMenuItemClickListener, mSuggestedWidth);
            mShowingMenuItems = getShowingMenuItemsReferences(menuItems);
        }
        if (!mPopup.isShowing()) {
            mPopup.show(mContentRect);
        } else if (!mPreviousContentRect.equals(mContentRect)) {
            mPopup.updateCoordinates(mContentRect);
        }
        mWidthChanged = false;
        mPreviousContentRect.set(mContentRect);
        return this;
    }

    /**
     * Updates this floating toolbar to reflect recent position and view updates.
     * NOTE: This method is a no-op if the toolbar isn't showing.
     */
    public FloatingToolbar updateLayout() {
        if (mPopup.isShowing()) {
            // show() performs all the logic we need here.
            show();
        }
        return this;
    }

    /**
     * Dismisses this floating toolbar.
     */
    public void dismiss() {
        mContext.unregisterComponentCallbacks(mOrientationChangeHandler);
        mPopup.dismiss();
    }

    /**
     * Hides this floating toolbar. This is a no-op if the toolbar is not showing.
     * Use {@link #isHidden()} to distinguish between a hidden and a dismissed toolbar.
     */
    public void hide() {
        mPopup.hide();
    }

    /**
     * Returns {@code true} if this toolbar is currently showing. {@code false} otherwise.
     */
    public boolean isShowing() {
        return mPopup.isShowing();
    }

    /**
     * Returns {@code true} if this toolbar is currently hidden. {@code false} otherwise.
     */
    public boolean isHidden() {
        return mPopup.isHidden();
    }

    /**
     * Returns true if this floating toolbar is currently showing the specified menu items.
     */
    private boolean isCurrentlyShowing(List<MenuItem> menuItems) {
        return mShowingMenuItems.equals(getShowingMenuItemsReferences(menuItems));
    }

    /**
     * Returns the visible and enabled menu items in the specified menu.
     * This method is recursive.
     */
    private List<MenuItem> getVisibleAndEnabledMenuItems(Menu menu) {
        List<MenuItem> menuItems = new ArrayList<MenuItem>();
        for (int i = 0; (menu != null) && (i < menu.size()); i++) {
            MenuItem menuItem = menu.getItem(i);
            if (menuItem.isVisible() && menuItem.isEnabled()) {
                Menu subMenu = menuItem.getSubMenu();
                if (subMenu != null) {
                    menuItems.addAll(getVisibleAndEnabledMenuItems(subMenu));
                } else {
                    menuItems.add(menuItem);
                }
            }
        }
        return menuItems;
    }

    private List<Object> getShowingMenuItemsReferences(List<MenuItem> menuItems) {
        List<Object> references = new ArrayList<Object>();
        for (MenuItem menuItem : menuItems) {
            if (isIconOnlyMenuItem(menuItem)) {
                references.add(menuItem.getIcon());
            } else {
                references.add(menuItem.getTitle());
            }
        }
        return references;
    }


    /**
     * A popup window used by the floating toolbar.
     *
     * This class is responsible for the rendering/animation of the floating toolbar.
     * It can hold one of 2 panels (i.e. main panel and overflow panel) at a time.
     * It delegates specific panel functionality to the appropriate panel.
     */
    private static final class FloatingToolbarPopup {

        public static final int OVERFLOW_DIRECTION_UP = 0;
        public static final int OVERFLOW_DIRECTION_DOWN = 1;

        private final Context mContext;
        private final View mParent;
        private final PopupWindow mPopupWindow;
        private final ViewGroup mContentContainer;
        private final int mMarginHorizontal;
        private final int mMarginVertical;

        private final Animation.AnimationListener mOnOverflowOpened =
                new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {}

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        setOverflowPanelAsContent();
                        mOverflowPanel.fadeIn(true);
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {}
                };
        private final Animation.AnimationListener mOnOverflowClosed =
                new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {}

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        setMainPanelAsContent();
                        mMainPanel.fadeIn(true);
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {
                    }
                };
        private final AnimatorSet mDismissAnimation;
        private final AnimatorSet mHideAnimation;
        private final AnimationSet mOpenOverflowAnimation = new AnimationSet(true);
        private final AnimationSet mCloseOverflowAnimation = new AnimationSet(true);

        private final Runnable mOpenOverflow = new Runnable() {
            @Override
            public void run() {
                openOverflow();
            }
        };
        private final Runnable mCloseOverflow = new Runnable() {
            @Override
            public void run() {
                closeOverflow();
            }
        };

        private final Rect mViewPort = new Rect();
        private final Point mCoords = new Point();
        private final Rect mTmpRect = new Rect();

        private final Region mTouchableRegion = new Region();
        private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer =
                new ViewTreeObserver.OnComputeInternalInsetsListener() {
                    public void onComputeInternalInsets(
                            ViewTreeObserver.InternalInsetsInfo info) {
                        info.contentInsets.setEmpty();
                        info.visibleInsets.setEmpty();
                        info.touchableRegion.set(mTouchableRegion);
                        info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo
                                .TOUCHABLE_INSETS_REGION);
                    }
                };

        private boolean mDismissed = true; // tracks whether this popup is dismissed or dismissing.
        private boolean mHidden; // tracks whether this popup is hidden or hiding.

        private FloatingToolbarOverflowPanel mOverflowPanel;
        private FloatingToolbarMainPanel mMainPanel;
        private int mOverflowDirection;

        /**
         * Initializes a new floating toolbar popup.
         *
         * @param parent  A parent view to get the {@link android.view.View#getWindowToken()} token
         *      from.
         */
        public FloatingToolbarPopup(Context context, View parent) {
            mParent = Preconditions.checkNotNull(parent);
            mContext = Preconditions.checkNotNull(context);
            mContentContainer = createContentContainer(context);
            mPopupWindow = createPopupWindow(mContentContainer);
            mDismissAnimation = createExitAnimation(
                    mContentContainer,
                    150,  // startDelay
                    new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            mPopupWindow.dismiss();
                            mContentContainer.removeAllViews();
                        }
                    });
            mHideAnimation = createExitAnimation(
                    mContentContainer,
                    0,  // startDelay
                    new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            mPopupWindow.dismiss();
                        }
                    });
            mMarginHorizontal = parent.getResources()
                    .getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin);
            mMarginVertical = parent.getResources()
                    .getDimensionPixelSize(R.dimen.floating_toolbar_vertical_margin);
        }

        /**
         * Lays out buttons for the specified menu items.
         */
        public void layoutMenuItems(
                List<MenuItem> menuItems,
                MenuItem.OnMenuItemClickListener menuItemClickListener,
                int suggestedWidth) {
            Preconditions.checkNotNull(menuItems);

            mContentContainer.removeAllViews();
            if (mMainPanel == null) {
                mMainPanel = new FloatingToolbarMainPanel(mContext, mOpenOverflow);
            }
            List<MenuItem> overflowMenuItems =
                    mMainPanel.layoutMenuItems(menuItems, getToolbarWidth(suggestedWidth));
            mMainPanel.setOnMenuItemClickListener(menuItemClickListener);
            if (!overflowMenuItems.isEmpty()) {
                if (mOverflowPanel == null) {
                    mOverflowPanel =
                            new FloatingToolbarOverflowPanel(mContext, mCloseOverflow);
                }
                mOverflowPanel.setMenuItems(overflowMenuItems);
                mOverflowPanel.setOnMenuItemClickListener(menuItemClickListener);
            }
            updatePopupSize();
        }

        /**
         * Shows this popup at the specified coordinates.
         * The specified coordinates may be adjusted to make sure the popup is entirely on-screen.
         */
        public void show(Rect contentRect) {
            Preconditions.checkNotNull(contentRect);

            if (isShowing()) {
                return;
            }

            mHidden = false;
            mDismissed = false;
            cancelDismissAndHideAnimations();
            cancelOverflowAnimations();

            // Make sure a panel is set as the content.
            if (mContentContainer.getChildCount() == 0) {
                setMainPanelAsContent();
                // If we're yet to show the popup, set the container visibility to zero.
                // The "show" animation will make this visible.
                mContentContainer.setAlpha(0);
            }
            refreshCoordinatesAndOverflowDirection(contentRect);
            preparePopupContent();
            mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, mCoords.x, mCoords.y);
            setTouchableSurfaceInsetsComputer();
            runShowAnimation();
        }

        /**
         * Gets rid of this popup. If the popup isn't currently showing, this will be a no-op.
         */
        public void dismiss() {
            if (mDismissed) {
                return;
            }

            mHidden = false;
            mDismissed = true;
            mHideAnimation.cancel();
            runDismissAnimation();
            setZeroTouchableSurface();
        }

        /**
         * Hides this popup. This is a no-op if this popup is not showing.
         * Use {@link #isHidden()} to distinguish between a hidden and a dismissed popup.
         */
        public void hide() {
            if (!isShowing()) {
                return;
            }

            mHidden = true;
            runHideAnimation();
            setZeroTouchableSurface();
        }

        /**
         * Returns {@code true} if this popup is currently showing. {@code false} otherwise.
         */
        public boolean isShowing() {
            return !mDismissed && !mHidden;
        }

        /**
         * Returns {@code true} if this popup is currently hidden. {@code false} otherwise.
         */
        public boolean isHidden() {
            return mHidden;
        }

        /**
         * Updates the coordinates of this popup.
         * The specified coordinates may be adjusted to make sure the popup is entirely on-screen.
         * This is a no-op if this popup is not showing.
         */
        public void updateCoordinates(Rect contentRect) {
            Preconditions.checkNotNull(contentRect);

            if (!isShowing() || !mPopupWindow.isShowing()) {
                return;
            }

            cancelOverflowAnimations();
            refreshCoordinatesAndOverflowDirection(contentRect);
            preparePopupContent();
            mPopupWindow.update(mCoords.x, mCoords.y, getWidth(), getHeight());
        }

        /**
         * Returns the width of this popup.
         */
        public int getWidth() {
            return mPopupWindow.getWidth();
        }

        /**
         * Returns the height of this popup.
         */
        public int getHeight() {
            return mPopupWindow.getHeight();
        }

        /**
         * Returns the context this popup is running in.
         */
        public Context getContext() {
            return mContext;
        }

        private void refreshCoordinatesAndOverflowDirection(Rect contentRect) {
            refreshViewPort();

            int x = contentRect.centerX() - getWidth() / 2;
            // Update x so that the toolbar isn't rendered behind the nav bar in landscape.
            x = Math.max(0, Math.min(x, mViewPort.right - getWidth()));

            int y;

            int availableHeightAboveContent = contentRect.top - mViewPort.top;
            int availableHeightBelowContent = mViewPort.bottom - contentRect.bottom;

            if (mOverflowPanel == null) {  // There is no overflow.
                if (availableHeightAboveContent >= getToolbarHeightWithVerticalMargin()) {
                    // There is enough space at the top of the content.
                    y = contentRect.top - getToolbarHeightWithVerticalMargin();
                } else if (availableHeightBelowContent >= getToolbarHeightWithVerticalMargin()) {
                    // There is enough space at the bottom of the content.
                    y = contentRect.bottom;
                } else if (availableHeightBelowContent >= getEstimatedToolbarHeight(mContext)) {
                    // Just enough space to fit the toolbar with no vertical margins.
                    y = contentRect.bottom - mMarginVertical;
                } else {
                    // Not enough space. Prefer to position as high as possible.
                    y = Math.max(
                            mViewPort.top,
                            contentRect.top - getToolbarHeightWithVerticalMargin());
                }
            } else {  // There is an overflow.
                int margin = 2 * mMarginVertical;
                int minimumOverflowHeightWithMargin = mOverflowPanel.getMinimumHeight() + margin;
                int availableHeightThroughContentDown =
                        mViewPort.bottom - contentRect.top + getToolbarHeightWithVerticalMargin();
                int availableHeightThroughContentUp =
                        contentRect.bottom - mViewPort.top + getToolbarHeightWithVerticalMargin();

                if (availableHeightAboveContent >= minimumOverflowHeightWithMargin) {
                    // There is enough space at the top of the content rect for the overflow.
                    // Position above and open upwards.
                    updateOverflowHeight(availableHeightAboveContent - margin);
                    y = contentRect.top - getHeight();
                    mOverflowDirection = OVERFLOW_DIRECTION_UP;
                } else if (availableHeightAboveContent >= getToolbarHeightWithVerticalMargin()
                        && availableHeightThroughContentDown >= minimumOverflowHeightWithMargin) {
                    // There is enough space at the top of the content rect for the main panel
                    // but not the overflow.
                    // Position above but open downwards.
                    updateOverflowHeight(availableHeightThroughContentDown - margin);
                    y = contentRect.top - getToolbarHeightWithVerticalMargin();
                    mOverflowDirection = OVERFLOW_DIRECTION_DOWN;
                } else if (availableHeightBelowContent >= minimumOverflowHeightWithMargin) {
                    // There is enough space at the bottom of the content rect for the overflow.
                    // Position below and open downwards.
                    updateOverflowHeight(availableHeightBelowContent - margin);
                    y = contentRect.bottom;
                    mOverflowDirection = OVERFLOW_DIRECTION_DOWN;
                } else if (availableHeightBelowContent >= getToolbarHeightWithVerticalMargin()
                        && mViewPort.height() >= minimumOverflowHeightWithMargin) {
                    // There is enough space at the bottom of the content rect for the main panel
                    // but not the overflow.
                    // Position below but open upwards.
                    updateOverflowHeight(availableHeightThroughContentUp - margin);
                    y = contentRect.bottom + getToolbarHeightWithVerticalMargin() - getHeight();
                    mOverflowDirection = OVERFLOW_DIRECTION_UP;
                } else {
                    // Not enough space.
                    // Position at the top of the view port and open downwards.
                    updateOverflowHeight(mViewPort.height() - margin);
                    y = mViewPort.top;
                    mOverflowDirection = OVERFLOW_DIRECTION_DOWN;
                }
                mOverflowPanel.setOverflowDirection(mOverflowDirection);
            }

            mCoords.set(x, y);
        }

        private int getToolbarHeightWithVerticalMargin() {
            return getEstimatedToolbarHeight(mContext) + mMarginVertical * 2;
        }

        /**
         * Performs the "show" animation on the floating popup.
         */
        private void runShowAnimation() {
            createEnterAnimation(mContentContainer).start();
        }

        /**
         * Performs the "dismiss" animation on the floating popup.
         */
        private void runDismissAnimation() {
            mDismissAnimation.start();
        }

        /**
         * Performs the "hide" animation on the floating popup.
         */
        private void runHideAnimation() {
            mHideAnimation.start();
        }

        private void cancelDismissAndHideAnimations() {
            mDismissAnimation.cancel();
            mHideAnimation.cancel();
        }

        private void cancelOverflowAnimations() {
            if (mOpenOverflowAnimation.hasStarted()
                    && !mOpenOverflowAnimation.hasEnded()) {
                // Remove the animation listener, stop the animation,
                // then trigger the lister explicitly so it is not posted
                // to the message queue.
                mOpenOverflowAnimation.setAnimationListener(null);
                mContentContainer.clearAnimation();
                mOnOverflowOpened.onAnimationEnd(null);
            }
            if (mCloseOverflowAnimation.hasStarted()
                    && !mCloseOverflowAnimation.hasEnded()) {
                // Remove the animation listener, stop the animation,
                // then trigger the lister explicitly so it is not posted
                // to the message queue.
                mCloseOverflowAnimation.setAnimationListener(null);
                mContentContainer.clearAnimation();
                mOnOverflowClosed.onAnimationEnd(null);
            }
        }

        /**
         * Opens the floating toolbar overflow.
         * This method should not be called if menu items have not been laid out with
         * {@link #layoutMenuItems(java.util.List, MenuItem.OnMenuItemClickListener, int)}.
         *
         * @throws IllegalStateException if called when menu items have not been laid out.
         */
        private void openOverflow() {
            Preconditions.checkState(mMainPanel != null);
            Preconditions.checkState(mOverflowPanel != null);

            mMainPanel.fadeOut(true);
            Size overflowPanelSize = mOverflowPanel.measure();
            final int targetWidth = overflowPanelSize.getWidth();
            final int targetHeight = overflowPanelSize.getHeight();
            final boolean morphUpwards = (mOverflowDirection == OVERFLOW_DIRECTION_UP);
            final int startWidth = mContentContainer.getWidth();
            final int startHeight = mContentContainer.getHeight();
            final float startY = mContentContainer.getY();
            final float left = mContentContainer.getX();
            final float right = left + mContentContainer.getWidth();
            Animation widthAnimation = new Animation() {
                @Override
                protected void applyTransformation(float interpolatedTime, Transformation t) {
                    ViewGroup.LayoutParams params = mContentContainer.getLayoutParams();
                    int deltaWidth = (int) (interpolatedTime * (targetWidth - startWidth));
                    params.width = startWidth + deltaWidth;
                    mContentContainer.setLayoutParams(params);
                    if (isRTL()) {
                        mContentContainer.setX(left);
                    } else {
                        mContentContainer.setX(right - mContentContainer.getWidth());
                    }
                }
            };
            Animation heightAnimation = new Animation() {
                @Override
                protected void applyTransformation(float interpolatedTime, Transformation t) {
                    ViewGroup.LayoutParams params = mContentContainer.getLayoutParams();
                    int deltaHeight = (int) (interpolatedTime * (targetHeight - startHeight));
                    params.height = startHeight + deltaHeight;
                    mContentContainer.setLayoutParams(params);
                    if (morphUpwards) {
                        float y = startY - (mContentContainer.getHeight() - startHeight);
                        mContentContainer.setY(y);
                    }
                }
            };
            widthAnimation.setDuration(240);
            heightAnimation.setDuration(180);
            heightAnimation.setStartOffset(60);
            mOpenOverflowAnimation.getAnimations().clear();
            mOpenOverflowAnimation.setAnimationListener(mOnOverflowOpened);
            mOpenOverflowAnimation.addAnimation(widthAnimation);
            mOpenOverflowAnimation.addAnimation(heightAnimation);
            mContentContainer.startAnimation(mOpenOverflowAnimation);
        }

        /**
         * Opens the floating toolbar overflow.
         * This method should not be called if menu items have not been laid out with
         * {@link #layoutMenuItems(java.util.List, MenuItem.OnMenuItemClickListener, int)}.
         *
         * @throws IllegalStateException if called when menu items have not been laid out.
         */
        private void closeOverflow() {
            Preconditions.checkState(mMainPanel != null);
            Preconditions.checkState(mOverflowPanel != null);

            mOverflowPanel.fadeOut(true);
            Size mainPanelSize = mMainPanel.measure();
            final int targetWidth = mainPanelSize.getWidth();
            final int targetHeight = mainPanelSize.getHeight();
            final int startWidth = mContentContainer.getWidth();
            final int startHeight = mContentContainer.getHeight();
            final float bottom = mContentContainer.getY() + mContentContainer.getHeight();
            final boolean morphedUpwards = (mOverflowDirection == OVERFLOW_DIRECTION_UP);
            final float left = mContentContainer.getX();
            final float right = left + mContentContainer.getWidth();
            Animation widthAnimation = new Animation() {
                @Override
                protected void applyTransformation(float interpolatedTime, Transformation t) {
                    ViewGroup.LayoutParams params = mContentContainer.getLayoutParams();
                    int deltaWidth = (int) (interpolatedTime * (targetWidth - startWidth));
                    params.width = startWidth + deltaWidth;
                    mContentContainer.setLayoutParams(params);
                    if (isRTL()) {
                        mContentContainer.setX(left);
                    } else {
                        mContentContainer.setX(right - mContentContainer.getWidth());
                    }
                }
            };
            Animation heightAnimation = new Animation() {
                @Override
                protected void applyTransformation(float interpolatedTime, Transformation t) {
                    ViewGroup.LayoutParams params = mContentContainer.getLayoutParams();
                    int deltaHeight = (int) (interpolatedTime * (targetHeight - startHeight));
                    params.height = startHeight + deltaHeight;
                    mContentContainer.setLayoutParams(params);
                    if (morphedUpwards) {
                        mContentContainer.setY(bottom - mContentContainer.getHeight());
                    }
                }
            };
            widthAnimation.setDuration(150);
            widthAnimation.setStartOffset(150);
            heightAnimation.setDuration(210);
            mCloseOverflowAnimation.getAnimations().clear();
            mCloseOverflowAnimation.setAnimationListener(mOnOverflowClosed);
            mCloseOverflowAnimation.addAnimation(widthAnimation);
            mCloseOverflowAnimation.addAnimation(heightAnimation);
            mContentContainer.startAnimation(mCloseOverflowAnimation);
        }

        /**
         * Prepares the content container for show and update calls.
         */
        private void preparePopupContent() {
            // Reset visibility.
            if (mMainPanel != null) {
                mMainPanel.fadeIn(false);
            }
            if (mOverflowPanel != null) {
                mOverflowPanel.fadeIn(false);
            }

            // Reset position.
            if (isMainPanelContent()) {
                positionMainPanel();
            }
            if (isOverflowPanelContent()) {
                positionOverflowPanel();
            }
        }

        private boolean isMainPanelContent() {
            return mMainPanel != null
                    && mContentContainer.getChildAt(0) == mMainPanel.getView();
        }

        private boolean isOverflowPanelContent() {
            return mOverflowPanel != null
                    && mContentContainer.getChildAt(0) == mOverflowPanel.getView();
        }

        /**
         * Sets the current content to be the main view panel.
         */
        private void setMainPanelAsContent() {
            // This should never be called if the main panel has not been initialized.
            Preconditions.checkNotNull(mMainPanel);
            mContentContainer.removeAllViews();
            Size mainPanelSize = mMainPanel.measure();
            ViewGroup.LayoutParams params = mContentContainer.getLayoutParams();
            params.width = mainPanelSize.getWidth();
            params.height = mainPanelSize.getHeight();
            mContentContainer.setLayoutParams(params);
            mContentContainer.addView(mMainPanel.getView());
            setContentAreaAsTouchableSurface();
        }

        /**
         * Sets the current content to be the overflow view panel.
         */
        private void setOverflowPanelAsContent() {
            // This should never be called if the overflow panel has not been initialized.
            Preconditions.checkNotNull(mOverflowPanel);
            mContentContainer.removeAllViews();
            Size overflowPanelSize = mOverflowPanel.measure();
            ViewGroup.LayoutParams params = mContentContainer.getLayoutParams();
            params.width = overflowPanelSize.getWidth();
            params.height = overflowPanelSize.getHeight();
            mContentContainer.setLayoutParams(params);
            mContentContainer.addView(mOverflowPanel.getView());
            setContentAreaAsTouchableSurface();
        }

        /**
         * Places the main view panel at the appropriate resting coordinates.
         */
        private void positionMainPanel() {
            Preconditions.checkNotNull(mMainPanel);
            mContentContainer.setX(mMarginHorizontal);

            float y = mMarginVertical;
            if  (mOverflowDirection == OVERFLOW_DIRECTION_UP) {
                y = getHeight()
                        - (mMainPanel.getView().getMeasuredHeight() + mMarginVertical);
            }
            mContentContainer.setY(y);
            setContentAreaAsTouchableSurface();
        }

        /**
         * Places the main view panel at the appropriate resting coordinates.
         */
        private void positionOverflowPanel() {
            Preconditions.checkNotNull(mOverflowPanel);
            float x;
            if (isRTL()) {
                x = mMarginHorizontal;
            } else {
                x = mPopupWindow.getWidth()
                    - (mOverflowPanel.getView().getMeasuredWidth() + mMarginHorizontal);
            }
            mContentContainer.setX(x);
            mContentContainer.setY(mMarginVertical);
            setContentAreaAsTouchableSurface();
        }

        private void updateOverflowHeight(int height) {
            if (mOverflowPanel != null) {
                mOverflowPanel.setSuggestedHeight(height);

                // Re-measure the popup and it's contents.
                boolean mainPanelContent = isMainPanelContent();
                boolean overflowPanelContent = isOverflowPanelContent();
                mContentContainer.removeAllViews();  // required to update popup size.
                updatePopupSize();
                // Reset the appropriate content.
                if (mainPanelContent) {
                    setMainPanelAsContent();
                }
                if (overflowPanelContent) {
                    setOverflowPanelAsContent();
                }
            }
        }

        private void updatePopupSize() {
            int width = 0;
            int height = 0;
            if (mMainPanel != null) {
                Size mainPanelSize = mMainPanel.measure();
                width = mainPanelSize.getWidth();
                height = mainPanelSize.getHeight();
            }
            if (mOverflowPanel != null) {
                Size overflowPanelSize = mOverflowPanel.measure();
                width = Math.max(width, overflowPanelSize.getWidth());
                height = Math.max(height, overflowPanelSize.getHeight());
            }
            mPopupWindow.setWidth(width + mMarginHorizontal * 2);
            mPopupWindow.setHeight(height + mMarginVertical * 2);
        }


        private void refreshViewPort() {
            mParent.getWindowVisibleDisplayFrame(mViewPort);
        }

        private boolean viewPortHasChanged() {
            mParent.getWindowVisibleDisplayFrame(mTmpRect);
            return !mTmpRect.equals(mViewPort);
        }

        private int getToolbarWidth(int suggestedWidth) {
            int width = suggestedWidth;
            refreshViewPort();
            int maximumWidth = mViewPort.width() - 2 * mParent.getResources()
                    .getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin);
            if (width <= 0) {
                width = mParent.getResources()
                        .getDimensionPixelSize(R.dimen.floating_toolbar_preferred_width);
            }
            return Math.min(width, maximumWidth);
        }

        /**
         * Sets the touchable region of this popup to be zero. This means that all touch events on
         * this popup will go through to the surface behind it.
         */
        private void setZeroTouchableSurface() {
            mTouchableRegion.setEmpty();
        }

        /**
         * Sets the touchable region of this popup to be the area occupied by its content.
         */
        private void setContentAreaAsTouchableSurface() {
            if (!mPopupWindow.isShowing()) {
                mContentContainer.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
            }
            int width = mContentContainer.getMeasuredWidth();
            int height = mContentContainer.getMeasuredHeight();
            mTouchableRegion.set(
                    (int) mContentContainer.getX(),
                    (int) mContentContainer.getY(),
                    (int) mContentContainer.getX() + width,
                    (int) mContentContainer.getY() + height);
        }

        /**
         * Make the touchable area of this popup be the area specified by mTouchableRegion.
         * This should be called after the popup window has been dismissed (dismiss/hide)
         * and is probably being re-shown with a new content root view.
         */
        private void setTouchableSurfaceInsetsComputer() {
            ViewTreeObserver viewTreeObserver = mPopupWindow.getContentView()
                    .getRootView()
                    .getViewTreeObserver();
            viewTreeObserver.removeOnComputeInternalInsetsListener(mInsetsComputer);
            viewTreeObserver.addOnComputeInternalInsetsListener(mInsetsComputer);
        }

        private boolean isRTL() {
            return mContentContainer.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
        }
    }

    /**
     * A widget that holds the primary menu items in the floating toolbar.
     */
    private static final class FloatingToolbarMainPanel {

        private final Context mContext;
        private final ViewGroup mContentView;
        private final View.OnClickListener mMenuItemButtonOnClickListener =
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (v.getTag() instanceof MenuItem) {
                            if (mOnMenuItemClickListener != null) {
                                mOnMenuItemClickListener.onMenuItemClick((MenuItem) v.getTag());
                            }
                        }
                    }
                };
        private final ViewFader viewFader;
        private final Runnable mOpenOverflow;

        private View mOpenOverflowButton;
        private MenuItem.OnMenuItemClickListener mOnMenuItemClickListener;

        /**
         * Initializes a floating toolbar popup main view panel.
         *
         * @param context
         * @param openOverflow  The code that opens the toolbar popup overflow.
         */
        public FloatingToolbarMainPanel(Context context, Runnable openOverflow) {
            mContext = Preconditions.checkNotNull(context);
            mContentView = new LinearLayout(context);
            viewFader = new ViewFader(mContentView);
            mOpenOverflow = Preconditions.checkNotNull(openOverflow);
        }

        /**
         * Fits as many menu items in the main panel and returns a list of the menu items that
         * were not fit in.
         *
         * @return The menu items that are not included in this main panel.
         */
        public List<MenuItem> layoutMenuItems(List<MenuItem> menuItems, int width) {
            Preconditions.checkNotNull(menuItems);

            // Reserve space for the "open overflow" button.
            final int toolbarWidth = width - getEstimatedOpenOverflowButtonWidth(mContext);

            int availableWidth = toolbarWidth;
            final LinkedList<MenuItem> remainingMenuItems = new LinkedList<MenuItem>(menuItems);

            mContentView.removeAllViews();

            boolean isFirstItem = true;
            while (!remainingMenuItems.isEmpty()) {
                final MenuItem menuItem = remainingMenuItems.peek();
                View menuItemButton = createMenuItemButton(mContext, menuItem);

                // Adding additional start padding for the first button to even out button spacing.
                if (isFirstItem) {
                    menuItemButton.setPaddingRelative(
                            (int) (1.5 * menuItemButton.getPaddingStart()),
                            menuItemButton.getPaddingTop(),
                            menuItemButton.getPaddingEnd(),
                            menuItemButton.getPaddingBottom());
                    isFirstItem = false;
                }

                // Adding additional end padding for the last button to even out button spacing.
                if (remainingMenuItems.size() == 1) {
                    menuItemButton.setPaddingRelative(
                            menuItemButton.getPaddingStart(),
                            menuItemButton.getPaddingTop(),
                            (int) (1.5 * menuItemButton.getPaddingEnd()),
                            menuItemButton.getPaddingBottom());
                }

                menuItemButton.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
                int menuItemButtonWidth = Math.min(menuItemButton.getMeasuredWidth(), toolbarWidth);
                if (menuItemButtonWidth <= availableWidth) {
                    setButtonTagAndClickListener(menuItemButton, menuItem);
                    mContentView.addView(menuItemButton);
                    ViewGroup.LayoutParams params = menuItemButton.getLayoutParams();
                    params.width = menuItemButtonWidth;
                    menuItemButton.setLayoutParams(params);
                    availableWidth -= menuItemButtonWidth;
                    remainingMenuItems.pop();
                } else {
                    if (mOpenOverflowButton == null) {
                        mOpenOverflowButton = LayoutInflater.from(mContext)
                                .inflate(R.layout.floating_popup_open_overflow_button, null);
                        mOpenOverflowButton.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                if (mOpenOverflowButton != null) {
                                    mOpenOverflow.run();
                                }
                            }
                        });
                    }
                    mContentView.addView(mOpenOverflowButton);
                    break;
                }
            }
            return remainingMenuItems;
        }

        public void setOnMenuItemClickListener(MenuItem.OnMenuItemClickListener listener) {
            mOnMenuItemClickListener = listener;
        }

        public View getView() {
            return mContentView;
        }

        public void fadeIn(boolean animate) {
            viewFader.fadeIn(animate);
        }

        public void fadeOut(boolean animate) {
            viewFader.fadeOut(animate);
        }

        /**
         * Returns how big this panel's view should be.
         * This method should only be called when the view has not been attached to a parent
         * otherwise it will throw an illegal state.
         */
        public Size measure() throws IllegalStateException {
            Preconditions.checkState(mContentView.getParent() == null);
            mContentView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
            return new Size(mContentView.getMeasuredWidth(), mContentView.getMeasuredHeight());
        }

        private void setButtonTagAndClickListener(View menuItemButton, MenuItem menuItem) {
            View button = menuItemButton;
            if (isIconOnlyMenuItem(menuItem)) {
                button = menuItemButton.findViewById(R.id.floating_toolbar_menu_item_image_button);
            }
            button.setTag(menuItem);
            button.setOnClickListener(mMenuItemButtonOnClickListener);
        }
    }


    /**
     * A widget that holds the overflow items in the floating toolbar.
     */
    private static final class FloatingToolbarOverflowPanel {

        private final LinearLayout mContentView;
        private final ViewGroup mBackButtonContainer;
        private final View mBackButton;
        private final ListView mListView;
        private final TextView mListViewItemWidthCalculator;
        private final ViewFader mViewFader;
        private final Runnable mCloseOverflow;

        private MenuItem.OnMenuItemClickListener mOnMenuItemClickListener;
        private int mOverflowWidth = 0;
        private int mSuggestedHeight;

        /**
         * Initializes a floating toolbar popup overflow view panel.
         *
         * @param context
         * @param closeOverflow  The code that closes the toolbar popup's overflow.
         */
        public FloatingToolbarOverflowPanel(Context context, Runnable closeOverflow) {
            mCloseOverflow = Preconditions.checkNotNull(closeOverflow);
            mSuggestedHeight = getScreenHeight(context);

            mContentView = new LinearLayout(context);
            mContentView.setOrientation(LinearLayout.VERTICAL);
            mViewFader = new ViewFader(mContentView);

            mBackButton = LayoutInflater.from(context)
                    .inflate(R.layout.floating_popup_close_overflow_button, null);
            mBackButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mCloseOverflow.run();
                }
            });
            mBackButtonContainer = new LinearLayout(context);
            mBackButtonContainer.addView(mBackButton);

            mListView = createOverflowListView();
            mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    MenuItem menuItem = (MenuItem) mListView.getAdapter().getItem(position);
                    if (mOnMenuItemClickListener != null) {
                        mOnMenuItemClickListener.onMenuItemClick(menuItem);
                    }
                }
            });

            mContentView.addView(mListView);
            mContentView.addView(mBackButtonContainer);

            mListViewItemWidthCalculator = createOverflowMenuItemButton(context);
            mListViewItemWidthCalculator.setLayoutParams(new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        }

        /**
         * Sets the menu items to be displayed in the overflow.
         */
        public void setMenuItems(List<MenuItem> menuItems) {
            ArrayAdapter overflowListViewAdapter = (ArrayAdapter) mListView.getAdapter();
            overflowListViewAdapter.clear();
            overflowListViewAdapter.addAll(menuItems);
            setListViewHeight();
            setOverflowWidth();
        }

        public void setOnMenuItemClickListener(MenuItem.OnMenuItemClickListener listener) {
            mOnMenuItemClickListener = listener;
        }

        /**
         * Notifies the overflow of the current direction in which the overflow will be opened.
         *
         * @param overflowDirection  {@link FloatingToolbarPopup#OVERFLOW_DIRECTION_UP}
         *   or {@link FloatingToolbarPopup#OVERFLOW_DIRECTION_DOWN}.
         */
        public void setOverflowDirection(int overflowDirection) {
            mContentView.removeView(mBackButtonContainer);
            int index = (overflowDirection == FloatingToolbarPopup.OVERFLOW_DIRECTION_UP)? 1 : 0;
            mContentView.addView(mBackButtonContainer, index);
        }

        public void setSuggestedHeight(int height) {
            mSuggestedHeight = height;
            setListViewHeight();
        }

        public int getMinimumHeight() {
            return mContentView.getContext().getResources().
                    getDimensionPixelSize(R.dimen.floating_toolbar_minimum_overflow_height)
                    + getEstimatedToolbarHeight(mContentView.getContext());
        }

        /**
         * Returns the content view of the overflow.
         */
        public View getView() {
            return mContentView;
        }

        public void fadeIn(boolean animate) {
            mViewFader.fadeIn(animate);
        }

        public void fadeOut(boolean animate) {
            mViewFader.fadeOut(animate);
        }

        /**
         * Returns how big this panel's view should be.
         * This method should only be called when the view has not been attached to a parent.
         *
         * @throws IllegalStateException
         */
        public Size measure() {
            Preconditions.checkState(mContentView.getParent() == null);
            mContentView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
            return new Size(mContentView.getMeasuredWidth(), mContentView.getMeasuredHeight());
        }

        private void setListViewHeight() {
            int itemHeight = getEstimatedToolbarHeight(mContentView.getContext());
            int height = mListView.getAdapter().getCount() * itemHeight;
            int maxHeight = mContentView.getContext().getResources().
                    getDimensionPixelSize(R.dimen.floating_toolbar_maximum_overflow_height);
            int minHeight = mContentView.getContext().getResources().
                    getDimensionPixelSize(R.dimen.floating_toolbar_minimum_overflow_height);
            int suggestedListViewHeight = mSuggestedHeight - (mSuggestedHeight % itemHeight)
                    - itemHeight;  // reserve space for the back button.
            ViewGroup.LayoutParams params = mListView.getLayoutParams();
            if (suggestedListViewHeight <= 0) {
                // Invalid height. Use the maximum height available.
                params.height = Math.min(maxHeight, height);
            } else if (suggestedListViewHeight < minHeight) {
                // Height is smaller than minimum allowed. Use minimum height.
                params.height = minHeight;
            } else {
                // Use the suggested height. Cap it at the maximum available height.
                params.height = Math.min(Math.min(suggestedListViewHeight, maxHeight), height);
            }
            mListView.setLayoutParams(params);
        }

        private int setOverflowWidth() {
            for (int i = 0; i < mListView.getAdapter().getCount(); i++) {
                MenuItem menuItem = (MenuItem) mListView.getAdapter().getItem(i);
                Preconditions.checkNotNull(menuItem);
                mListViewItemWidthCalculator.setText(menuItem.getTitle());
                mListViewItemWidthCalculator.measure(
                        MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
                mOverflowWidth = Math.max(
                        mListViewItemWidthCalculator.getMeasuredWidth(), mOverflowWidth);
            }
            return mOverflowWidth;
        }

        private ListView createOverflowListView() {
            final Context context = mContentView.getContext();
            final ListView overflowListView = new ListView(context);
            overflowListView.setLayoutParams(new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            overflowListView.setDivider(null);
            overflowListView.setDividerHeight(0);

            final int viewTypeCount = 2;
            final int stringLabelViewType = 0;
            final int iconOnlyViewType = 1;
            final ArrayAdapter overflowListViewAdapter =
                    new ArrayAdapter<MenuItem>(context, 0) {
                        @Override
                        public int getViewTypeCount() {
                            return viewTypeCount;
                        }

                        @Override
                        public int getItemViewType(int position) {
                            if (isIconOnlyMenuItem(getItem(position))) {
                                return iconOnlyViewType;
                            }
                            return stringLabelViewType;
                        }

                        @Override
                        public View getView(int position, View convertView, ViewGroup parent) {
                            if (getItemViewType(position) == iconOnlyViewType) {
                                return getIconOnlyView(position, convertView);
                            }
                            return getStringTitleView(position, convertView);
                        }

                        private View getStringTitleView(int position, View convertView) {
                            TextView menuButton;
                            if (convertView != null) {
                                menuButton = (TextView) convertView;
                            } else {
                                menuButton = createOverflowMenuItemButton(context);
                            }
                            MenuItem menuItem = getItem(position);
                            menuButton.setText(menuItem.getTitle());
                            menuButton.setContentDescription(menuItem.getTitle());
                            menuButton.setMinimumWidth(mOverflowWidth);
                            return menuButton;
                        }

                        private View getIconOnlyView(int position, View convertView) {
                            View menuButton;
                            if (convertView != null) {
                                menuButton = convertView;
                            } else {
                                menuButton = LayoutInflater.from(context).inflate(
                                        R.layout.floating_popup_overflow_image_list_item, null);
                            }
                            MenuItem menuItem = getItem(position);
                            ((ImageView) menuButton
                                    .findViewById(R.id.floating_toolbar_menu_item_image_button))
                                    .setImageDrawable(menuItem.getIcon());
                            menuButton.setMinimumWidth(mOverflowWidth);
                            return menuButton;
                        }
                    };
            overflowListView.setAdapter(overflowListViewAdapter);
            return overflowListView;
        }
    }


    /**
     * A helper for fading in or out a view.
     */
    private static final class ViewFader {

        private static final int FADE_OUT_DURATION = 250;
        private static final int FADE_IN_DURATION = 150;

        private final View mView;
        private final ObjectAnimator mFadeOutAnimation;
        private final ObjectAnimator mFadeInAnimation;

        private ViewFader(View view) {
            mView = Preconditions.checkNotNull(view);
            mFadeOutAnimation = ObjectAnimator.ofFloat(view, View.ALPHA, 1, 0)
                    .setDuration(FADE_OUT_DURATION);
            mFadeInAnimation = ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1)
                    .setDuration(FADE_IN_DURATION);
        }

        public void fadeIn(boolean animate) {
            cancelFadeAnimations();
            if (animate) {
                mFadeInAnimation.start();
            } else {
                mView.setAlpha(1);
            }
        }

        public void fadeOut(boolean animate) {
            cancelFadeAnimations();
            if (animate) {
                mFadeOutAnimation.start();
            } else {
                mView.setAlpha(0);
            }
        }

        private void cancelFadeAnimations() {
            mFadeInAnimation.cancel();
            mFadeOutAnimation.cancel();
        }
    }

    /**
     * @return {@code true} if the menu item does not not have a string title but has an icon.
     *   {@code false} otherwise.
     */
    private static boolean isIconOnlyMenuItem(MenuItem menuItem) {
        if (TextUtils.isEmpty(menuItem.getTitle()) && menuItem.getIcon() != null) {
            return true;
        }
        return false;
    }

    /**
     * Creates and returns a menu button for the specified menu item.
     */
    private static View createMenuItemButton(Context context, MenuItem menuItem) {
        if (isIconOnlyMenuItem(menuItem)) {
            View imageMenuItemButton = LayoutInflater.from(context)
                    .inflate(R.layout.floating_popup_menu_image_button, null);
            ((ImageButton) imageMenuItemButton
                    .findViewById(R.id.floating_toolbar_menu_item_image_button))
                    .setImageDrawable(menuItem.getIcon());
            return imageMenuItemButton;
        }

        Button menuItemButton = (Button) LayoutInflater.from(context)
                .inflate(R.layout.floating_popup_menu_button, null);
        menuItemButton.setText(menuItem.getTitle());
        menuItemButton.setContentDescription(menuItem.getTitle());
        return menuItemButton;
    }

    /**
     * Creates and returns a styled floating toolbar overflow list view item.
     */
    private static TextView createOverflowMenuItemButton(Context context) {
        return (TextView) LayoutInflater.from(context)
                .inflate(R.layout.floating_popup_overflow_list_item, null);
    }

    private static ViewGroup createContentContainer(Context context) {
        return (ViewGroup) LayoutInflater.from(context)
                .inflate(R.layout.floating_popup_container, null);
    }

    private static PopupWindow createPopupWindow(View content) {
        ViewGroup popupContentHolder = new LinearLayout(content.getContext());
        PopupWindow popupWindow = new PopupWindow(popupContentHolder);
        popupWindow.setWindowLayoutType(
                WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL);
        popupWindow.setAnimationStyle(0);
        popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        content.setLayoutParams(new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        popupContentHolder.addView(content);
        return popupWindow;
    }

    /**
     * Creates an "appear" animation for the specified view.
     *
     * @param view  The view to animate
     */
    private static AnimatorSet createEnterAnimation(View view) {
        AnimatorSet animation =  new AnimatorSet();
        animation.playTogether(
                ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1).setDuration(200),
                // Make sure that view.x is always fixed throughout the duration of this animation.
                ObjectAnimator.ofFloat(view, View.X, view.getX(), view.getX()));
        animation.setStartDelay(50);
        return animation;
    }

    /**
     * Creates a "disappear" animation for the specified view.
     *
     * @param view  The view to animate
     * @param startDelay  The start delay of the animation
     * @param listener  The animation listener
     */
    private static AnimatorSet createExitAnimation(
            View view, int startDelay, Animator.AnimatorListener listener) {
        AnimatorSet animation =  new AnimatorSet();
        animation.playTogether(
                ObjectAnimator.ofFloat(view, View.ALPHA, 1, 0).setDuration(200));
        animation.setStartDelay(startDelay);
        animation.addListener(listener);
        return animation;
    }

    /**
     * Returns a re-themed context with controlled look and feel for views.
     */
    private static Context applyDefaultTheme(Context originalContext) {
        TypedArray a = originalContext.obtainStyledAttributes(new int[]{R.attr.isLightTheme});
        boolean isLightTheme = a.getBoolean(0, true);
        int themeId = isLightTheme ? R.style.Theme_Material_Light : R.style.Theme_Material;
        a.recycle();
        return new ContextThemeWrapper(originalContext, themeId);
    }

    private static int getEstimatedToolbarHeight(Context context) {
        return context.getResources().getDimensionPixelSize(R.dimen.floating_toolbar_height);
    }

    private static int getEstimatedOpenOverflowButtonWidth(Context context) {
        return context.getResources()
                .getDimensionPixelSize(R.dimen.floating_toolbar_menu_button_minimum_width);
    }

    /**
     * Returns the device's screen width.
     */
    private static int getScreenWidth(Context context) {
        return context.getResources().getDisplayMetrics().widthPixels;
    }

    /**
     * Returns the device's screen height.
     */
    private static int getScreenHeight(Context context) {
        return context.getResources().getDisplayMetrics().heightPixels;
    }
}
