/*
 * Copyright (C) 2020 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.car.ui.toolbar;

import static android.view.View.GONE;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;

import static com.android.car.ui.core.CarUi.TARGET_API_R;
import static com.android.car.ui.utils.CarUiUtils.findViewByRefId;
import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;

import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.annotation.XmlRes;
import androidx.core.content.ContextCompat;

import com.android.car.ui.AlertDialogBuilder;
import com.android.car.ui.CarUiText;
import com.android.car.ui.R;
import com.android.car.ui.imewidescreen.CarUiImeSearchListItem;
import com.android.car.ui.recyclerview.CarUiContentListItem;
import com.android.car.ui.recyclerview.CarUiListItem;
import com.android.car.ui.recyclerview.CarUiListItemAdapter;
import com.android.car.ui.utils.CarUiUtils;
import com.android.car.ui.widget.CarUiTextView;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * The implementation of {@link ToolbarController}. This class takes a ViewGroup, and looks in the
 * ViewGroup to find all the toolbar-related views to control.
 */
@SuppressWarnings("AndroidJdkLibsChecker")
@TargetApi(TARGET_API_R)
public final class ToolbarControllerImpl implements ToolbarController {
    private static final String TAG = "CarUiToolbarController";

    @Nullable
    private View mBackground;
    private ImageView mNavIcon;
    private ImageView mLogoInNavIconSpace;
    private ViewGroup mNavIconContainer;
    private ViewGroup mTitleContainer;
    private CarUiTextView mTitle;
    @NonNull
    private CarUiText mTitleText = new CarUiText.Builder("").build();
    private CarUiTextView mSubtitle;
    @NonNull
    private CarUiText mSubtitleText = new CarUiText.Builder("").build();
    private ImageView mTitleLogo;
    private ViewGroup mTitleLogoContainer;
    private TabLayout mTabLayout;
    private ViewGroup mMenuItemsContainer;
    private SearchConfig.SearchConfigBuilder mSearchConfigBuilder;
    private final FrameLayout mSearchViewContainer;
    private SearchView mSearchView;

    // Cached values that we will send to views when they are inflated
    private CharSequence mSearchHint;
    private Drawable mSearchIcon;
    private String mSearchQuery;
    private final Context mContext;
    private final Set<Consumer<String>> mOnSearchListeners = new HashSet<>();
    private final Set<Runnable> mOnSearchCompletedListeners = new HashSet<>();
    private final Set<Toolbar.OnSearchListener> mDeprecatedSearchListeners = new HashSet<>();
    private final Set<Toolbar.OnSearchCompletedListener> mDeprecatedSearchCompletedListeners =
            new HashSet<>();

    private final Set<Toolbar.OnBackListener> mDeprecatedBackListeners = new HashSet<>();
    private final Set<Supplier<Boolean>> mBackListeners = new HashSet<>();
    private final Set<Toolbar.OnTabSelectedListener> mOnTabSelectedListeners = new HashSet<>();

    private final MenuItem mOverflowButton;
    private final boolean mIsTabsInSecondRow;
    private boolean mShowTabsInSubpage = false;
    private boolean mHasLogo = false;
    private boolean mShowMenuItemsWhileSearching;
    private Toolbar.State mState = Toolbar.State.HOME;
    private boolean mStateSet = false;
    private NavButtonMode mNavButtonMode = NavButtonMode.DISABLED;
    private SearchMode mSearchMode = SearchMode.DISABLED;
    @NonNull
    private List<MenuItem> mMenuItems = Collections.emptyList();
    private List<MenuItem> mOverflowItems = new ArrayList<>();
    private final List<CarUiListItem> mUiOverflowItems = new ArrayList<>();
    private final CarUiListItemAdapter mOverflowAdapter;
    private final List<MenuItemRenderer> mMenuItemRenderers = new ArrayList<>();
    private final List<DeprecatedTabWrapper> mDeprecatedTabs = new ArrayList<>();
    private View[] mMenuItemViews;
    private int mMenuItemsXmlId = 0;
    private AlertDialog mOverflowDialog;
    private final boolean mNavIconSpaceReserved;
    private final boolean mLogoFillsNavIconSpace;
    private final boolean mShowLogo;
    private SearchConfig mSearchConfigForWidescreen;
    private final ProgressBarController mProgressBar;
    private final MenuItem.Listener mOverflowItemListener = item -> {
        updateOverflowDialog(item);
        update();
    };


    public ToolbarControllerImpl(View view) {
        mContext = view.getContext();
        mOverflowButton = MenuItem.builder(getContext())
                .setIcon(R.drawable.car_ui_icon_overflow_menu)
                .setTitle(R.string.car_ui_toolbar_menu_item_overflow_title)
                .setOnClickListener(v -> {
                    if (mOverflowDialog == null) {
                        if (Log.isLoggable(TAG, Log.ERROR)) {
                            Log.e(TAG, "Overflow dialog was null when trying to show it!");
                        }
                    } else {
                        mOverflowDialog.show();
                    }
                })
                .build();

        mIsTabsInSecondRow = getContext().getResources().getBoolean(
                R.bool.car_ui_toolbar_tabs_on_second_row);
        mNavIconSpaceReserved = getContext().getResources().getBoolean(
                R.bool.car_ui_toolbar_nav_icon_reserve_space);
        mLogoFillsNavIconSpace = getContext().getResources().getBoolean(
                R.bool.car_ui_toolbar_logo_fills_nav_icon_space);
        mShowLogo = getContext().getResources().getBoolean(
                R.bool.car_ui_toolbar_show_logo);
        mSearchHint = getContext().getString(R.string.car_ui_toolbar_default_search_hint);

        mBackground = findViewByRefId(view, R.id.car_ui_toolbar_background);
        mTabLayout = requireViewByRefId(view, R.id.car_ui_toolbar_tabs);
        mNavIcon = requireViewByRefId(view, R.id.car_ui_toolbar_nav_icon);
        mLogoInNavIconSpace = requireViewByRefId(view, R.id.car_ui_toolbar_logo);
        mNavIconContainer = requireViewByRefId(view, R.id.car_ui_toolbar_nav_icon_container);
        mMenuItemsContainer = requireViewByRefId(view, R.id.car_ui_toolbar_menu_items_container);
        mTitleContainer = requireViewByRefId(view, R.id.car_ui_toolbar_title_container);
        mSubtitle = requireViewByRefId(view, R.id.car_ui_toolbar_subtitle);
        mTitle = requireViewByRefId(view, R.id.car_ui_toolbar_title);
        mTitleLogoContainer = requireViewByRefId(view, R.id.car_ui_toolbar_title_logo_container);
        mTitleLogo = requireViewByRefId(view, R.id.car_ui_toolbar_title_logo);
        mSearchViewContainer = requireViewByRefId(view, R.id.car_ui_toolbar_search_view_container);
        mProgressBar = new ProgressBarControllerImpl(
                requireViewByRefId(view, R.id.car_ui_toolbar_progress_bar));
        mSearchConfigBuilder = SearchConfig.builder();

        setBackgroundShown(true);

        mOverflowAdapter = new CarUiListItemAdapter(mUiOverflowItems);
        update();
    }

    private Context getContext() {
        return mContext;
    }

    private Drawable getDrawable(@DrawableRes int resId) {
        if (resId == 0) {
            return null;
        } else {
            return ContextCompat.getDrawable(getContext(), resId);
        }
    }

    /**
     * Sets the title of the toolbar to a string resource.
     *
     * <p>The title may not always be shown, for example with one row layout with tabs.
     */
    @Override
    public void setTitle(@StringRes int title) {
        setTitle(title == 0 ? null : getContext().getString(title));
    }

    /**
     * Sets the title of the toolbar to a CharSequence.
     *
     * <p>The title may not always be shown, for example with one row layout with tabs.
     */
    @Override
    public void setTitle(CharSequence title) {
        mTitleText = title == null ? new CarUiText.Builder("").build() : new CarUiText.Builder(
                title).build();
        mTitle.setText(mTitleText);
        update();
    }

    @Override
    public void setTitle(CarUiText title) {
        mTitleText = title;
        mTitle.setText(mTitleText);
        update();
    }

    @Override
    public CharSequence getTitle() {
        return mTitleText.getPreferredText();
    }

    /**
     * Sets the subtitle of the toolbar to a string resource.
     *
     * <p>The title may not always be shown, for example with one row layout with tabs.
     */
    @Override
    public void setSubtitle(@StringRes int subTitle) {
        setSubtitle(subTitle == 0 ? null : getContext().getString(subTitle));
    }

    /**
     * Sets the subtitle of the toolbar to a CharSequence.
     *
     * <p>The title may not always be shown, for example with one row layout with tabs.
     */
    @Override
    public void setSubtitle(CharSequence subTitle) {
        mSubtitleText = subTitle == null ? new CarUiText.Builder("").build()
                : new CarUiText.Builder(subTitle).build();
        mSubtitle.setText(mSubtitleText);
        update();
    }

    @Override
    public void setSubtitle(CarUiText text) {
        mSubtitleText = text;
        mSubtitle.setText(mSubtitleText);
        update();
    }

    @Override
    public CharSequence getSubtitle() {
        return mSubtitleText.getPreferredText();
    }

    @Override
    public void setTabs(@Nullable List<Tab> tabs) {
        setTabs(tabs, 0);
    }

    @Override
    public void setTabs(@Nullable List<Tab> tabs, int selectedTab) {
        mDeprecatedTabs.clear();
        setTabsInternal(tabs, selectedTab);
    }

    @Override
    public List<Tab> getTabs() {
        return mTabLayout.getTabs();
    }

    private void setTabsInternal(@Nullable List<Tab> tabs, int selectedTab) {
        if (tabs == null || tabs.isEmpty()) {
            selectedTab = -1;
        } else if (selectedTab < 0 || selectedTab >= tabs.size()) {
            throw new IllegalArgumentException("Tab position is invalid: " + selectedTab);
        }
        mTabLayout.setTabs(tabs, selectedTab);
        update();
    }

    /**
     * Gets the number of tabs in the toolbar. The tabs can be retrieved using
     * {@link #getTab(int)}.
     */
    @Override
    public int getTabCount() {
        return mDeprecatedTabs.size();
    }

    @Override
    public int getTabPosition(TabLayout.Tab tab) {
        for (int i = 0; i < mDeprecatedTabs.size(); i++) {
            if (mDeprecatedTabs.get(i).getDeprecatedTab() == tab) {
                return i;
            }
        }
        return -1;
    }

    @Override
    public void addTab(TabLayout.Tab newTab) {
        mDeprecatedTabs.add(new DeprecatedTabWrapper(getContext(), newTab,
                this::updateModernTabsFromDeprecatedOnes, (tab) -> {
            for (Toolbar.OnTabSelectedListener listener : mOnTabSelectedListeners) {
                listener.onTabSelected(newTab);
            }
        }));
        updateModernTabsFromDeprecatedOnes();
    }

    private void updateModernTabsFromDeprecatedOnes() {
        List<Tab> modernTabs = new ArrayList<>();

        for (DeprecatedTabWrapper tab : mDeprecatedTabs) {
            modernTabs.add(tab.getModernTab());
        }

        setTabsInternal(modernTabs, 0);
    }

    @Override
    public void clearAllTabs() {
        mDeprecatedTabs.clear();
        setTabs(null);
    }

    @Override
    public TabLayout.Tab getTab(int position) {
        return mDeprecatedTabs.get(position).getDeprecatedTab();
    }

    /**
     * Selects a tab added to this toolbar. See {@link #addTab(TabLayout.Tab)}.
     */
    @Override
    public void selectTab(int position) {
        mTabLayout.selectTab(position);
    }

    @Override
    public int getSelectedTab() {
        return mTabLayout.getSelectedTab();
    }

    /**
     * Sets whether or not tabs should also be shown in the SUBPAGE {@link Toolbar.State}.
     */
    @Override
    public void setShowTabsInSubpage(boolean showTabs) {
        if (showTabs != mShowTabsInSubpage) {
            mShowTabsInSubpage = showTabs;
            update();
        }
    }

    /**
     * Gets whether or not tabs should also be shown in the SUBPAGE {@link Toolbar.State}.
     */
    @Override
    public boolean getShowTabsInSubpage() {
        return mShowTabsInSubpage;
    }

    /**
     * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
     * will be displayed next to the title.
     */
    @Override
    public void setLogo(@DrawableRes int resId) {
        asyncSetLogo(resId, Runnable::run);
    }

    private void asyncSetLogo(int resId, Executor bgExecutor) {
        if (!mShowLogo) {
            // If no logo should be shown then we act as if we never received one.
            return;
        }
        if (resId != 0) {
            bgExecutor.execute(() -> {
                // load resource on background thread.
                Drawable drawable = getDrawable(resId);
                mTitleLogo.post(() -> {
                    // UI thread.
                    mLogoInNavIconSpace.setImageDrawable(drawable);
                    mTitleLogo.setImageDrawable(drawable);
                });
            });
            mHasLogo = true;
        } else {
            mHasLogo = false;
        }
        update();
    }

    /**
     * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
     * will be displayed next to the title.
     */
    @Override
    public void setLogo(Drawable drawable) {
        if (!mShowLogo) {
            // If no logo should be shown then we act as if we never received one.
            return;
        }
        if (drawable != null) {
            mLogoInNavIconSpace.setImageDrawable(drawable);
            mTitleLogo.setImageDrawable(drawable);
            mHasLogo = true;
        } else {
            mHasLogo = false;
        }

        update();
    }

    /**
     * Sets the hint for the search bar.
     */
    @Override
    public void setSearchHint(@StringRes int resId) {
        setSearchHint(getContext().getString(resId));
    }

    /**
     * Sets the hint for the search bar.
     */
    public void setSearchHint(CharSequence hint) {
        mSearchHint = hint;
        if (mSearchView != null) {
            mSearchView.setHint(mSearchHint);
        }
    }

    /**
     * Gets the search hint
     */
    @Override
    public CharSequence getSearchHint() {
        return mSearchHint;
    }

    /**
     * Sets the icon to display in the search box.
     *
     * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
     * a similar place.
     */
    @Override
    public void setSearchIcon(@DrawableRes int resId) {
        setSearchIcon(getDrawable(resId));
    }

    /**
     * Sets the icon to display in the search box.
     *
     * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
     * a similar place.
     */
    @Override
    public void setSearchIcon(Drawable d) {
        if (!Objects.equals(d, mSearchIcon)) {
            mSearchIcon = d;
            if (mSearchView != null) {
                mSearchView.setIcon(mSearchIcon);
            }
        }
    }


    /**
     * Sets the {@link Toolbar.NavButtonMode}
     */
    @Override
    public void setNavButtonMode(Toolbar.NavButtonMode mode) {
        NavButtonMode modernMode;
        switch (mode) {
            case BACK:
                modernMode = NavButtonMode.BACK;
                break;
            case DOWN:
                modernMode = NavButtonMode.DOWN;
                break;
            case CLOSE:
                modernMode = NavButtonMode.CLOSE;
                break;
            case DISABLED:
            default:
                modernMode = NavButtonMode.DISABLED;
                break;
        }
        setNavButtonMode(modernMode);
    }

    @Override
    public void setNavButtonMode(NavButtonMode mode) {
        if (mode != mNavButtonMode) {
            mNavButtonMode = mode;
            update();
        }
    }

    /**
     * Gets the {@link Toolbar.NavButtonMode}
     */
    @Override
    public NavButtonMode getNavButtonMode() {
        return mNavButtonMode;
    }

    /**
     * Show/hide the background. When hidden, the toolbar is completely transparent.
     */
    @Override
    public void setBackgroundShown(boolean shown) {
        if (mBackground == null) {
            return;
        }

        if (shown) {
            mBackground.setBackground(getDrawable(R.drawable.car_ui_toolbar_background));
        } else {
            mBackground.setBackground(null);
        }
    }

    /**
     * Returns true is the toolbar background is shown
     */
    @Override
    public boolean getBackgroundShown() {
        if (mBackground == null) {
            return true;
        }

        return mBackground.getBackground() != null;
    }

    private void setMenuItemsInternal(@Nullable List<MenuItem> items) {
        if (items == null) {
            items = Collections.emptyList();
        }

        List<MenuItem> visibleMenuItems = new ArrayList<>();
        List<MenuItem> overflowItems = new ArrayList<>();
        AtomicInteger loadedMenuItems = new AtomicInteger(0);

        synchronized (this) {
            if (items.equals(mMenuItems)) {
                return;
            }

            for (MenuItem item : items) {
                if (item.getDisplayBehavior() == MenuItem.DisplayBehavior.NEVER) {
                    overflowItems.add(item);
                    item.setListener(mOverflowItemListener);
                } else {
                    visibleMenuItems.add(item);
                }
            }

            // Copy the list so that if the list is modified and setMenuItems is called again,
            // the equals() check will fail. Note that the MenuItems are not copied here.
            mMenuItems = new ArrayList<>(items);
            mOverflowItems = overflowItems;
            mMenuItemRenderers.clear();
            mMenuItemsContainer.removeAllViews();

            if (!overflowItems.isEmpty()) {
                visibleMenuItems.add(mOverflowButton);
                createOverflowDialog();
            }

            View[] menuItemViews = new View[visibleMenuItems.size()];
            mMenuItemViews = menuItemViews;

            for (int i = 0; i < visibleMenuItems.size(); ++i) {
                int index = i;
                MenuItem item = visibleMenuItems.get(i);
                MenuItemRenderer renderer = new MenuItemRenderer(item, mMenuItemsContainer);
                mMenuItemRenderers.add(renderer);
                renderer.createView(view -> {
                    synchronized (ToolbarControllerImpl.this) {
                        if (menuItemViews != mMenuItemViews) {
                            return;
                        }

                        menuItemViews[index] = view;
                        if (loadedMenuItems.addAndGet(1) == menuItemViews.length) {
                            for (View v : menuItemViews) {
                                mMenuItemsContainer.addView(v);
                            }
                        }
                    }
                });
            }
        }

        update();
    }

    /**
     * Sets the {@link MenuItem Menuitems} to display.
     */
    @Override
    public void setMenuItems(@Nullable List<MenuItem> items) {
        mMenuItemsXmlId = 0;
        setMenuItemsInternal(items);
    }

    /**
     * Sets the {@link MenuItem Menuitems} to display to a list defined in XML.
     *
     * <p>If this method is called twice with the same argument (and {@link #setMenuItems(List)}
     * wasn't called), nothing will happen the second time, even if the MenuItems were changed.
     *
     * <p>The XML file must have one <MenuItems> tag, with a variable number of <MenuItem>
     * child tags. See CarUiToolbarMenuItem in CarUi's attrs.xml for a list of available
     * attributes.
     * <p>
     * Example:
     * <pre>
     * <MenuItems>
     *     <MenuItem
     *         app:title="Foo"/>
     *     <MenuItem
     *         app:title="Bar"
     *         app:icon="@drawable/ic_tracklist"
     *         app:onClick="xmlMenuItemClicked"/>
     *     <MenuItem
     *         app:title="Bar"
     *         app:checkable="true"
     *         app:uxRestrictions="FULLY_RESTRICTED"
     *         app:onClick="xmlMenuItemClicked"/>
     * </MenuItems>
     * </pre>
     *
     * @return The MenuItems that were loaded from XML.
     * @see #setMenuItems(List)
     */
    @Override
    public List<MenuItem> setMenuItems(@XmlRes int resId) {
        if (mMenuItemsXmlId != 0 && mMenuItemsXmlId == resId) {
            return mMenuItems;
        }

        mMenuItemsXmlId = resId;
        List<MenuItem> menuItems = MenuItemXmlParserUtil.readMenuItemList(getContext(), resId);
        setMenuItemsInternal(menuItems);
        return menuItems;
    }

    /**
     * Gets the {@link MenuItem MenuItems} currently displayed
     */
    @Override
    @NonNull
    public List<MenuItem> getMenuItems() {
        return Collections.unmodifiableList(mMenuItems);
    }

    /**
     * Gets a {@link MenuItem} by id.
     */
    @Override
    @Nullable
    public MenuItem findMenuItemById(int id) {
        for (MenuItem item : mMenuItems) {
            if (item.getId() == id) {
                return item;
            }
        }
        return null;
    }

    /**
     * Gets a {@link MenuItem} by id. Will throw an IllegalArgumentException if not found.
     */
    @Override
    @NonNull
    public MenuItem requireMenuItemById(int id) {
        MenuItem result = findMenuItemById(id);

        if (result == null) {
            throw new IllegalArgumentException("ID does not reference a MenuItem on this Toolbar");
        }

        return result;
    }

    private int countVisibleOverflowItems() {
        int numVisibleItems = 0;
        for (MenuItem item : mOverflowItems) {
            if (item.isVisible()) {
                numVisibleItems++;
            }
        }
        return numVisibleItems;
    }

    private void createOverflowDialog() {
        mUiOverflowItems.clear();
        for (MenuItem menuItem : mOverflowItems) {
            if (menuItem.isVisible()) {
                mUiOverflowItems.add(toCarUiContentListItem(menuItem));
            }
        }

        mOverflowDialog = new AlertDialogBuilder(getContext())
                .setAdapter(mOverflowAdapter)
                .create();
    }

    private void updateOverflowDialog(MenuItem changedItem) {
        int itemIndex = mOverflowItems.indexOf(changedItem);
        if (itemIndex >= 0) {
            mUiOverflowItems.set(itemIndex, toCarUiContentListItem(changedItem));
            mOverflowAdapter.notifyItemChanged(itemIndex);
        } else {
            createOverflowDialog();
        }
    }

    private CarUiContentListItem toCarUiContentListItem(MenuItem menuItem) {
        CarUiContentListItem carUiItem;
        if (menuItem.isCheckable()) {
            carUiItem = new CarUiContentListItem(CarUiContentListItem.Action.SWITCH);
        } else {
            carUiItem = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
        }
        carUiItem.setIcon(menuItem.getIcon());
        carUiItem.setActivated(menuItem.isActivated());
        carUiItem.setChecked(menuItem.isChecked());
        carUiItem.setEnabled(menuItem.isEnabled());
        carUiItem.setTitle(menuItem.getTitle());
        carUiItem.setOnItemClickedListener(item -> {
            menuItem.performClick();
            mOverflowDialog.hide();
        });
        return carUiItem;
    }

    /**
     * Set whether or not to show the {@link MenuItem MenuItems} while searching. Default false.
     * Even if this is set to true, the {@link MenuItem} created by
     * {@link MenuItem.Builder#setToSearch()} will still be hidden.
     */
    @Override
    public void setShowMenuItemsWhileSearching(boolean showMenuItems) {
        mShowMenuItemsWhileSearching = showMenuItems;
        update();
    }

    /**
     * Returns if {@link MenuItem MenuItems} are shown while searching
     */
    @Override
    public boolean getShowMenuItemsWhileSearching() {
        return mShowMenuItemsWhileSearching;
    }

    /**
     * Sets the search query.
     */
    @Override
    public void setSearchQuery(String query) {
        if (mSearchView != null) {
            mSearchView.setSearchQuery(query);
        } else {
            mSearchQuery = query;
            for (Toolbar.OnSearchListener listener : mDeprecatedSearchListeners) {
                listener.onSearch(query);
            }
            for (Consumer<String> listener : mOnSearchListeners) {
                listener.accept(query);
            }
        }
    }

    /**
     * Sets the state of the toolbar. This will show/hide the appropriate elements of the toolbar
     * for the desired state.
     */
    @Override
    public void setState(Toolbar.State state) {
        if (mState != state || !mStateSet) {
            mState = state;
            mStateSet = true;
            update();
        }
    }

    @Override
    public void setSearchMode(SearchMode mode) {
        if (mStateSet) {
            throw new IllegalStateException("Cannot set search mode when using setState()");
        }
        if (mSearchMode != mode) {
            mSearchMode = mode;
            update();
        }
    }

    @Override
    public SearchMode getSearchMode() {
        return mSearchMode;
    }

    private void update() {
        // Start by removing mState/mStateSet from the equation by incorporating them into other
        // variables.
        NavButtonMode navButtonMode = mNavButtonMode;
        if (mStateSet) {
            if (mState == Toolbar.State.HOME) {
                navButtonMode = NavButtonMode.DISABLED;
            } else if (navButtonMode == NavButtonMode.DISABLED) {
                navButtonMode = NavButtonMode.BACK;
            }
        }

        SearchMode searchMode = mSearchMode;
        if (mStateSet) {
            if (mState == Toolbar.State.SEARCH) {
                searchMode = SearchMode.SEARCH;
            } else if (mState == Toolbar.State.EDIT) {
                searchMode = SearchMode.EDIT;
            } else {
                searchMode = SearchMode.DISABLED;
            }
        }

        boolean hasLogo = mHasLogo;
        if (mStateSet && (mState == Toolbar.State.SEARCH || mState == Toolbar.State.EDIT)) {
            hasLogo = false;
        }

        boolean hasTabs = mTabLayout.hasTabs();
        if (mStateSet && mState != Toolbar.State.HOME
                && !(mState == Toolbar.State.SUBPAGE && mShowTabsInSubpage)) {
            hasTabs = false;
        }

        boolean isSearching = searchMode != SearchMode.DISABLED;
        if (mSearchView == null && isSearching) {
            inflateSearchView();
        }

        for (MenuItemRenderer renderer : mMenuItemRenderers) {
            renderer.setToolbarIsSearching(searchMode == SearchMode.SEARCH);
        }

        View.OnClickListener backClickListener = (v) -> {
            boolean absorbed = false;
            List<Toolbar.OnBackListener> deprecatedListenersCopy =
                    new ArrayList<>(mDeprecatedBackListeners);
            List<Supplier<Boolean>> listenersCopy = new ArrayList<>(mBackListeners);
            for (Toolbar.OnBackListener listener : deprecatedListenersCopy) {
                absorbed = absorbed || listener.onBack();
            }
            for (Supplier<Boolean> listener : listenersCopy) {
                absorbed = absorbed || listener.get();
            }

            if (!absorbed) {
                Activity activity = CarUiUtils.getActivity(getContext());
                if (activity != null) {
                    activity.onBackPressed();
                }
            }
        };

        switch (navButtonMode) {
            case CLOSE:
                mNavIcon.setImageResource(R.drawable.car_ui_icon_close);
                break;
            case DOWN:
                mNavIcon.setImageResource(R.drawable.car_ui_icon_down);
                break;
            default:
                mNavIcon.setImageResource(R.drawable.car_ui_icon_arrow_back);
                break;
        }

        mNavIcon.setVisibility(navButtonMode != NavButtonMode.DISABLED
                ? VISIBLE : GONE);

        // Show the logo in the nav space if that's enabled, we have a logo,
        // and we don't have a nav button.
        mLogoInNavIconSpace.setVisibility(hasLogo
                && navButtonMode == NavButtonMode.DISABLED
                && mLogoFillsNavIconSpace
                ? VISIBLE : INVISIBLE);

        // Show logo next to the title if we have a back button or we're configured to not show
        // the logo in the nav icon space.
        mTitleLogoContainer.setVisibility(hasLogo
                && (navButtonMode != NavButtonMode.DISABLED || !mLogoFillsNavIconSpace)
                ? VISIBLE : GONE);

        // Show the nav icon container if we're not in the home space or the logo fills the nav icon
        // container. If car_ui_toolbar_nav_icon_reserve_space is true, hiding it will still reserve
        // its space
        mNavIconContainer.setVisibility(
                navButtonMode != NavButtonMode.DISABLED
                        || (hasLogo && mLogoFillsNavIconSpace)
                        ? VISIBLE : (mNavIconSpaceReserved ? INVISIBLE : GONE));
        mNavIconContainer.setOnClickListener(
                navButtonMode != NavButtonMode.DISABLED ? backClickListener : null);
        mNavIconContainer.setClickable(navButtonMode != NavButtonMode.DISABLED);
        mNavIconContainer.setContentDescription(navButtonMode != NavButtonMode.DISABLED
                ? getContext().getString(R.string.car_ui_toolbar_nav_icon_content_description)
                : null);

        // Show the title if we're in the subpage state, or in the home state with no tabs or tabs
        // on the second row
        mTitleContainer.setVisibility((!hasTabs || mIsTabsInSecondRow) && !isSearching
                ? VISIBLE : GONE);
        mSubtitle.setVisibility(
                TextUtils.isEmpty(getSubtitle()) ? GONE : VISIBLE);

        mTabLayout.setVisibility(hasTabs
                && (mSearchMode == SearchMode.DISABLED || mIsTabsInSecondRow) ? VISIBLE : GONE);

        if (mSearchView != null) {
            if (isSearching) {
                mSearchView.setPlainText(searchMode == SearchMode.EDIT);
                mSearchView.setVisibility(VISIBLE);
            } else {
                mSearchView.setVisibility(GONE);
            }
        }

        boolean showButtons = !isSearching || mShowMenuItemsWhileSearching;
        mMenuItemsContainer.setVisibility(showButtons ? VISIBLE : GONE);
        mOverflowButton.setVisible(showButtons && countVisibleOverflowItems() > 0);
    }

    private void inflateSearchView() {
        SearchView searchView = new SearchView(getContext());
        searchView.setHint(mSearchHint);
        searchView.setIcon(mSearchIcon);
        searchView.setSearchQuery(mSearchQuery);
        searchView.setSearchListeners(
                mDeprecatedSearchListeners, mOnSearchListeners);
        searchView.setSearchCompletedListeners(
                mDeprecatedSearchCompletedListeners, mOnSearchCompletedListeners);
        searchView.setVisibility(GONE);

        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        mSearchViewContainer.addView(searchView, layoutParams);

        searchView.setSearchConfig(mSearchConfigForWidescreen);

        mSearchView = searchView;
    }

    /**
     * Add a view within a container that will animate with the wide screen IME to display search
     * results.
     *
     * <p>Note: Apps can only call this method if the package name is allowed via OEM to render
     * their view.  To check if the application have the permission to do so or not first call
     * {@link SearchCapabilities#canShowSearchResultsView()}. If the app is not allowed this method
     * will throw an {@link IllegalStateException}
     *
     * @param view to be added in the container.
     */
    @Override
    public void setSearchResultsView(View view) {
        if (!getSearchCapabilities().canShowSearchResultsView()) {
            throw new IllegalStateException(
                    "not allowed to add view to wide screen IME, package name: "
                            + getContext().getPackageName());
        }

        setSearchConfig(mSearchConfigBuilder.setSearchResultsView(view).build());
    }

    @Override
    public void setSearchResultsInputViewIcon(@NonNull Drawable drawable) {
        setSearchConfig(mSearchConfigBuilder.setSearchResultsInputViewIcon(drawable).build());
    }

    /**
     * Sets list of search item {@link CarUiListItem} to be displayed in the IMS template. This
     * method should be called when system is running in a wide screen mode. Apps can check that by
     * using {@link SearchCapabilities#canShowSearchResultItems()} Else, this method will throw an
     * {@link IllegalStateException}
     */
    @Override
    public void setSearchResultItems(List<? extends CarUiImeSearchListItem> searchItems) {
        if (!getSearchCapabilities().canShowSearchResultItems()) {
            throw new IllegalStateException(
                    "system not in wide screen mode, not allowed to set search result items ");
        }

        setSearchConfig(mSearchConfigBuilder.setSearchResultItems(searchItems).build());
    }

    @Override
    public void setSearchConfig(SearchConfig searchConfig) {
        mSearchConfigForWidescreen = searchConfig;
        if (mSearchView != null) {
            mSearchView.setSearchConfig(mSearchConfigForWidescreen);
        }
    }

    @Override
    public SearchCapabilities getSearchCapabilities() {
        return SearchWidescreenController.getSearchCapabilities(mContext);
    }

    @Override
    public boolean canShowSearchResultItems() {
        return getSearchCapabilities().canShowSearchResultItems();
    }

    @Override
    public boolean canShowSearchResultsView() {
        return getSearchCapabilities().canShowSearchResultsView();
    }

    /**
     * Gets the current {@link Toolbar.State} of the toolbar.
     */
    @Override
    public Toolbar.State getState() {
        return mState;
    }

    /**
     * Returns whether or not the state of the toolbar was previously set.
     */
    @Override
    public boolean isStateSet() {
        return mStateSet;
    }

    /**
     * Registers a new {@link Toolbar.OnTabSelectedListener} to the list of listeners.
     */
    @Override
    public void registerOnTabSelectedListener(Toolbar.OnTabSelectedListener listener) {
        mOnTabSelectedListeners.add(listener);
    }

    /**
     * Unregisters an existing {@link Toolbar.OnTabSelectedListener} from the list of listeners.
     */
    @Override
    public boolean unregisterOnTabSelectedListener(Toolbar.OnTabSelectedListener listener) {
        return mOnTabSelectedListeners.remove(listener);
    }

    /**
     * Registers a new {@link Toolbar.OnSearchListener} to the list of listeners.
     */
    @Override
    public void registerOnSearchListener(Toolbar.OnSearchListener listener) {
        mDeprecatedSearchListeners.add(listener);
    }

    /**
     * Unregisters an existing {@link Toolbar.OnSearchListener} from the list of listeners.
     */
    @Override
    public boolean unregisterOnSearchListener(Toolbar.OnSearchListener listener) {
        return mDeprecatedSearchListeners.remove(listener);
    }

    @Override
    public void registerSearchListener(Consumer<String> listener) {
        mOnSearchListeners.add(listener);
    }

    @Override
    public boolean unregisterSearchListener(Consumer<String> listener) {
        return mOnSearchListeners.remove(listener);
    }

    /**
     * Registers a new {@link Toolbar.OnSearchCompletedListener} to the list of listeners.
     */
    @Override
    public void registerOnSearchCompletedListener(Toolbar.OnSearchCompletedListener listener) {
        mDeprecatedSearchCompletedListeners.add(listener);
    }

    /**
     * Unregisters an existing {@link Toolbar.OnSearchCompletedListener} from the list of
     * listeners.
     */
    @Override
    public boolean unregisterOnSearchCompletedListener(Toolbar.OnSearchCompletedListener listener) {
        return mDeprecatedSearchCompletedListeners.remove(listener);
    }

    @Override
    public void registerSearchCompletedListener(Runnable listener) {
        mOnSearchCompletedListeners.add(listener);
    }

    @Override
    public boolean unregisterSearchCompletedListener(Runnable listener) {
        return mOnSearchCompletedListeners.remove(listener);
    }

    /**
     * Registers a new {@link Toolbar.OnBackListener} to the list of listeners.
     */
    @Override
    public void registerOnBackListener(Toolbar.OnBackListener listener) {
        mDeprecatedBackListeners.add(listener);
    }

    /**
     * Unregisters an existing {@link Toolbar.OnBackListener} from the list of listeners.
     */
    @Override
    public boolean unregisterOnBackListener(Toolbar.OnBackListener listener) {
        return mDeprecatedBackListeners.remove(listener);
    }

    @Override
    public void registerBackListener(Supplier<Boolean> listener) {
        mBackListeners.add(listener);
    }

    @Override
    public boolean unregisterBackListener(Supplier<Boolean> listener) {
        return mBackListeners.remove(listener);
    }

    /**
     * Returns the progress bar
     */
    @Override
    public ProgressBarController getProgressBar() {
        return mProgressBar;
    }
}
