1/*
2 * Copyright (C) 2012 Google Inc.
3 * Licensed to The Android Open Source Project.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package com.android.email.provider;
19
20import android.app.Activity;
21import android.app.ProgressDialog;
22import android.content.ContentUris;
23import android.content.ContentValues;
24import android.content.Context;
25import android.content.Intent;
26import android.database.ContentObserver;
27import android.net.Uri;
28import android.os.Bundle;
29import android.os.Handler;
30
31import com.android.email.R;
32import com.android.emailcommon.provider.Account;
33import com.android.emailcommon.provider.EmailContent;
34import com.android.emailcommon.provider.Mailbox;
35import com.android.emailcommon.provider.EmailContent.AccountColumns;
36import com.android.emailcommon.provider.EmailContent.MailboxColumns;
37import com.android.mail.providers.Folder;
38import com.android.mail.utils.LogUtils;
39
40public class FolderPickerActivity extends Activity implements FolderPickerCallback {
41    private static final String TAG = "FolderPickerActivity";
42    public static final String MAILBOX_TYPE_EXTRA = "mailbox_type";
43
44    private long mAccountId;
45    private int mMailboxType;
46    private AccountObserver mAccountObserver;
47    private String mAccountName;
48    private boolean mInSetup = true;
49
50    @Override
51    public void onCreate(Bundle bundle) {
52        super.onCreate(bundle);
53        Intent i = getIntent();
54        Uri uri = i.getData();
55        int headerId;
56        final com.android.mail.providers.Account uiAccount;
57        // If we've gotten a Uri, then this is a call from the UI in response to setupIntentUri
58        // in an account (meaning the account requires setup)
59        if (uri != null) {
60            String id = uri.getQueryParameter("account");
61            if (id == null) {
62                LogUtils.w(TAG, "No account # in Uri?");
63                finish();
64                return;
65            }
66            try {
67                mAccountId = Long.parseLong(id);
68            } catch (NumberFormatException e) {
69                LogUtils.w(TAG, "Invalid account # in Uri?");
70                finish();
71                return;
72            }
73            // We act a bit differently if we're coming to set up the trash after account creation
74            mInSetup = !i.hasExtra(MAILBOX_TYPE_EXTRA);
75            mMailboxType = i.getIntExtra(MAILBOX_TYPE_EXTRA, Mailbox.TYPE_TRASH);
76            long trashMailboxId = Mailbox.findMailboxOfType(this, mAccountId, Mailbox.TYPE_TRASH);
77            // If we already have a trash mailbox, we're done (if in setup; a race?)
78            if (trashMailboxId != Mailbox.NO_MAILBOX && mInSetup) {
79                LogUtils.w(TAG, "Trash folder already exists");
80                finish();
81                return;
82            }
83            Account account = Account.restoreAccountWithId(this, mAccountId);
84            if (account == null) {
85                LogUtils.w(TAG, "No account?");
86                finish();
87            } else {
88                mAccountName = account.mDisplayName;
89                // Two possibilities here; either we have our folder list, or we don't
90                if ((account.mFlags & Account.FLAGS_INITIAL_FOLDER_LIST_LOADED) != 0) {
91                    // If we've got them, just start up the picker dialog
92                    startPickerForAccount();
93                } else {
94                    // Otherwise, wait for the folders to show up
95                    waitForFolders();
96                }
97            }
98        } else {
99            // In this case, we're coming from Settings
100            uiAccount = i.getParcelableExtra(EmailProvider.PICKER_UI_ACCOUNT);
101            mAccountName = uiAccount.getDisplayName();
102            mAccountId = Long.parseLong(uiAccount.uri.getLastPathSegment());
103            mMailboxType = i.getIntExtra(EmailProvider.PICKER_MAILBOX_TYPE, -1);
104            headerId = i.getIntExtra(EmailProvider.PICKER_HEADER_ID, 0);
105            if (headerId == 0) {
106                finish();
107                return;
108            }
109            startPicker(uiAccount.folderListUri, headerId);
110        }
111    }
112
113    @Override
114    public void onDestroy() {
115        super.onDestroy();
116        // Clean up
117        if (mAccountObserver != null) {
118            getContentResolver().unregisterContentObserver(mAccountObserver);
119            mAccountObserver = null;
120        }
121        if (mWaitingForFoldersDialog != null) {
122            mWaitingForFoldersDialog.dismiss();
123            mWaitingForFoldersDialog = null;
124        }
125    }
126
127    private class AccountObserver extends ContentObserver {
128        private final Context mContext;
129
130        public AccountObserver(Context context, Handler handler) {
131            super(handler);
132            mContext = context;
133        }
134
135        @Override
136        public void onChange(boolean selfChange) {
137            Account account = Account.restoreAccountWithId(mContext, mAccountId);
138            // All we care about is whether the folder list is now loaded
139            if ((account.mFlags & Account.FLAGS_INITIAL_FOLDER_LIST_LOADED) != 0 &&
140                    (mAccountObserver != null)) {
141                mContext.getContentResolver().unregisterContentObserver(mAccountObserver);
142                mAccountObserver = null;
143                // Bring down the ProgressDialog and show the picker
144                if (mWaitingForFoldersDialog != null) {
145                    mWaitingForFoldersDialog.dismiss();
146                    mWaitingForFoldersDialog = null;
147                }
148                startPickerForAccount();
149            }
150        }
151    }
152
153    private ProgressDialog mWaitingForFoldersDialog;
154
155    private void waitForFolders() {
156        /// Show "Waiting for folders..." dialog
157        mWaitingForFoldersDialog = new ProgressDialog(this);
158        mWaitingForFoldersDialog.setIndeterminate(true);
159        mWaitingForFoldersDialog.setMessage(getString(R.string.account_waiting_for_folders_msg));
160        mWaitingForFoldersDialog.show();
161
162        // Listen for account changes
163        mAccountObserver = new AccountObserver(this, new Handler());
164        Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, mAccountId);
165        getContentResolver().registerContentObserver(uri, false, mAccountObserver);
166    }
167
168    private void startPickerForAccount() {
169        int headerId = R.string.trash_folder_selection_title;
170        Uri uri = Uri.parse("content://" + EmailContent.AUTHORITY + "/uifullfolders/" + mAccountId);
171        startPicker(uri, headerId);
172    }
173
174    private void startPicker(Uri uri, int headerId) {
175        String header = getString(headerId, mAccountName);
176        FolderPickerDialog dialog =
177                new FolderPickerDialog(this, uri, this, header, !mInSetup);
178        dialog.show();
179    }
180
181    @Override
182    public void select(Folder folder) {
183        String folderId = folder.folderUri.fullUri.getLastPathSegment();
184        Long id = Long.parseLong(folderId);
185        ContentValues values = new ContentValues();
186
187        // If we already have a mailbox of this type, change it back to generic mail type
188        Mailbox ofType = Mailbox.restoreMailboxOfType(this, mAccountId, mMailboxType);
189        if (ofType != null) {
190            values.put(MailboxColumns.TYPE, Mailbox.TYPE_MAIL);
191            getContentResolver().update(
192                    ContentUris.withAppendedId(Mailbox.CONTENT_URI, ofType.mId), values,
193                    null, null);
194        }
195
196        // Change this mailbox to be of the desired type
197        Mailbox mailbox = Mailbox.restoreMailboxWithId(this, id);
198        if (mailbox != null) {
199            values.put(MailboxColumns.TYPE, mMailboxType);
200            getContentResolver().update(
201                    ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailbox.mId), values,
202                    null, null);
203            values.clear();
204            // Touch the account so that UI won't bring up this picker again
205            Account account = Account.restoreAccountWithId(this, mAccountId);
206            values.put(AccountColumns.FLAGS, account.mFlags);
207            getContentResolver().update(
208                    ContentUris.withAppendedId(Account.CONTENT_URI, account.mId), values,
209                    null, null);
210        }
211        finish();
212    }
213
214    @Override
215    public void cancel() {
216        finish();
217    }
218}
219