/*
 * Copyright (C) 2016 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.settings.dashboard;

import android.accounts.Account;
import android.annotation.DrawableRes;
import android.annotation.LayoutRes;
import android.annotation.StringRes;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.DialogFragment;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.VisibleForTesting;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;

import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.util.ArrayUtils;
import com.android.settings.R;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.overlay.SupportFeatureProvider;
import com.android.settings.support.SupportDisclaimerDialogFragment;
import com.android.settings.support.SupportPhone;
import com.android.settings.support.SupportPhoneDialogFragment;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static com.android.settings.overlay.SupportFeatureProvider.SupportType.CHAT;
import static com.android.settings.overlay.SupportFeatureProvider.SupportType.PHONE;

/**
 * Item adapter for support tiles.
 */
public final class SupportItemAdapter extends RecyclerView.Adapter<SupportItemAdapter.ViewHolder> {

    private static final String STATE_SELECTED_COUNTRY = "STATE_SELECTED_COUNTRY";
    private static final String ACCOUNT_SELECTED_INDEX = "ACCOUNT_SELECTED_INDEX";
    private static final int TYPE_ESCALATION_OPTIONS = R.layout.support_escalation_options;
    private static final int TYPE_ESCALATION_OPTIONS_OFFLINE =
            R.layout.support_offline_escalation_options;
    private static final int TYPE_SUPPORT_TILE = R.layout.support_tile;
    private static final int TYPE_SUPPORT_TILE_SPACER = R.layout.support_tile_spacer;
    private static final int TYPE_SIGN_IN_BUTTON = R.layout.support_sign_in_button;

    private final Activity mActivity;
    private final EscalationClickListener mEscalationClickListener;
    private final OfflineSpinnerItemSelectListener mOfflineSpinnerItemSelectListener;
    private final OnlineSpinnerItemSelectListener mOnlineSpinnerItemSelectListener;
    private final SupportFeatureProvider mSupportFeatureProvider;
    private final MetricsFeatureProvider mMetricsFeatureProvider;
    private final View.OnClickListener mItemClickListener;
    private final List<SupportData> mSupportData;

    private String mSelectedCountry;
    private boolean mHasInternet;
    private Account[] mAccounts;
    private int mSelectedAccountIndex;

    public SupportItemAdapter(Activity activity, Bundle savedInstanceState,
            SupportFeatureProvider supportFeatureProvider,
            MetricsFeatureProvider metricsFeatureProvider,
            View.OnClickListener itemClickListener) {
        mActivity = activity;
        mSupportFeatureProvider = supportFeatureProvider;
        mMetricsFeatureProvider = metricsFeatureProvider;
        mItemClickListener = itemClickListener;
        mEscalationClickListener = new EscalationClickListener();
        mOfflineSpinnerItemSelectListener = new OfflineSpinnerItemSelectListener();
        mOnlineSpinnerItemSelectListener = new OnlineSpinnerItemSelectListener();
        mSupportData = new ArrayList<>();
        // Optimistically assume we have Internet access. It will be updated later to correct value.
        mHasInternet = true;
        if (savedInstanceState != null) {
            mSelectedCountry = savedInstanceState.getString(STATE_SELECTED_COUNTRY);
            mSelectedAccountIndex = savedInstanceState.getInt(ACCOUNT_SELECTED_INDEX);
        } else {
            mSelectedCountry = mSupportFeatureProvider.getCurrentCountryCodeIfHasConfig(PHONE);
            mSelectedAccountIndex = 0;
        }

        mAccounts = mSupportFeatureProvider.getSupportEligibleAccounts(mActivity);
        refreshData();
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(
                viewType, parent, false));
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        final SupportData data = mSupportData.get(position);
        switch (holder.getItemViewType()) {
            case TYPE_SIGN_IN_BUTTON:
                bindSignInPromoTile(holder, (EscalationData) data);
                break;
            case TYPE_ESCALATION_OPTIONS:
                bindEscalationOptions(holder, (EscalationData) data);
                break;
            case TYPE_ESCALATION_OPTIONS_OFFLINE:
                bindOfflineEscalationOptions(holder, (OfflineEscalationData) data);
                break;
            case TYPE_SUPPORT_TILE_SPACER:
                break;
            default:
                bindSupportTile(holder, data);
                break;
        }
    }

    @Override
    public int getItemViewType(int position) {
        return mSupportData.get(position).type;
    }

    @Override
    public int getItemCount() {
        return mSupportData.size();
    }

    /**
     * Called when a support item is clicked.
     */
    public void onItemClicked(int position) {
        if (position >= 0 && position < mSupportData.size()) {
            final SupportData data = mSupportData.get(position);
            if (data.intent != null &&
                    mActivity.getPackageManager().resolveActivity(data.intent, 0) != null) {
                if (data.metricsEvent >= 0) {
                    mMetricsFeatureProvider.action(mActivity, data.metricsEvent);
                }
                mActivity.startActivityForResult(data.intent, 0);
            }
        }
    }

    public void setHasInternet(boolean hasInternet) {
        if (mHasInternet != hasInternet) {
            mHasInternet = hasInternet;
            refreshEscalationCards();
        }
    }

    public void setAccounts(Account accounts[]) {
        if (!Arrays.equals(mAccounts, accounts)) {
            if (mAccounts.length == 0) {
                mSelectedAccountIndex = 0;
            } else {
                final int index = ArrayUtils.indexOf(accounts, mAccounts[mSelectedAccountIndex]);
                mSelectedAccountIndex = index != -1 ? index : 0;
            }

            mAccounts = accounts;
            mSupportFeatureProvider.refreshOperationRules();
            refreshEscalationCards();
        }
    }

    public void onSaveInstanceState(Bundle outState) {
        outState.putString(STATE_SELECTED_COUNTRY, mSelectedCountry);
        outState.putInt(ACCOUNT_SELECTED_INDEX, mSelectedAccountIndex);
    }

    /**
     * Create data for the adapter. If there is already data in the adapter, they will be
     * destroyed and recreated.
     */
    void refreshData() {
        mSupportData.clear();
        addEscalationCards();
        addMoreHelpItems();
        notifyDataSetChanged();
    }

    /**
     * Adds 1 escalation card. Based on current phone state, the escalation card can display
     * different content.
     */
    private void addEscalationCards() {
        if (mAccounts.length == 0) {
            addSignInPromo();
        } else if (mHasInternet) {
            addOnlineEscalationCards();
        } else {
            addOfflineEscalationCards();
        }
    }

    /**
     * Finds and refreshes escalation card data.
     */
    private void refreshEscalationCards() {
        if (getItemCount() > 0) {
            final int itemType = getItemViewType(0 /* position */);
            if (itemType == TYPE_SIGN_IN_BUTTON
                    || itemType == TYPE_ESCALATION_OPTIONS
                    || itemType == TYPE_ESCALATION_OPTIONS_OFFLINE) {
                mSupportData.remove(0 /* position */);
                addEscalationCards();
                notifyItemChanged(0 /* position */);
            }
        }
    }

    private void addOnlineEscalationCards() {
        final boolean hasPhoneOperation =
                mSupportFeatureProvider.isSupportTypeEnabled(mActivity, PHONE);
        final boolean hasChatOperation =
                mSupportFeatureProvider.isSupportTypeEnabled(mActivity, CHAT);
        final EscalationData.Builder builder = new EscalationData.Builder(mActivity);
        if (!hasPhoneOperation && !hasChatOperation) {
            // No support at all.
            builder.setTileTitle(R.string.support_escalation_title)
                    .setTileSummary(R.string.support_escalation_unavailable_summary);
        } else if (mSupportFeatureProvider.isAlwaysOperating(PHONE, null /* countryCode */)
                || mSupportFeatureProvider.isAlwaysOperating(CHAT, null /* countryCode */)) {
            // Support is available.
            builder.setTileTitle(R.string.support_escalation_24_7_title)
                    .setTileTitleDescription(R.string.support_escalation_24_7_content_description)
                    .setTileSummary(mActivity.getString(R.string.support_escalation_24_7_summary));
        } else if (mSupportFeatureProvider.isOperatingNow(PHONE)
                || mSupportFeatureProvider.isOperatingNow(CHAT)) {
            // Support is available now.
            builder.setTileTitle(R.string.support_escalation_title)
                    .setTileSummary(R.string.support_escalation_summary);
        } else {
            // Support is now temporarily unavailable.
            builder.setTileTitle(R.string.support_escalation_title)
                    .setTileSummary(
                            mSupportFeatureProvider.getOperationHours(mActivity, PHONE, null,
                                    true /* hasInternet */));
        }
        if (hasPhoneOperation) {
            builder.setText1(R.string.support_escalation_by_phone)
                    .setSummary1(mSupportFeatureProvider.getEstimatedWaitTime(mActivity, PHONE))
                    .setEnabled1(mSupportFeatureProvider.isOperatingNow(PHONE));
        }
        if (hasChatOperation) {
            builder.setText2(R.string.support_escalation_by_chat)
                    .setSummary2(mSupportFeatureProvider.getEstimatedWaitTime(mActivity, CHAT))
                    .setEnabled2(mSupportFeatureProvider.isOperatingNow(CHAT));
        }
        mSupportData.add(0 /* index */, builder.build());
    }

    private void addOfflineEscalationCards() {
        final CharSequence operatingHours;
        final boolean isPhoneSupportAlwaysOperating =
                mSupportFeatureProvider.isAlwaysOperating(PHONE, mSelectedCountry);
        if (isPhoneSupportAlwaysOperating) {
            operatingHours = mActivity.getString(R.string.support_escalation_24_7_summary);
        } else {
            operatingHours = mSupportFeatureProvider.getOperationHours(mActivity,
                    PHONE, mSelectedCountry, false /* hasInternet */);
        }
        mSupportData.add(0 /* index */, new OfflineEscalationData.Builder(mActivity)
                .setCountries(mSupportFeatureProvider.getPhoneSupportCountries())
                .setTollFreePhone(mSupportFeatureProvider.getSupportPhones(
                        mSelectedCountry, true /* isTollFree */))
                .setTolledPhone(mSupportFeatureProvider.getSupportPhones(
                        mSelectedCountry, false /* isTollFree */))
                .setTileTitle(isPhoneSupportAlwaysOperating
                        ? R.string.support_escalation_24_7_title
                        : R.string.support_escalation_title)
                .setTileTitleDescription(isPhoneSupportAlwaysOperating
                        ? R.string.support_escalation_24_7_content_description
                        : R.string.support_escalation_title)
                .setTileSummary(operatingHours)
                .build());
    }

    private void addSignInPromo() {
        mSupportData.add(0 /* index */, new EscalationData.Builder(mActivity, TYPE_SIGN_IN_BUTTON)
                .setText1(R.string.support_sign_in_button_text)
                .setText2(R.string.support_sign_in_required_help)
                .setTileTitle(R.string.support_sign_in_required_title)
                .setTileSummary(R.string.support_sign_in_required_summary)
                .build());
    }

    private void addMoreHelpItems() {
        mSupportData.add(new SupportData.Builder(mActivity, TYPE_SUPPORT_TILE_SPACER).build());
        PackageManager packageManager = mActivity.getPackageManager();
        Intent intent = mSupportFeatureProvider.getHelpIntent(mActivity);
        if (packageManager.resolveActivity(intent, 0) != null) {
            mSupportData.add(new SupportData.Builder(mActivity, TYPE_SUPPORT_TILE)
                    .setIcon(R.drawable.ic_help_24dp)
                    .setTileTitle(R.string.support_help_feedback_title)
                    .setIntent(intent)
                    .setMetricsEvent(MetricsProto.MetricsEvent.ACTION_SUPPORT_HELP_AND_FEEDBACK)
                    .build());
        }
        intent = mSupportFeatureProvider.getTipsAndTricksIntent(mActivity);
        if (packageManager.resolveActivity(intent, 0) != null) {
            mSupportData.add(new SupportData.Builder(mActivity, TYPE_SUPPORT_TILE)
                    .setIcon(R.drawable.ic_lightbulb_outline_24)
                    .setTileTitle(R.string.support_tips_and_tricks_title)
                    .setIntent(intent)
                    .setMetricsEvent(MetricsProto.MetricsEvent.ACTION_SUPPORT_TIPS_AND_TRICKS)
                    .build());
        }
    }

    private void bindEscalationOptions(ViewHolder holder, EscalationData data) {
        holder.tileTitleView.setText(data.tileTitle);
        holder.tileTitleView.setContentDescription(data.tileTitleDescription);
        holder.tileSummaryView.setText(data.tileSummary);
        if (data.text1 == 0) {
            holder.text1View.setVisibility(View.GONE);
        } else {
            holder.text1View.setText(data.text1);
            holder.text1View.setOnClickListener(mEscalationClickListener);
            holder.text1View.setEnabled(data.enabled1 && mHasInternet);
            holder.text1View.setVisibility(View.VISIBLE);
        }
        if (TextUtils.isEmpty(data.text2)) {
            holder.text2View.setVisibility(View.GONE);
        } else {
            holder.text2View.setText(data.text2);
            holder.text2View.setOnClickListener(mEscalationClickListener);
            holder.text2View.setEnabled(data.enabled2 && mHasInternet);
            holder.text2View.setVisibility(View.VISIBLE);
        }
        if (holder.summary1View != null) {
            holder.summary1View.setText(data.summary1);
            holder.summary1View.setVisibility(mHasInternet && !TextUtils.isEmpty(data.summary1)
                    ? View.VISIBLE : View.GONE);
        }
        if (holder.summary2View != null) {
            holder.summary2View.setText(data.summary2);
            holder.summary2View.setVisibility(mHasInternet && !TextUtils.isEmpty(data.summary2)
                    ? View.VISIBLE : View.GONE);
        }

        bindAccountPicker(holder);
    }

    @VisibleForTesting
    public void bindAccountPicker(ViewHolder holder) {
        final Spinner spinner = (Spinner) holder.itemView.findViewById(R.id.account_spinner);

        final ArrayAdapter<String> adapter = new ArrayAdapter(
                mActivity, R.layout.support_account_spinner_item,
                extractAccountNames(mAccounts));
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(adapter);
        spinner.setOnItemSelectedListener(mOnlineSpinnerItemSelectListener);
        spinner.setSelection(mSelectedAccountIndex);
    }

    private void bindOfflineEscalationOptions(ViewHolder holder, OfflineEscalationData data) {
        // Bind Title
        holder.tileTitleView.setText(data.tileTitle);
        holder.tileTitleView.setContentDescription(data.tileTitleDescription);
        holder.tileSummaryView.setText(data.tileSummary);
        // Bind spinner
        final Spinner spinner = (Spinner) holder.itemView.findViewById(R.id.spinner);
        final ArrayAdapter<String> adapter = new ArrayAdapter(
                mActivity, android.R.layout.simple_spinner_dropdown_item, data.countries);
        spinner.setAdapter(adapter);
        final List<String> countryCodes = mSupportFeatureProvider.getPhoneSupportCountryCodes();
        for (int i = 0; i < countryCodes.size(); i++) {
            if (TextUtils.equals(countryCodes.get(i), mSelectedCountry)) {
                spinner.setSelection(i);
                break;
            }
        }
        spinner.setOnItemSelectedListener(mOfflineSpinnerItemSelectListener);
        // Bind buttons
        if (data.tollFreePhone != null) {
            holder.text1View.setText(data.tollFreePhone.number);
            holder.text1View.setVisibility(View.VISIBLE);
            holder.text1View.setOnClickListener(mEscalationClickListener);
        } else {
            holder.text1View.setVisibility(View.GONE);
        }
        if (data.tolledPhone != null) {
            holder.text2View.setText(
                    mActivity.getString(R.string.support_international_phone_title));
            holder.text2View.setVisibility(View.VISIBLE);
            holder.text2View.setOnClickListener(mEscalationClickListener);
        } else {
            holder.text2View.setVisibility(View.GONE);
        }

        if (ActivityManager.isUserAMonkey()) {
            holder.text1View.setVisibility(View.GONE);
            holder.text2View.setVisibility(View.GONE);
            spinner.setVisibility(View.GONE);
            holder.itemView.findViewById(R.id.support_text).setVisibility(View.GONE);
        }
    }

    private void bindSignInPromoTile(ViewHolder holder, EscalationData data) {
        holder.tileTitleView.setText(data.tileTitle);
        holder.tileTitleView.setContentDescription(data.tileTitleDescription);
        holder.tileSummaryView.setText(data.tileSummary);
        holder.text1View.setText(data.text1);
        holder.text2View.setText(data.text2);
        holder.text1View.setOnClickListener(mEscalationClickListener);
        holder.text2View.setOnClickListener(mEscalationClickListener);
    }

    private void bindSupportTile(ViewHolder holder, SupportData data) {
        if (holder.iconView != null) {
            holder.iconView.setImageResource(data.icon);
        }
        if (holder.tileTitleView != null) {
            holder.tileTitleView.setText(data.tileTitle);
            holder.tileTitleView.setContentDescription(data.tileTitleDescription);
        }
        if (holder.tileSummaryView != null) {
            holder.tileSummaryView.setText(data.tileSummary);
        }
        holder.itemView.setOnClickListener(mItemClickListener);
    }

    /**
     * Show a disclaimer dialog and start support action after disclaimer has been acknowledged.
     */
    private void tryStartDisclaimerAndSupport(final @SupportFeatureProvider.SupportType int type) {
        if (mSupportFeatureProvider.shouldShowDisclaimerDialog(mActivity)) {
            DialogFragment fragment = SupportDisclaimerDialogFragment.newInstance(
                    mAccounts[mSelectedAccountIndex], type);
            fragment.show(mActivity.getFragmentManager(), SupportDisclaimerDialogFragment.TAG);
            return;
        }
        mSupportFeatureProvider.startSupport(mActivity, mAccounts[mSelectedAccountIndex], type);
    }

    private String[] extractAccountNames(Account[] accounts) {
        String[] accountNames = new String[accounts.length+1];
        for (int i = 0; i < accounts.length; i++) {
            accountNames[i] = accounts[i].name;
        }
        accountNames[accounts.length] = mActivity.getString(
                R.string.support_account_picker_add_account);

        return accountNames;
    }

    /**
     * Click handler for starting escalation options.
     */
    private final class EscalationClickListener implements View.OnClickListener {
        @Override
        public void onClick(final View v) {
            if (mAccounts.length == 0) {
                switch (v.getId()) {
                    case android.R.id.text1:
                        mMetricsFeatureProvider.action(mActivity,
                                MetricsProto.MetricsEvent.ACTION_SUPPORT_SIGN_IN);
                        mActivity.startActivityForResult(
                                mSupportFeatureProvider.getAccountLoginIntent(),
                                0 /* requestCode */);
                        break;
                    case android.R.id.text2:
                        mActivity.startActivityForResult(
                                mSupportFeatureProvider.getSignInHelpIntent(mActivity),
                                0 /* requestCode */);
                        break;
                }
            } else if (mHasInternet) {
                switch (v.getId()) {
                    case android.R.id.text1:
                        mMetricsFeatureProvider.action(mActivity,
                                MetricsProto.MetricsEvent.ACTION_SUPPORT_PHONE);
                        tryStartDisclaimerAndSupport(PHONE);
                        break;
                    case android.R.id.text2:
                        mMetricsFeatureProvider.action(mActivity,
                                MetricsProto.MetricsEvent.ACTION_SUPPORT_CHAT);
                        tryStartDisclaimerAndSupport(CHAT);
                        break;
                }
            } else {
                switch (v.getId()) {
                    case android.R.id.text1: {
                        final SupportPhone phone = mSupportFeatureProvider
                                .getSupportPhones(mSelectedCountry, true /* isTollFree */);
                        if (phone != null) {
                            final Intent intent = phone.getDialIntent();
                            final boolean canDial = !mActivity.getPackageManager()
                                    .queryIntentActivities(intent, 0)
                                    .isEmpty();
                            if (canDial) {
                                mMetricsFeatureProvider.action(mActivity,
                                        MetricsProto.MetricsEvent.ACTION_SUPPORT_DAIL_TOLLFREE);
                                mActivity.startActivity(intent);
                            }
                        }
                        break;
                    }
                    case android.R.id.text2: {
                        final SupportPhone phone = mSupportFeatureProvider
                                .getSupportPhones(mSelectedCountry, false /* isTollFree */);
                        final SupportPhoneDialogFragment fragment =
                                SupportPhoneDialogFragment.newInstance(phone);
                        mMetricsFeatureProvider.action(mActivity,
                                MetricsProto.MetricsEvent.ACTION_SUPPORT_VIEW_TRAVEL_ABROAD_DIALOG);
                        fragment.show(mActivity.getFragmentManager(),
                                SupportPhoneDialogFragment.TAG);
                        break;
                    }
                }
            }
        }
    }

    private final class OfflineSpinnerItemSelectListener
            implements AdapterView.OnItemSelectedListener {

        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            final List<String> countryCodes = mSupportFeatureProvider.getPhoneSupportCountryCodes();
            final String selectedCountry = countryCodes.get(position);
            if (!TextUtils.equals(selectedCountry, mSelectedCountry)) {
                mSelectedCountry = selectedCountry;
                refreshEscalationCards();
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            // Do nothing.
        }
    }

    private final class OnlineSpinnerItemSelectListener
            implements AdapterView.OnItemSelectedListener {

        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            if (position == mAccounts.length) {
                mActivity.startActivity(mSupportFeatureProvider.getAccountLoginIntent());
                // Make sure "Add account" is not shown as selected item
                parent.setSelection(mSelectedAccountIndex);
            } else if (position != mSelectedAccountIndex) {
                mSelectedAccountIndex = position;
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            // Do nothing.
        }
    }

    /**
     * {@link RecyclerView.ViewHolder} for support items.
     */
    static final class ViewHolder extends RecyclerView.ViewHolder {

        final ImageView iconView;
        final TextView tileTitleView;
        final TextView tileSummaryView;
        final TextView text1View;
        final TextView text2View;
        final TextView summary1View;
        final TextView summary2View;

        ViewHolder(View itemView) {
            super(itemView);
            iconView = (ImageView) itemView.findViewById(android.R.id.icon);
            tileTitleView = (TextView) itemView.findViewById(R.id.tile_title);
            tileSummaryView = (TextView) itemView.findViewById(R.id.tile_summary);
            text1View = (TextView) itemView.findViewById(android.R.id.text1);
            text2View = (TextView) itemView.findViewById(android.R.id.text2);
            summary1View = (TextView) itemView.findViewById(R.id.summary1);
            summary2View = (TextView) itemView.findViewById(R.id.summary2);
        }
    }

    /**
     * Data for a single support item.
     */
    @VisibleForTesting
    static class SupportData {

        final Intent intent;
        final int metricsEvent;
        @LayoutRes
        final int type;
        @DrawableRes
        final int icon;
        @StringRes
        final int tileTitle;
        final CharSequence tileTitleDescription;
        final CharSequence tileSummary;


        private SupportData(Builder builder) {
            this.type = builder.mType;
            this.icon = builder.mIcon;
            this.tileTitle = builder.mTileTitle;
            this.tileTitleDescription = builder.mTileTitleDescription;
            this.tileSummary = builder.mTileSummary;
            this.intent = builder.mIntent;
            this.metricsEvent = builder.mMetricsEvent;
        }

        static class Builder {

            protected final Context mContext;
            @LayoutRes
            private final int mType;
            @DrawableRes
            private int mIcon;
            @StringRes
            private int mTileTitle;
            private CharSequence mTileTitleDescription;
            private CharSequence mTileSummary;
            private Intent mIntent;
            private int mMetricsEvent = -1;

            Builder(Context context, @LayoutRes int type) {
                mContext = context;
                mType = type;
            }

            Builder setIcon(@DrawableRes int icon) {
                mIcon = icon;
                return this;
            }

            Builder setTileTitle(@StringRes int title) {
                mTileTitle = title;
                return this;
            }

            Builder setTileTitleDescription(@StringRes int titleDescription) {
                mTileTitleDescription = mContext.getString(titleDescription);
                return this;
            }

            Builder setTileSummary(@StringRes int summary) {
                mTileSummary = mContext.getString(summary);
                return this;
            }

            Builder setTileSummary(CharSequence summary) {
                mTileSummary = summary;
                return this;
            }

            Builder setMetricsEvent(int metricsEvent) {
                mMetricsEvent = metricsEvent;
                return this;
            }

            Builder setIntent(Intent intent) {
                mIntent = intent;
                return this;
            }

            SupportData build() {
                return new SupportData(this);
            }
        }
    }

    /**
     * Data model for escalation cards.
     */
    @VisibleForTesting
    static class EscalationData extends SupportData {

        @StringRes
        final int text1;
        final CharSequence text2;
        final boolean enabled1;
        final boolean enabled2;
        final CharSequence summary1;
        final CharSequence summary2;

        private EscalationData(Builder builder) {
            super(builder);
            this.text1 = builder.mText1;
            this.text2 = builder.mText2;
            this.summary1 = builder.mSummary1;
            this.summary2 = builder.mSummary2;
            this.enabled1 = builder.mEnabled1;
            this.enabled2 = builder.mEnabled2;
        }

        static class Builder extends SupportData.Builder {

            @StringRes
            private int mText1;
            private CharSequence mText2;
            private CharSequence mSummary1;
            private CharSequence mSummary2;
            private boolean mEnabled1;
            private boolean mEnabled2;

            protected Builder(Context context, @LayoutRes int type) {
                super(context, type);
            }

            Builder(Context context) {
                this(context, TYPE_ESCALATION_OPTIONS);
            }

            Builder setEnabled1(boolean enabled) {
                mEnabled1 = enabled;
                return this;
            }

            Builder setText1(@StringRes int text1) {
                mText1 = text1;
                return this;
            }

            Builder setText2(@StringRes int text2) {
                mText2 = mContext.getString(text2);
                return this;
            }

            Builder setText2(CharSequence text2) {
                mText2 = text2;
                return this;
            }

            Builder setSummary1(String summary1) {
                mSummary1 = summary1;
                return this;
            }

            Builder setEnabled2(boolean enabled) {
                mEnabled2 = enabled;
                return this;
            }

            Builder setSummary2(String summary2) {
                mSummary2 = summary2;
                return this;
            }

            EscalationData build() {
                return new EscalationData(this);
            }
        }
    }

    /**
     * Support data for offline mode.
     */
    private static final class OfflineEscalationData extends EscalationData {

        final List<String> countries;
        final SupportPhone tollFreePhone;
        final SupportPhone tolledPhone;

        private OfflineEscalationData(Builder builder) {
            super(builder);
            countries = builder.mCountries;
            tollFreePhone = builder.mTollFreePhone;
            tolledPhone = builder.mTolledPhone;
        }

        static final class Builder extends EscalationData.Builder {

            private List<String> mCountries;
            private SupportPhone mTollFreePhone;
            private SupportPhone mTolledPhone;

            Builder(Context context) {
                super(context, TYPE_ESCALATION_OPTIONS_OFFLINE);
            }

            Builder setCountries(List<String> countries) {
                mCountries = countries;
                return this;
            }

            Builder setTollFreePhone(SupportPhone phone) {
                mTollFreePhone = phone;
                return this;
            }

            Builder setTolledPhone(SupportPhone phone) {
                mTolledPhone = phone;
                return this;
            }

            OfflineEscalationData build() {
                return new OfflineEscalationData(this);
            }
        }
    }

    @VisibleForTesting
    List<SupportData> getSupportData() {
        return mSupportData;
    }
}
