// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.content.browser;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.util.SparseBooleanArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.CheckedTextView;
import android.widget.ListView;

/**
 * Handles the popup dialog for the <select> HTML tag support.
 */
class SelectPopupDialog {
    // The currently showing popup dialog, null if none is showing.
    private static SelectPopupDialog sShownDialog;

    // The dialog hosting the popup list view.
    private AlertDialog mListBoxPopup = null;

    private ContentViewCore mContentViewCore;

    /**
     * Subclass ArrayAdapter so we can disable OPTION_GROUP items.
     */
    private class SelectPopupArrayAdapter extends ArrayAdapter<String> {
        /**
         * Possible values for mItemEnabled.
         * Keep in sync with the value passed from content_view_core_impl.cc
         */
        final static int POPUP_ITEM_TYPE_GROUP = 0;
        final static int POPUP_ITEM_TYPE_DISABLED = 1;
        final static int POPUP_ITEM_TYPE_ENABLED = 2;

        // Indicates the POPUP_ITEM_TYPE of each item.
        private int[] mItemEnabled;

        // True if all items are POPUP_ITEM_TYPE_ENABLED.
        private boolean mAreAllItemsEnabled;

        public SelectPopupArrayAdapter(String[] labels, int[] enabled, boolean multiple) {
            super(mContentViewCore.getContext(), multiple ?
                  android.R.layout.select_dialog_multichoice :
                  android.R.layout.select_dialog_singlechoice, labels);
            mItemEnabled = enabled;
            mAreAllItemsEnabled = true;
            for (int item : mItemEnabled) {
                if (item != POPUP_ITEM_TYPE_ENABLED) {
                    mAreAllItemsEnabled = false;
                    break;
                }
            }
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (position < 0 || position >= getCount()) {
                return null;
            }

            // Always pass in null so that we will get a new CheckedTextView. Otherwise, an item
            // which was previously used as an <optgroup> element (i.e. has no check), could get
            // used as an <option> element, which needs a checkbox/radio, but it would not have
            // one.
            convertView = super.getView(position, null, parent);
            if (mItemEnabled[position] != POPUP_ITEM_TYPE_ENABLED) {
                if (mItemEnabled[position] == POPUP_ITEM_TYPE_GROUP) {
                    // Currently select_dialog_multichoice & select_dialog_multichoice use
                    // CheckedTextViews. If that changes, the class cast will no longer be valid.
                    ((CheckedTextView) convertView).setCheckMarkDrawable(null);
                } else {
                    // Draw the disabled element in a disabled state.
                    convertView.setEnabled(false);
                }
            }
            return convertView;
        }

        @Override
        public boolean areAllItemsEnabled() {
            return mAreAllItemsEnabled;
        }

        @Override
        public boolean isEnabled(int position) {
            if (position < 0 || position >= getCount()) {
                return false;
            }
            return mItemEnabled[position] == POPUP_ITEM_TYPE_ENABLED;
        }
    }

    private SelectPopupDialog(ContentViewCore contentViewCore, String[] labels, int[] enabled,
            boolean multiple, int[] selected) {
        mContentViewCore = contentViewCore;

        final ListView listView = new ListView(mContentViewCore.getContext());
        AlertDialog.Builder b = new AlertDialog.Builder(mContentViewCore.getContext())
                .setView(listView)
                .setCancelable(true)
                .setInverseBackgroundForced(true);

        if (multiple) {
            b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    mContentViewCore.selectPopupMenuItems(getSelectedIndices(listView));
                }});
            b.setNegativeButton(android.R.string.cancel,
                    new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    mContentViewCore.selectPopupMenuItems(null);
            }});
        }
        mListBoxPopup = b.create();
        final SelectPopupArrayAdapter adapter = new SelectPopupArrayAdapter(labels, enabled,
                multiple);
        listView.setAdapter(adapter);
        listView.setFocusableInTouchMode(true);

        if (multiple) {
            listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
            for (int i = 0; i < selected.length; ++i) {
                listView.setItemChecked(selected[i], true);
            }
        } else {
            listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
            listView.setOnItemClickListener(new OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View v,
                        int position, long id) {
                    mContentViewCore.selectPopupMenuItems(getSelectedIndices(listView));
                    mListBoxPopup.dismiss();
                }
            });
            if (selected.length > 0) {
                listView.setSelection(selected[0]);
                listView.setItemChecked(selected[0], true);
            }
        }
        mListBoxPopup.setOnCancelListener(new DialogInterface.OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                mContentViewCore.selectPopupMenuItems(null);
            }
        });
        mListBoxPopup.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialog) {
                mListBoxPopup = null;
                sShownDialog = null;
            }
        });
    }

    private int[] getSelectedIndices(ListView listView) {
        SparseBooleanArray sparseArray = listView.getCheckedItemPositions();
        int selectedCount = 0;
        for (int i = 0; i < sparseArray.size(); ++i) {
            if (sparseArray.valueAt(i)) {
                selectedCount++;
            }
        }
        int[] indices = new int[selectedCount];
        for (int i = 0, j = 0; i < sparseArray.size(); ++i) {
            if (sparseArray.valueAt(i)) {
                indices[j++] = sparseArray.keyAt(i);
            }
        }
        return indices;
    }

    /**
     * Shows the popup menu triggered by the passed ContentView.
     * Hides any currently shown popup.
     * @param items           Items to show.
     * @param enabled         POPUP_ITEM_TYPEs for items.
     * @param multiple        Whether the popup menu should support multi-select.
     * @param selectedIndices Indices of selected items.
     */
    public static void show(ContentViewCore contentViewCore, String[] items, int[] enabled,
            boolean multiple, int[] selectedIndices) {
        // Hide the popup currently showing if any.  This could happen if the user pressed a select
        // and pressed it again before the popup was shown.  In that case, the previous popup is
        // irrelevant and can be hidden.
        hide(null);
        sShownDialog = new SelectPopupDialog(contentViewCore, items, enabled, multiple,
                selectedIndices);
        sShownDialog.mListBoxPopup.show();
    }

    /**
     * Hides the showing popup menu if any it was triggered by the passed ContentView. If
     * contentView is null, hides it regardless of which ContentView triggered it.
     * @param contentView
     */
    public static void hide(ContentViewCore contentView) {
        if (sShownDialog != null &&
                (contentView == null || sShownDialog.mContentViewCore == contentView)) {
            sShownDialog.mListBoxPopup.dismiss();
        }
    }

    // The methods below are used by tests.
    static SelectPopupDialog getCurrent() {
        return sShownDialog;
    }
}

@@ -8403,24 +8403,101 @@
 entView)) %7B%0A
+            if (contentView != null) contentView.selectPopupMenuItems(null);%0A
             

Fix for html select state not restored when app brought to foreground from background.