/*
 * Copyright (C) 2011 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.view.menu;

import com.android.internal.view.menu.MenuView.ItemView;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.SparseArray;
import android.view.ContextThemeWrapper;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;

/**
 * MenuPresenter for the classic "six-pack" icon menu.
 */
public class IconMenuPresenter extends BaseMenuPresenter {
    private IconMenuItemView mMoreView;
    private int mMaxItems = -1;

    int mOpenSubMenuId;
    SubMenuPresenterCallback mSubMenuPresenterCallback = new SubMenuPresenterCallback();
    MenuDialogHelper mOpenSubMenu;

    private static final String VIEWS_TAG = "android:menu:icon";
    private static final String OPEN_SUBMENU_KEY = "android:menu:icon:submenu";

    public IconMenuPresenter(Context context) {
        super(new ContextThemeWrapper(context, com.android.internal.R.style.Theme_IconMenu),
                com.android.internal.R.layout.icon_menu_layout,
                com.android.internal.R.layout.icon_menu_item_layout);
    }

    @Override
    public void initForMenu(@NonNull Context context, @Nullable MenuBuilder menu) {
        super.initForMenu(context, menu);
        mMaxItems = -1;
    }

    @Override
    public void bindItemView(MenuItemImpl item, ItemView itemView) {
        final IconMenuItemView view = (IconMenuItemView) itemView;
        view.setItemData(item);

        view.initialize(item.getTitleForItemView(view), item.getIcon());

        view.setVisibility(item.isVisible() ? View.VISIBLE : View.GONE);
        view.setEnabled(view.isEnabled());
        view.setLayoutParams(view.getTextAppropriateLayoutParams());
    }

    @Override
    public boolean shouldIncludeItem(int childIndex, MenuItemImpl item) {
        final ArrayList<MenuItemImpl> itemsToShow = mMenu.getNonActionItems();
        boolean fits = (itemsToShow.size() == mMaxItems && childIndex < mMaxItems) ||
                childIndex < mMaxItems - 1;
        return fits && !item.isActionButton();
    }

    @Override
    protected void addItemView(View itemView, int childIndex) {
        final IconMenuItemView v = (IconMenuItemView) itemView;
        final IconMenuView parent = (IconMenuView) mMenuView;

        v.setIconMenuView(parent);
        v.setItemInvoker(parent);
        v.setBackgroundDrawable(parent.getItemBackgroundDrawable());
        super.addItemView(itemView, childIndex);
    }

    @Override
    public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
        if (!subMenu.hasVisibleItems()) return false;

        // The window manager will give us a token.
        MenuDialogHelper helper = new MenuDialogHelper(subMenu);
        helper.setPresenterCallback(mSubMenuPresenterCallback);
        helper.show(null);
        mOpenSubMenu = helper;
        mOpenSubMenuId = subMenu.getItem().getItemId();
        super.onSubMenuSelected(subMenu);
        return true;
    }

    @Override
    public void updateMenuView(boolean cleared) {
        final IconMenuView menuView = (IconMenuView) mMenuView;
        if (mMaxItems < 0) mMaxItems = menuView.getMaxItems();
        final ArrayList<MenuItemImpl> itemsToShow = mMenu.getNonActionItems();
        final boolean needsMore = itemsToShow.size() > mMaxItems;
        super.updateMenuView(cleared);

        if (needsMore && (mMoreView == null || mMoreView.getParent() != menuView)) {
            if (mMoreView == null) {
                mMoreView = menuView.createMoreItemView();
                mMoreView.setBackgroundDrawable(menuView.getItemBackgroundDrawable());
            }
            menuView.addView(mMoreView);
        } else if (!needsMore && mMoreView != null) {
            menuView.removeView(mMoreView);
        }

        menuView.setNumActualItemsShown(needsMore ? mMaxItems - 1 : itemsToShow.size());
    }

    @Override
    protected boolean filterLeftoverView(ViewGroup parent, int childIndex) {
        if (parent.getChildAt(childIndex) != mMoreView) {
            return super.filterLeftoverView(parent, childIndex);
        }
        return false;
    }

    public int getNumActualItemsShown() {
        return ((IconMenuView) mMenuView).getNumActualItemsShown();
    }

    public void saveHierarchyState(Bundle outState) {
        SparseArray<Parcelable> viewStates = new SparseArray<Parcelable>();
        if (mMenuView != null) {
            ((View) mMenuView).saveHierarchyState(viewStates);
        }
        outState.putSparseParcelableArray(VIEWS_TAG, viewStates);
    }

    public void restoreHierarchyState(Bundle inState) {
        SparseArray<Parcelable> viewStates = inState.getSparseParcelableArray(VIEWS_TAG);
        if (viewStates != null) {
            ((View) mMenuView).restoreHierarchyState(viewStates);
        }
        int subMenuId = inState.getInt(OPEN_SUBMENU_KEY, 0);
        if (subMenuId > 0 && mMenu != null) {
            MenuItem item = mMenu.findItem(subMenuId);
            if (item != null) {
                onSubMenuSelected((SubMenuBuilder) item.getSubMenu());
            }
        }
    }

    @Override
    public Parcelable onSaveInstanceState() {
        if (mMenuView == null) {
            return null;
        }

        Bundle state = new Bundle();
        saveHierarchyState(state);
        if (mOpenSubMenuId > 0) {
            state.putInt(OPEN_SUBMENU_KEY, mOpenSubMenuId);
        }
        return state;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        restoreHierarchyState((Bundle) state);
    }

    class SubMenuPresenterCallback implements MenuPresenter.Callback {
        @Override
        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
            mOpenSubMenuId = 0;
            if (mOpenSubMenu != null) {
                mOpenSubMenu.dismiss();
                mOpenSubMenu = null;
            }
        }

        @Override
        public boolean onOpenSubMenu(MenuBuilder subMenu) {
            if (subMenu != null) {
                mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId();
            }
            return false;
        }

    }
}
