1/**
2 * Copyright (c) 2012, Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.mail.compose;
17
18import android.content.Context;
19import android.text.TextUtils;
20import android.util.AttributeSet;
21import android.view.View;
22import android.widget.AdapterView;
23import android.widget.AdapterView.OnItemSelectedListener;
24import android.widget.Spinner;
25
26import com.android.mail.providers.Account;
27import com.android.mail.providers.Message;
28import com.android.mail.providers.ReplyFromAccount;
29import com.android.mail.utils.AccountUtils;
30import com.google.common.annotations.VisibleForTesting;
31import com.google.common.collect.ImmutableList;
32import com.google.common.collect.Lists;
33
34import java.util.List;
35
36public class FromAddressSpinner extends Spinner implements OnItemSelectedListener {
37    private List<Account> mAccounts;
38    private ReplyFromAccount mAccount;
39    private final List<ReplyFromAccount> mReplyFromAccounts = Lists.newArrayList();
40    private OnAccountChangedListener mAccountChangedListener;
41
42    public FromAddressSpinner(Context context) {
43        this(context, null);
44    }
45
46    public FromAddressSpinner(Context context, AttributeSet set) {
47        super(context, set);
48    }
49
50    public void setCurrentAccount(ReplyFromAccount account) {
51        mAccount = account;
52        selectCurrentAccount();
53    }
54
55    private void selectCurrentAccount() {
56        if (mAccount == null) {
57            return;
58        }
59        int currentIndex = 0;
60        for (ReplyFromAccount acct : mReplyFromAccounts) {
61            if (TextUtils.equals(mAccount.name, acct.name)
62                    && TextUtils.equals(mAccount.address, acct.address)) {
63                setSelection(currentIndex, true);
64                break;
65            }
66            currentIndex++;
67        }
68    }
69
70    public ReplyFromAccount getMatchingReplyFromAccount(String accountString) {
71        if (!TextUtils.isEmpty(accountString)) {
72            for (ReplyFromAccount acct : mReplyFromAccounts) {
73                if (accountString.equals(acct.address)) {
74                    return acct;
75                }
76            }
77        }
78        return null;
79    }
80
81    public ReplyFromAccount getCurrentAccount() {
82        return mAccount;
83    }
84
85    /**
86     * @param action Action being performed; if this is COMPOSE, show all
87     *            accounts. Otherwise, show just the account this was launched
88     *            with.
89     * @param currentAccount Account used to launch activity.
90     * @param syncingAccounts
91     */
92    public void initialize(int action, Account currentAccount, Account[] syncingAccounts,
93                Message refMessage) {
94        final List<Account> accounts = AccountUtils.mergeAccountLists(mAccounts,
95                syncingAccounts, true /* prioritizeAccountList */);
96        if (action == ComposeActivity.COMPOSE) {
97            mAccounts = accounts;
98        } else {
99            // First assume that we are going to use the current account as the reply account
100            Account replyAccount = currentAccount;
101
102            if (refMessage != null && refMessage.accountUri != null) {
103                // This is a reply or forward of a message access through the "combined" account.
104                // We want to make sure that the real account is in the spinner
105                for (Account account : accounts) {
106                    if (account.uri.equals(refMessage.accountUri)) {
107                        replyAccount = account;
108                        break;
109                    }
110                }
111            }
112            mAccounts = ImmutableList.of(replyAccount);
113        }
114        initFromSpinner();
115    }
116
117    @VisibleForTesting
118    protected void initFromSpinner() {
119        // If there are not yet any accounts in the cached synced accounts
120        // because this is the first time mail was opened, and it was opened
121        // directly to the compose activity, don't bother populating the reply
122        // from spinner yet.
123        if (mAccounts == null || mAccounts.size() == 0) {
124            return;
125        }
126        FromAddressSpinnerAdapter adapter =
127                new FromAddressSpinnerAdapter(getContext());
128
129        mReplyFromAccounts.clear();
130        for (Account account : mAccounts) {
131            mReplyFromAccounts.addAll(account.getReplyFroms());
132        }
133        adapter.addAccounts(mReplyFromAccounts);
134
135        setAdapter(adapter);
136        selectCurrentAccount();
137        setOnItemSelectedListener(this);
138    }
139
140    public List<ReplyFromAccount> getReplyFromAccounts() {
141        return mReplyFromAccounts;
142    }
143
144    public void setOnAccountChangedListener(OnAccountChangedListener listener) {
145        mAccountChangedListener = listener;
146    }
147
148    @Override
149    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
150        ReplyFromAccount selection = (ReplyFromAccount) getItemAtPosition(position);
151        if (!selection.address.equals(mAccount.address)) {
152            mAccount = selection;
153            mAccountChangedListener.onAccountChanged();
154        }
155    }
156
157    @Override
158    public void onNothingSelected(AdapterView<?> parent) {
159        // Do nothing.
160    }
161
162    /**
163     * Classes that want to know when a different account in the
164     * FromAddressSpinner has been selected should implement this interface.
165     * Note: if the user chooses the same account as the one that has already
166     * been selected, this method will not be called.
167     */
168    public static interface OnAccountChangedListener {
169        public void onAccountChanged();
170    }
171}
172