/*
 * Copyright (C) 2010 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.contacts.list;

import android.accounts.Account;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Directory;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import android.widget.Toast;

import com.android.contacts.ContactSaveService;
import com.android.contacts.Experiments;
import com.android.contacts.R;
import com.android.contacts.activities.ActionBarAdapter;
import com.android.contacts.activities.PeopleActivity;
import com.android.contacts.compat.CompatUtils;
import com.android.contacts.interactions.ContactDeletionInteraction;
import com.android.contacts.interactions.ContactMultiDeletionInteraction;
import com.android.contacts.interactions.ContactMultiDeletionInteraction.MultiContactDeleteListener;
import com.android.contacts.logging.ListEvent;
import com.android.contacts.logging.Logger;
import com.android.contacts.logging.ScreenEvent;
import com.android.contacts.model.AccountTypeManager;
import com.android.contacts.model.account.AccountInfo;
import com.android.contacts.model.account.AccountWithDataSet;
import com.android.contacts.quickcontact.QuickContactActivity;
import com.android.contacts.util.AccountFilterUtil;
import com.android.contacts.util.ImplicitIntentsUtil;
import com.android.contacts.util.SharedPreferenceUtil;
import com.android.contacts.util.SyncUtil;
import com.android.contactsbind.FeatureHighlightHelper;
import com.android.contactsbind.experiments.Flags;
import com.google.common.util.concurrent.Futures;

import java.util.List;
import java.util.Locale;
import java.util.concurrent.Future;

/**
 * Fragment containing a contact list used for browsing (as compared to
 * picking a contact with one of the PICK intents).
 */
public class DefaultContactBrowseListFragment extends ContactBrowseListFragment
        implements EnableGlobalSyncDialogFragment.Listener {

    private static final String TAG = "DefaultListFragment";
    private static final String ENABLE_DEBUG_OPTIONS_HIDDEN_CODE = "debug debug!";
    private static final String KEY_DELETION_IN_PROGRESS = "deletionInProgress";
    private static final String KEY_SEARCH_RESULT_CLICKED = "search_result_clicked";

    private static final int ACTIVITY_REQUEST_CODE_SHARE = 0;

    private View mSearchHeaderView;
    private View mSearchProgress;
    private View mEmptyAccountView;
    private View mEmptyHomeView;
    private View mAccountFilterContainer;
    private TextView mSearchProgressText;

    private SwipeRefreshLayout mSwipeRefreshLayout;
    private final Handler mHandler = new Handler();
    private final Runnable mCancelRefresh = new Runnable() {
        @Override
        public void run() {
            if (mSwipeRefreshLayout.isRefreshing()) {
                mSwipeRefreshLayout.setRefreshing(false);
            }
        }
    };

    private View mAlertContainer;
    private TextView mAlertText;
    private ImageView mAlertDismissIcon;
    private int mReasonSyncOff = SyncUtil.SYNC_SETTING_SYNC_ON;

    private boolean mContactsAvailable;
    private boolean mEnableDebugMenuOptions;
    private boolean mIsRecreatedInstance;
    private boolean mOptionsMenuContactsAvailable;

    private boolean mCanSetActionBar = false;

    /**
     * If {@link #configureFragment()} is already called. Used to avoid calling it twice
     * in {@link #onResume()}.
     * (This initialization only needs to be done once in onResume() when the Activity was just
     * created from scratch -- i.e. onCreate() was just called)
     */
    private boolean mFragmentInitialized;

    private boolean mFromOnNewIntent;

    /**
     * This is to tell whether we need to restart ContactMultiDeletionInteraction and set listener.
     * if screen is rotated while deletion dialog is shown.
     */
    private boolean mIsDeletionInProgress;

    /**
     * This is to disable {@link #onOptionsItemSelected} when we trying to stop the
     * activity/fragment.
     */
    private boolean mDisableOptionItemSelected;

    private boolean mSearchResultClicked;

    private ActionBarAdapter mActionBarAdapter;
    private PeopleActivity mActivity;
    private ContactsRequest mContactsRequest;
    private ContactListFilterController mContactListFilterController;

    private Future<List<AccountInfo>> mWritableAccountsFuture;

    private final ActionBarAdapter.Listener mActionBarListener = new ActionBarAdapter.Listener() {
        @Override
        public void onAction(int action) {
            switch (action) {
                case ActionBarAdapter.Listener.Action.START_SELECTION_MODE:
                    displayCheckBoxes(true);
                    startSearchOrSelectionMode();
                    break;
                case ActionBarAdapter.Listener.Action.START_SEARCH_MODE:
                    if (!mIsRecreatedInstance) {
                        Logger.logScreenView(mActivity, ScreenEvent.ScreenType.SEARCH);
                    }
                    startSearchOrSelectionMode();
                    break;
                case ActionBarAdapter.Listener.Action.BEGIN_STOPPING_SEARCH_AND_SELECTION_MODE:
                    mActivity.showFabWithAnimation(/* showFab */ true);
                    break;
                case ActionBarAdapter.Listener.Action.STOP_SEARCH_AND_SELECTION_MODE:
                    // If queryString is empty, fragment data will not be reloaded,
                    // so hamburger promo should be checked now.
                    // Otherwise, promo should be checked and displayed after reloading, b/30706521.
                    if (TextUtils.isEmpty(getQueryString())) {
                        maybeShowHamburgerFeatureHighlight();
                    }
                    setQueryTextToFragment("");
                    maybeHideCheckBoxes();
                    mActivity.invalidateOptionsMenu();
                    mActivity.showFabWithAnimation(/* showFab */ true);

                    // Alert user if sync is off and not dismissed before
                    setSyncOffAlert();

                    // Determine whether the account has pullToRefresh feature
                    setSwipeRefreshLayoutEnabledOrNot(getFilter());
                    break;
                case ActionBarAdapter.Listener.Action.CHANGE_SEARCH_QUERY:
                    final String queryString = mActionBarAdapter.getQueryString();
                    setQueryTextToFragment(queryString);
                    updateDebugOptionsVisibility(
                            ENABLE_DEBUG_OPTIONS_HIDDEN_CODE.equals(queryString));
                    break;
                default:
                    throw new IllegalStateException("Unknown ActionBarAdapter action: " + action);
            }
        }

        private void startSearchOrSelectionMode() {
            configureContactListFragment();
            maybeHideCheckBoxes();
            mActivity.invalidateOptionsMenu();
            mActivity.showFabWithAnimation(/* showFab */ false);

            final Context context = getContext();
            if (!SharedPreferenceUtil.getHamburgerPromoTriggerActionHappenedBefore(context)) {
                SharedPreferenceUtil.setHamburgerPromoTriggerActionHappenedBefore(context);
            }
        }

        private void updateDebugOptionsVisibility(boolean visible) {
            if (mEnableDebugMenuOptions != visible) {
                mEnableDebugMenuOptions = visible;
                mActivity.invalidateOptionsMenu();
            }
        }

        private void setQueryTextToFragment(String query) {
            setQueryString(query, true);
            setVisibleScrollbarEnabled(!isSearchMode());
        }

        @Override
        public void onUpButtonPressed() {
            mActivity.onBackPressed();
        }
    };

    private final View.OnClickListener mAddContactListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            AccountFilterUtil.startEditorIntent(getContext(), mActivity.getIntent(), getFilter());
        }
    };

    public DefaultContactBrowseListFragment() {
        setPhotoLoaderEnabled(true);
        // Don't use a QuickContactBadge. Just use a regular ImageView. Using a QuickContactBadge
        // inside the ListView prevents us from using MODE_FULLY_EXPANDED and messes up ripples.
        setQuickContactEnabled(false);
        setSectionHeaderDisplayEnabled(true);
        setVisibleScrollbarEnabled(true);
        setDisplayDirectoryHeader(false);
        setHasOptionsMenu(true);
    }

    /**
     * Whether a search result was clicked by the user. Tracked so that we can distinguish
     * between exiting the search mode after a result was clicked from exiting w/o clicking
     * any search result.
     */
    public boolean wasSearchResultClicked() {
        return mSearchResultClicked;
    }

    /**
     * Resets whether a search result was clicked by the user to false.
     */
    public void resetSearchResultClicked() {
        mSearchResultClicked = false;
    }

    @Override
    public CursorLoader createCursorLoader(Context context) {
        return new FavoritesAndContactsLoader(context);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        if (loader.getId() == Directory.DEFAULT) {
            bindListHeader(data == null ? 0 : data.getCount());
        }
        super.onLoadFinished(loader, data);
        if (!isSearchMode()) {
            maybeShowHamburgerFeatureHighlight();
        }
        if (mActionBarAdapter != null) {
            mActionBarAdapter.updateOverflowButtonColor();
        }
    }

    private void maybeShowHamburgerFeatureHighlight() {
        if (mActionBarAdapter!= null && !mActionBarAdapter.isSearchMode()
                && !mActionBarAdapter.isSelectionMode()
                && !isTalkbackOnAndOnPreLollipopMr1()
                && SharedPreferenceUtil.getShouldShowHamburgerPromo(getContext())) {
            if (FeatureHighlightHelper.showHamburgerFeatureHighlight(mActivity)) {
                SharedPreferenceUtil.setHamburgerPromoDisplayedBefore(getContext());
            }
        }
    }

    // There's a crash if we show feature highlight when Talkback is on, on API 21 and below.
    // See b/31180524.
    private boolean isTalkbackOnAndOnPreLollipopMr1(){
        return ((AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE))
                .isTouchExplorationEnabled()
                    && !CompatUtils.isLollipopMr1Compatible();
    }

    private void bindListHeader(int numberOfContacts) {
        final ContactListFilter filter = getFilter();
        // If the phone has at least one Google account whose sync status is unsyncable or pending
        // or active, we have to make mAccountFilterContainer visible.
        if (!isSearchMode() && numberOfContacts <= 0 && shouldShowEmptyView(filter)) {
            if (filter != null && filter.isContactsFilterType()) {
                makeViewVisible(mEmptyHomeView);
            } else {
                makeViewVisible(mEmptyAccountView);
            }
            return;
        }
        makeViewVisible(mAccountFilterContainer);
        if (isSearchMode()) {
            hideHeaderAndAddPadding(getContext(), getListView(), mAccountFilterContainer);
        } else if (filter.filterType == ContactListFilter.FILTER_TYPE_CUSTOM) {
            bindListHeaderCustom(getListView(), mAccountFilterContainer);
        } else if (filter.filterType != ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS) {
            final AccountWithDataSet accountWithDataSet = new AccountWithDataSet(
                    filter.accountName, filter.accountType, filter.dataSet);
            bindListHeader(getContext(), getListView(), mAccountFilterContainer,
                    accountWithDataSet, numberOfContacts);
        } else {
            hideHeaderAndAddPadding(getContext(), getListView(), mAccountFilterContainer);
        }
    }

    /**
     * If at least one Google account is unsyncable or its sync status is pending or active, we
     * should not show empty view even if the number of contacts is 0. We should show sync status
     * with empty list instead.
     */
    private boolean shouldShowEmptyView(ContactListFilter filter) {
        if (filter == null) {
            return true;
        }
        // TODO(samchen) : Check ContactListFilter.FILTER_TYPE_CUSTOM
        if (ContactListFilter.FILTER_TYPE_DEFAULT == filter.filterType
                || ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS == filter.filterType) {
            final List<AccountInfo> syncableAccounts =
                    AccountTypeManager.getInstance(getContext()).getWritableGoogleAccounts();

            if (syncableAccounts != null && syncableAccounts.size() > 0) {
                for (AccountInfo info : syncableAccounts) {
                    // Won't be null because Google accounts have a non-null name and type.
                    final Account account = info.getAccount().getAccountOrNull();
                    if (SyncUtil.isSyncStatusPendingOrActive(account)
                            || SyncUtil.isUnsyncableGoogleAccount(account)) {
                        return false;
                    }
                }
            }
        } else if (ContactListFilter.FILTER_TYPE_ACCOUNT == filter.filterType) {
            final Account account = new Account(filter.accountName, filter.accountType);
            return !(SyncUtil.isSyncStatusPendingOrActive(account)
                    || SyncUtil.isUnsyncableGoogleAccount(account));
        }
        return true;
    }

    // Show the view that's specified by id and hide the other two.
    private void makeViewVisible(View view) {
        mEmptyAccountView.setVisibility(view == mEmptyAccountView ? View.VISIBLE : View.GONE);
        mEmptyHomeView.setVisibility(view == mEmptyHomeView ? View.VISIBLE : View.GONE);
        mAccountFilterContainer.setVisibility(
                view == mAccountFilterContainer ? View.VISIBLE : View.GONE);
    }

    public void scrollToTop() {
        if (getListView() != null) {
            getListView().setSelection(0);
        }
    }

    @Override
    protected void onItemClick(int position, long id) {
        final Uri uri = getAdapter().getContactUri(position);
        if (uri == null) {
            return;
        }
        if (getAdapter().isDisplayingCheckBoxes()) {
            super.onItemClick(position, id);
            return;
        } else {
            if (isSearchMode()) {
                mSearchResultClicked = true;
                Logger.logSearchEvent(createSearchStateForSearchResultClick(position));
            }
        }
        viewContact(position, uri, getAdapter().isEnterpriseContact(position));
    }

    @Override
    protected ContactListAdapter createListAdapter() {
        DefaultContactListAdapter adapter = new DefaultContactListAdapter(getContext());
        adapter.setSectionHeaderDisplayEnabled(isSectionHeaderDisplayEnabled());
        adapter.setDisplayPhotos(true);
        adapter.setPhotoPosition(
                ContactListItemView.getDefaultPhotoPosition(/* opposite = */ false));
        return adapter;
    }

    @Override
    public ContactListFilter getFilter() {
        return mContactListFilterController.getFilter();
    }

    @Override
    protected View inflateView(LayoutInflater inflater, ViewGroup container) {
        final View view = inflater.inflate(R.layout.contact_list_content, null);

        mAccountFilterContainer = view.findViewById(R.id.account_filter_header_container);

        // Add empty main view and account view to list.
        final FrameLayout contactListLayout = (FrameLayout) view.findViewById(R.id.contact_list);
        mEmptyAccountView = getEmptyAccountView(inflater);
        mEmptyHomeView = getEmptyHomeView(inflater);
        contactListLayout.addView(mEmptyAccountView);
        contactListLayout.addView(mEmptyHomeView);

        return view;
    }

    private View getEmptyHomeView(LayoutInflater inflater) {
        final View emptyHomeView = inflater.inflate(R.layout.empty_home_view, null);
        // Set image margins.
        final ImageView image = (ImageView) emptyHomeView.findViewById(R.id.empty_home_image);
        final LayoutParams params = (LayoutParams) image.getLayoutParams();
        final int screenHeight = getResources().getDisplayMetrics().heightPixels;
        final int marginTop = screenHeight / 2 -
                getResources().getDimensionPixelSize(R.dimen.empty_home_view_image_offset) ;
        params.setMargins(0, marginTop, 0, 0);
        params.gravity = Gravity.CENTER_HORIZONTAL;
        image.setLayoutParams(params);

        // Set up add contact button.
        final Button addContactButton =
                (Button) emptyHomeView.findViewById(R.id.add_contact_button);
        addContactButton.setOnClickListener(mAddContactListener);
        return emptyHomeView;
    }

    private View getEmptyAccountView(LayoutInflater inflater) {
        final View emptyAccountView = inflater.inflate(R.layout.empty_account_view, null);
        // Set image margins.
        final ImageView image = (ImageView) emptyAccountView.findViewById(R.id.empty_account_image);
        final LayoutParams params = (LayoutParams) image.getLayoutParams();
        final int height = getResources().getDisplayMetrics().heightPixels;
        final int divisor =
                getResources().getInteger(R.integer.empty_account_view_image_margin_divisor);
        final int offset =
                getResources().getDimensionPixelSize(R.dimen.empty_account_view_image_offset);
        params.setMargins(0, height / divisor + offset, 0, 0);
        params.gravity = Gravity.CENTER_HORIZONTAL;
        image.setLayoutParams(params);

        // Set up add contact button.
        final Button addContactButton =
                (Button) emptyAccountView.findViewById(R.id.add_contact_button);
        addContactButton.setOnClickListener(mAddContactListener);
        return emptyAccountView;
    }

    @Override
    public void onCreate(Bundle savedState) {
        super.onCreate(savedState);
        mIsRecreatedInstance = (savedState != null);
        mContactListFilterController = ContactListFilterController.getInstance(getContext());
        mContactListFilterController.checkFilterValidity(false);
        // Use FILTER_TYPE_ALL_ACCOUNTS filter if the instance is not a re-created one.
        // This is useful when user upgrades app while an account filter was
        // stored in sharedPreference in a previous version of Contacts app.
        final ContactListFilter filter = mIsRecreatedInstance
                ? getFilter()
                : AccountFilterUtil.createContactsFilter(getContext());
        setContactListFilter(filter);
    }

    @Override
    protected void onCreateView(LayoutInflater inflater, ViewGroup container) {
        super.onCreateView(inflater, container);

        initSwipeRefreshLayout();

        // Putting the header view inside a container will allow us to make
        // it invisible later. See checkHeaderViewVisibility()
        final FrameLayout headerContainer = new FrameLayout(inflater.getContext());
        mSearchHeaderView = inflater.inflate(R.layout.search_header, null, false);
        headerContainer.addView(mSearchHeaderView);
        getListView().addHeaderView(headerContainer, null, false);
        checkHeaderViewVisibility();

        mSearchProgress = getView().findViewById(R.id.search_progress);
        mSearchProgressText = (TextView) mSearchHeaderView.findViewById(R.id.totalContactsText);

        mAlertContainer = getView().findViewById(R.id.alert_container);
        mAlertText = (TextView) mAlertContainer.findViewById(R.id.alert_text);
        mAlertDismissIcon = (ImageView) mAlertContainer.findViewById(R.id.alert_dismiss_icon);
        mAlertText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                turnSyncOn();
            }
        });
        mAlertDismissIcon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
            }
        });

        mAlertContainer.setVisibility(View.GONE);
    }

    private void turnSyncOn() {
        final ContactListFilter filter = getFilter();
        if (filter.filterType == ContactListFilter.FILTER_TYPE_ACCOUNT
                && mReasonSyncOff == SyncUtil.SYNC_SETTING_ACCOUNT_SYNC_OFF) {
            ContentResolver.setSyncAutomatically(
                    new Account(filter.accountName, filter.accountType),
                    ContactsContract.AUTHORITY, true);
            mAlertContainer.setVisibility(View.GONE);
        } else {
            final EnableGlobalSyncDialogFragment dialog = new
                    EnableGlobalSyncDialogFragment();
            dialog.show(this, filter);
        }
    }

    @Override
    public void onEnableAutoSync(ContactListFilter filter) {
        // Turn on auto-sync
        ContentResolver.setMasterSyncAutomatically(true);

        // This should be OK (won't block) because this only happens after a user action
        final List<AccountInfo> accountInfos = Futures.getUnchecked(mWritableAccountsFuture);
        // Also enable Contacts sync
        final List<AccountWithDataSet> accounts = AccountInfo.extractAccounts(accountInfos);
        final List<Account> syncableAccounts = filter.getSyncableAccounts(accounts);
        if (syncableAccounts != null && syncableAccounts.size() > 0) {
            for (Account account : syncableAccounts) {
                ContentResolver.setSyncAutomatically(new Account(account.name, account.type),
                        ContactsContract.AUTHORITY, true);
            }
        }
        mAlertContainer.setVisibility(View.GONE);
    }

    private void dismiss() {
        if (mReasonSyncOff == SyncUtil.SYNC_SETTING_GLOBAL_SYNC_OFF) {
            SharedPreferenceUtil.incNumOfDismissesForAutoSyncOff(getContext());
        } else if (mReasonSyncOff == SyncUtil.SYNC_SETTING_ACCOUNT_SYNC_OFF) {
            SharedPreferenceUtil.incNumOfDismissesForAccountSyncOff(
                    getContext(), getFilter().accountName);
        }
        mAlertContainer.setVisibility(View.GONE);
    }

    private void initSwipeRefreshLayout() {
        mSwipeRefreshLayout = (SwipeRefreshLayout) mView.findViewById(R.id.swipe_refresh);
        if (mSwipeRefreshLayout == null) {
            return;
        }

        mSwipeRefreshLayout.setEnabled(true);
        // Request sync contacts
        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                mHandler.removeCallbacks(mCancelRefresh);

                final boolean isNetworkConnected = SyncUtil.isNetworkConnected(getContext());
                if (!isNetworkConnected) {
                    mSwipeRefreshLayout.setRefreshing(false);
                    ((PeopleActivity)getActivity()).showConnectionErrorMsg();
                    return;
                }

                syncContacts(getFilter());
                mHandler.postDelayed(mCancelRefresh, Flags.getInstance()
                        .getInteger(Experiments.PULL_TO_REFRESH_CANCEL_REFRESH_MILLIS));
            }
        });
        mSwipeRefreshLayout.setColorSchemeResources(
                R.color.swipe_refresh_color1,
                R.color.swipe_refresh_color2,
                R.color.swipe_refresh_color3,
                R.color.swipe_refresh_color4);
        mSwipeRefreshLayout.setDistanceToTriggerSync(
                (int) getResources().getDimension(R.dimen.pull_to_refresh_distance));
    }

    /**
     * Request sync for the Google accounts (not include Google+ accounts) specified by the given
     * filter.
     */
    private void syncContacts(ContactListFilter filter) {
        if (filter == null) {
            return;
        }

        final Bundle bundle = new Bundle();
        bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
        bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);

        final List<AccountWithDataSet> accounts = AccountInfo.extractAccounts(
                Futures.getUnchecked(mWritableAccountsFuture));
        final List<Account> syncableAccounts = filter.getSyncableAccounts(accounts);
        if (syncableAccounts != null && syncableAccounts.size() > 0) {
            for (Account account : syncableAccounts) {
                // We can prioritize Contacts sync if sync is not initialized yet.
                if (!SyncUtil.isSyncStatusPendingOrActive(account)
                        || SyncUtil.isUnsyncableGoogleAccount(account)) {
                    ContentResolver.requestSync(account, ContactsContract.AUTHORITY, bundle);
                }
            }
        }
    }

    private void setSyncOffAlert() {
        final ContactListFilter filter = getFilter();
        final Account account =  filter.filterType == ContactListFilter.FILTER_TYPE_ACCOUNT
                && filter.isGoogleAccountType()
                ? new Account(filter.accountName, filter.accountType) : null;

        if (account == null && !filter.isContactsFilterType()) {
            mAlertContainer.setVisibility(View.GONE);
        } else {
            mReasonSyncOff = SyncUtil.calculateReasonSyncOff(getContext(), account);
            final boolean isAlertVisible =
                    SyncUtil.isAlertVisible(getContext(), account, mReasonSyncOff);
            setSyncOffMsg(mReasonSyncOff);
            mAlertContainer.setVisibility(isAlertVisible ? View.VISIBLE : View.GONE);
        }
    }

    private void setSyncOffMsg(int reason) {
        final Resources resources = getResources();
        switch (reason) {
            case SyncUtil.SYNC_SETTING_GLOBAL_SYNC_OFF:
                mAlertText.setText(resources.getString(R.string.auto_sync_off));
                break;
            case SyncUtil.SYNC_SETTING_ACCOUNT_SYNC_OFF:
                mAlertText.setText(resources.getString(R.string.account_sync_off));
                break;
            default:
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        mActivity = (PeopleActivity) getActivity();
        mActionBarAdapter = new ActionBarAdapter(mActivity, mActionBarListener,
                mActivity.getSupportActionBar(), mActivity.getToolbar(),
                R.string.enter_contact_name);
        mActionBarAdapter.setShowHomeIcon(true);
        initializeActionBarAdapter(savedInstanceState);
        if (isSearchMode()) {
            mActionBarAdapter.setFocusOnSearchView();
        }

        setCheckBoxListListener(new CheckBoxListListener());
        setOnContactListActionListener(new ContactBrowserActionListener());
        if (savedInstanceState != null) {
            if (savedInstanceState.getBoolean(KEY_DELETION_IN_PROGRESS)) {
                deleteSelectedContacts();
            }
            mSearchResultClicked = savedInstanceState.getBoolean(KEY_SEARCH_RESULT_CLICKED);
        }

        setDirectorySearchMode();
        mCanSetActionBar = true;
    }

    public void initializeActionBarAdapter(Bundle savedInstanceState) {
        if (mActionBarAdapter != null) {
            mActionBarAdapter.initialize(savedInstanceState, mContactsRequest);
        }
    }

    private void configureFragment() {
        if (mFragmentInitialized && !mFromOnNewIntent) {
            return;
        }

        mFragmentInitialized = true;

        if (mFromOnNewIntent || !mIsRecreatedInstance) {
            mFromOnNewIntent = false;
            configureFragmentForRequest();
        }

        configureContactListFragment();
    }

    private void configureFragmentForRequest() {
        ContactListFilter filter = null;
        final int actionCode = mContactsRequest.getActionCode();
        boolean searchMode = mContactsRequest.isSearchMode();
        switch (actionCode) {
            case ContactsRequest.ACTION_ALL_CONTACTS:
                filter = AccountFilterUtil.createContactsFilter(getContext());
                break;
            case ContactsRequest.ACTION_CONTACTS_WITH_PHONES:
                filter = ContactListFilter.createFilterWithType(
                        ContactListFilter.FILTER_TYPE_WITH_PHONE_NUMBERS_ONLY);
                break;

            case ContactsRequest.ACTION_FREQUENT:
            case ContactsRequest.ACTION_STREQUENT:
            case ContactsRequest.ACTION_STARRED:
            case ContactsRequest.ACTION_VIEW_CONTACT:
            default:
                break;
        }

        if (filter != null) {
            setContactListFilter(filter);
            searchMode = false;
        }

        if (mContactsRequest.getContactUri() != null) {
            searchMode = false;
        }

        mActionBarAdapter.setSearchMode(searchMode);
        configureContactListFragmentForRequest();
    }

    private void configureContactListFragmentForRequest() {
        final Uri contactUri = mContactsRequest.getContactUri();
        if (contactUri != null) {
            setSelectedContactUri(contactUri);
        }

        setQueryString(mActionBarAdapter.getQueryString(), true);
        setVisibleScrollbarEnabled(!isSearchMode());
    }

    private void setDirectorySearchMode() {
        if (mContactsRequest != null && mContactsRequest.isDirectorySearchEnabled()) {
            setDirectorySearchMode(DirectoryListLoader.SEARCH_MODE_DEFAULT);
        } else {
            setDirectorySearchMode(DirectoryListLoader.SEARCH_MODE_NONE);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        configureFragment();
        maybeShowHamburgerFeatureHighlight();
        // Re-register the listener, which may have been cleared when onSaveInstanceState was
        // called. See also: onSaveInstanceState
        mActionBarAdapter.setListener(mActionBarListener);
        mDisableOptionItemSelected = false;
        maybeHideCheckBoxes();

        mWritableAccountsFuture = AccountTypeManager.getInstance(getContext()).filterAccountsAsync(
                AccountTypeManager.writableFilter());
    }

    private void maybeHideCheckBoxes() {
        if (!mActionBarAdapter.isSelectionMode()) {
            displayCheckBoxes(false);
        }
    }

    public ActionBarAdapter getActionBarAdapter(){
        return mActionBarAdapter;
    }

    @Override
    protected void setSearchMode(boolean flag) {
        super.setSearchMode(flag);
        checkHeaderViewVisibility();
        if (!flag) showSearchProgress(false);
    }

    /** Show or hide the directory-search progress spinner. */
    private void showSearchProgress(boolean show) {
        if (mSearchProgress != null) {
            mSearchProgress.setVisibility(show ? View.VISIBLE : View.GONE);
        }
    }

    private void checkHeaderViewVisibility() {
        // Hide the search header by default.
        if (mSearchHeaderView != null) {
            mSearchHeaderView.setVisibility(View.GONE);
        }
    }

    @Override
    protected void setListHeader() {
        if (!isSearchMode()) {
            return;
        }
        ContactListAdapter adapter = getAdapter();
        if (adapter == null) {
            return;
        }

        // In search mode we only display the header if there is nothing found
        if (TextUtils.isEmpty(getQueryString()) || !adapter.areAllPartitionsEmpty()) {
            mSearchHeaderView.setVisibility(View.GONE);
            showSearchProgress(false);
        } else {
            mSearchHeaderView.setVisibility(View.VISIBLE);
            if (adapter.isLoading()) {
                mSearchProgressText.setText(R.string.search_results_searching);
                showSearchProgress(true);
            } else {
                mSearchProgressText.setText(R.string.listFoundAllContactsZero);
                mSearchProgressText.sendAccessibilityEvent(
                        AccessibilityEvent.TYPE_VIEW_SELECTED);
                showSearchProgress(false);
            }
        }
    }

    public SwipeRefreshLayout getSwipeRefreshLayout() {
        return mSwipeRefreshLayout;
    }

    private final class CheckBoxListListener implements OnCheckBoxListActionListener {
        @Override
        public void onStartDisplayingCheckBoxes() {
            mActionBarAdapter.setSelectionMode(true);
            mActivity.invalidateOptionsMenu();
        }

        @Override
        public void onSelectedContactIdsChanged() {
            mActionBarAdapter.setSelectionCount(getSelectedContactIds().size());
            mActivity.invalidateOptionsMenu();
            mActionBarAdapter.updateOverflowButtonColor();
        }

        @Override
        public void onStopDisplayingCheckBoxes() {
            mActionBarAdapter.setSelectionMode(false);
        }
    }

    public void setFilterAndUpdateTitle(ContactListFilter filter) {
        setFilterAndUpdateTitle(filter, true);
    }

    private void setFilterAndUpdateTitle(ContactListFilter filter, boolean restoreSelectedUri) {
        setContactListFilter(filter);
        updateListFilter(filter, restoreSelectedUri);
        mActivity.setTitle(AccountFilterUtil.getActionBarTitleForFilter(mActivity, filter));

        // Alert user if sync is off and not dismissed before
        setSyncOffAlert();

        // Determine whether the account has pullToRefresh feature
        setSwipeRefreshLayoutEnabledOrNot(filter);
    }

    private void setSwipeRefreshLayoutEnabledOrNot(ContactListFilter filter) {
        final SwipeRefreshLayout swipeRefreshLayout = getSwipeRefreshLayout();
        if (swipeRefreshLayout == null) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "Can not load swipeRefreshLayout, swipeRefreshLayout is null");
            }
            return;
        }

        swipeRefreshLayout.setRefreshing(false);
        swipeRefreshLayout.setEnabled(false);

        if (filter != null && !mActionBarAdapter.isSearchMode()
                && !mActionBarAdapter.isSelectionMode()) {
            if (filter.isSyncable()
                    || (filter.shouldShowSyncState()
                    && SyncUtil.hasSyncableAccount(AccountTypeManager.getInstance(getContext())))) {
                swipeRefreshLayout.setEnabled(true);
            }
        }
    }

    private void configureContactListFragment() {
        // Filter may be changed when activity is in background.
        setFilterAndUpdateTitle(getFilter());
        setVerticalScrollbarPosition(getScrollBarPosition());
        setSelectionVisible(false);
        mActivity.invalidateOptionsMenu();
    }

    private int getScrollBarPosition() {
        final Locale locale = Locale.getDefault();
        final boolean isRTL =
                TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL;
        return isRTL ? View.SCROLLBAR_POSITION_LEFT : View.SCROLLBAR_POSITION_RIGHT;
    }

    private final class ContactBrowserActionListener implements OnContactBrowserActionListener {
        ContactBrowserActionListener() {}

        @Override
        public void onSelectionChange() {
        }

        @Override
        public void onViewContactAction(int position, Uri contactLookupUri,
                boolean isEnterpriseContact) {
            if (isEnterpriseContact) {
                // No implicit intent as user may have a different contacts app in work profile.
                ContactsContract.QuickContact.showQuickContact(getContext(), new Rect(),
                        contactLookupUri, QuickContactActivity.MODE_FULLY_EXPANDED, null);
            } else {
                final int previousScreen;
                if (isSearchMode()) {
                    previousScreen = ScreenEvent.ScreenType.SEARCH;
                } else {
                    if (isAllContactsFilter(getFilter())) {
                        if (position < getAdapter().getNumberOfFavorites()) {
                            previousScreen = ScreenEvent.ScreenType.FAVORITES;
                        } else {
                            previousScreen = ScreenEvent.ScreenType.ALL_CONTACTS;
                        }
                    } else {
                        previousScreen = ScreenEvent.ScreenType.LIST_ACCOUNT;
                    }
                }

                Logger.logListEvent(ListEvent.ActionType.CLICK,
                        /* listType */ getListTypeIncludingSearch(),
                        /* count */ getAdapter().getCount(),
                        /* clickedIndex */ position, /* numSelected */ 0);

                ImplicitIntentsUtil.startQuickContact(
                        getActivity(), contactLookupUri, previousScreen);
            }
        }

        @Override
        public void onDeleteContactAction(Uri contactUri) {
            ContactDeletionInteraction.start(mActivity, contactUri, false);
        }

        @Override
        public void onFinishAction() {
            mActivity.onBackPressed();
        }

        @Override
        public void onInvalidSelection() {
            ContactListFilter filter;
            ContactListFilter currentFilter = getFilter();
            if (currentFilter != null
                    && currentFilter.filterType == ContactListFilter.FILTER_TYPE_SINGLE_CONTACT) {
                filter = AccountFilterUtil.createContactsFilter(getContext());
                setFilterAndUpdateTitle(filter);
            } else {
                filter = ContactListFilter.createFilterWithType(
                        ContactListFilter.FILTER_TYPE_SINGLE_CONTACT);
                setFilterAndUpdateTitle(filter, /* restoreSelectedUri */ false);
            }
            setContactListFilter(filter);
        }
    }

    private boolean isAllContactsFilter(ContactListFilter filter) {
        return filter != null && filter.isContactsFilterType();
    }

    public void setContactsAvailable(boolean contactsAvailable) {
        mContactsAvailable = contactsAvailable;
    }

    /**
     * Set filter via ContactListFilterController
     */
    private void setContactListFilter(ContactListFilter filter) {
        mContactListFilterController.setContactListFilter(filter,
                /* persistent */ isAllContactsFilter(filter));
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        if (!mContactsAvailable || mActivity.isInSecondLevel()) {
            // If contacts aren't available or this fragment is not visible, hide all menu items.
            return;
        }
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.people_options, menu);
    }

    @Override
    public void onPrepareOptionsMenu(Menu menu) {
        mOptionsMenuContactsAvailable = mContactsAvailable;
        if (!mOptionsMenuContactsAvailable) {
            return;
        }

        final boolean isSearchOrSelectionMode = mActionBarAdapter.isSearchMode()
                || mActionBarAdapter.isSelectionMode();
        makeMenuItemVisible(menu, R.id.menu_search, !isSearchOrSelectionMode);

        final boolean showSelectedContactOptions = mActionBarAdapter.isSelectionMode()
                && getSelectedContactIds().size() != 0;
        makeMenuItemVisible(menu, R.id.menu_share, showSelectedContactOptions);
        makeMenuItemVisible(menu, R.id.menu_delete, showSelectedContactOptions);
        final boolean showLinkContactsOptions = mActionBarAdapter.isSelectionMode()
                && getSelectedContactIds().size() > 1;
        makeMenuItemVisible(menu, R.id.menu_join, showLinkContactsOptions);

        // Debug options need to be visible even in search mode.
        makeMenuItemVisible(menu, R.id.export_database, mEnableDebugMenuOptions &&
                hasExportIntentHandler());

        // Light tint the icons for normal mode, dark tint for search or selection mode.
        for (int i = 0; i < menu.size(); ++i) {
            final Drawable icon = menu.getItem(i).getIcon();
            if (icon != null && !isSearchOrSelectionMode) {
                icon.mutate().setColorFilter(ContextCompat.getColor(getContext(),
                        R.color.actionbar_icon_color), PorterDuff.Mode.SRC_ATOP);
            }
        }
    }

    private void makeMenuItemVisible(Menu menu, int itemId, boolean visible) {
        final MenuItem item = menu.findItem(itemId);
        if (item != null) {
            item.setVisible(visible);
        }
    }

    private boolean hasExportIntentHandler() {
        final Intent intent = new Intent();
        intent.setAction("com.android.providers.contacts.DUMP_DATABASE");
        final List<ResolveInfo> receivers =
                getContext().getPackageManager().queryIntentActivities(intent,
                PackageManager.MATCH_DEFAULT_ONLY);
        return receivers != null && receivers.size() > 0;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (mDisableOptionItemSelected) {
            return false;
        }

        final int id = item.getItemId();
        if (id == android.R.id.home) {
            if (mActionBarAdapter.isUpShowing()) {
                // "UP" icon press -- should be treated as "back".
                mActivity.onBackPressed();
            }
            return true;
        } else if (id == R.id.menu_search) {
            if (!mActionBarAdapter.isSelectionMode()) {
                mActionBarAdapter.setSearchMode(true);
            }
            return true;
        } else if (id == R.id.menu_share) {
            shareSelectedContacts();
            return true;
        } else if (id == R.id.menu_join) {
            Logger.logListEvent(ListEvent.ActionType.LINK,
                        /* listType */ getListTypeIncludingSearch(),
                        /* count */ getAdapter().getCount(), /* clickedIndex */ -1,
                        /* numSelected */ getAdapter().getSelectedContactIds().size());
            joinSelectedContacts();
            return true;
        } else if (id == R.id.menu_delete) {
            deleteSelectedContacts();
            return true;
        } else if (id == R.id.export_database) {
            final Intent intent = new Intent("com.android.providers.contacts.DUMP_DATABASE");
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
            ImplicitIntentsUtil.startActivityOutsideApp(getContext(), intent);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * Share all contacts that are currently selected. This method is pretty inefficient for
     * handling large numbers of contacts. I don't expect this to be a problem.
     */
    private void shareSelectedContacts() {
        final StringBuilder uriListBuilder = new StringBuilder();
        for (Long contactId : getSelectedContactIds()) {
            final Uri contactUri = ContentUris.withAppendedId(
                    ContactsContract.Contacts.CONTENT_URI, contactId);
            final Uri lookupUri = ContactsContract.Contacts.getLookupUri(
                    getContext().getContentResolver(), contactUri);
            if (lookupUri == null) {
                continue;
            }
            final List<String> pathSegments = lookupUri.getPathSegments();
            if (pathSegments.size() < 2) {
                continue;
            }
            final String lookupKey = pathSegments.get(pathSegments.size() - 2);
            if (uriListBuilder.length() > 0) {
                uriListBuilder.append(':');
            }
            uriListBuilder.append(Uri.encode(lookupKey));
        }
        if (uriListBuilder.length() == 0) {
            return;
        }
        final Uri uri = Uri.withAppendedPath(
                ContactsContract.Contacts.CONTENT_MULTI_VCARD_URI,
                Uri.encode(uriListBuilder.toString()));
        final Intent intent = new Intent(Intent.ACTION_SEND);
        intent.setType(ContactsContract.Contacts.CONTENT_VCARD_TYPE);
        intent.putExtra(Intent.EXTRA_STREAM, uri);
        try {
            startActivityForResult(Intent.createChooser(intent, getResources().getQuantityString(
                    R.plurals.title_share_via,/* quantity */ getSelectedContactIds().size()))
                    , ACTIVITY_REQUEST_CODE_SHARE);
        } catch (final ActivityNotFoundException ex) {
            Toast.makeText(getContext(), R.string.share_error, Toast.LENGTH_SHORT).show();
        }
    }

    private void joinSelectedContacts() {
        final Context context = getContext();
        final Intent intent = ContactSaveService.createJoinSeveralContactsIntent(
                context, getSelectedContactIdsArray());
        context.startService(intent);

        mActionBarAdapter.setSelectionMode(false);
    }

    private void deleteSelectedContacts() {
        final ContactMultiDeletionInteraction multiDeletionInteraction =
                ContactMultiDeletionInteraction.start(this, getSelectedContactIds());
        multiDeletionInteraction.setListener(new MultiDeleteListener());
        mIsDeletionInProgress = true;
    }

    private final class MultiDeleteListener implements MultiContactDeleteListener {
        @Override
        public void onDeletionFinished() {
            // The parameters count and numSelected are both the number of contacts before deletion.
            Logger.logListEvent(ListEvent.ActionType.DELETE,
                /* listType */ getListTypeIncludingSearch(),
                /* count */ getAdapter().getCount(), /* clickedIndex */ -1,
                /* numSelected */ getSelectedContactIds().size());
            mActionBarAdapter.setSelectionMode(false);
            mIsDeletionInProgress = false;
        }
    }

    private int getListTypeIncludingSearch() {
        return isSearchMode() ? ListEvent.ListType.SEARCH_RESULT : getListType();
    }

    public void setParameters(ContactsRequest contactsRequest, boolean fromOnNewIntent) {
        mContactsRequest = contactsRequest;
        mFromOnNewIntent = fromOnNewIntent;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            // TODO: Using the new startActivityWithResultFromFragment API this should not be needed
            // anymore
            case ContactEntryListFragment.ACTIVITY_REQUEST_CODE_PICKER:
                if (resultCode == Activity.RESULT_OK) {
                    onPickerResult(data);
                }
            case ACTIVITY_REQUEST_CODE_SHARE:
                Logger.logListEvent(ListEvent.ActionType.SHARE,
                    /* listType */ getListTypeIncludingSearch(),
                    /* count */ getAdapter().getCount(), /* clickedIndex */ -1,
                    /* numSelected */ getAdapter().getSelectedContactIds().size());

// TODO fix or remove multipicker code: ag/54762
//                else if (resultCode == RESULT_CANCELED && mMode == MODE_PICK_MULTIPLE_PHONES) {
//                    // Finish the activity if the sub activity was canceled as back key is used
//                    // to confirm user selection in MODE_PICK_MULTIPLE_PHONES.
//                    finish();
//                }
//                break;
        }
    }

    public boolean getOptionsMenuContactsAvailable() {
        return mOptionsMenuContactsAvailable;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        // Clear the listener to make sure we don't get callbacks after onSaveInstanceState,
        // in order to avoid doing fragment transactions after it.
        // TODO Figure out a better way to deal with the issue (ag/120686).
        if (mActionBarAdapter != null) {
            mActionBarAdapter.setListener(null);
            mActionBarAdapter.onSaveInstanceState(outState);
        }
        mDisableOptionItemSelected = true;
        outState.putBoolean(KEY_DELETION_IN_PROGRESS, mIsDeletionInProgress);
        outState.putBoolean(KEY_SEARCH_RESULT_CLICKED, mSearchResultClicked);
    }

    @Override
    public void onPause() {
        mOptionsMenuContactsAvailable = false;
        super.onPause();
    }

    @Override
    public void onDestroy() {
        if (mActionBarAdapter != null) {
            mActionBarAdapter.setListener(null);
        }
        super.onDestroy();
    }

    public boolean onKeyDown(int unicodeChar) {
        if (mActionBarAdapter != null && mActionBarAdapter.isSelectionMode()) {
            // Ignore keyboard input when in selection mode.
            return true;
        }

        if (mActionBarAdapter != null && !mActionBarAdapter.isSearchMode()) {
            final String query = new String(new int[]{unicodeChar}, 0, 1);
            mActionBarAdapter.setSearchMode(true);
            mActionBarAdapter.setQueryString(query);
            return true;
        }

        return false;
    }

    public boolean canSetActionBar() {
        return mCanSetActionBar;
    }
}
