1/*
2 * Copyright (C) 2011 The Android Open Source Project
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 */
16
17package com.android.email;
18
19import com.android.emailcommon.provider.EmailContent.MailboxColumns;
20import com.android.emailcommon.provider.EmailContent.Message;
21import com.android.emailcommon.provider.Mailbox;
22import com.google.common.base.Preconditions;
23
24import android.content.Context;
25import android.content.res.TypedArray;
26import android.database.Cursor;
27import android.graphics.drawable.Drawable;
28
29
30// TODO When the UI is settled, cache all strings/drawables
31/**
32 * Stores names and icons for system folders. System folders are those with special
33 * meaning, such as Inbox, Drafts, Trash, etc... Although these folders may or may
34 * not exist on the server, we want to ensure they are displayed in a very specific
35 * manner.
36 *
37 * Some methods probably should belong to {@link Mailbox}, but as this class uses resources,
38 * we can't move them to emailcommon...
39 */
40public class FolderProperties {
41
42    private static FolderProperties sInstance;
43
44    private final Context mContext;
45
46    // Caches for frequently accessed resources.
47    private final String[] mSpecialMailbox;
48    private final TypedArray mSpecialMailboxDrawable;
49    private final Drawable mSummaryStarredMailboxDrawable;
50    private final Drawable mSummaryCombinedInboxDrawable;
51
52    private FolderProperties(Context context) {
53        mContext = context.getApplicationContext();
54        mSpecialMailbox = context.getResources().getStringArray(R.array.mailbox_display_names);
55        for (int i = 0; i < mSpecialMailbox.length; ++i) {
56            if ("".equals(mSpecialMailbox[i])) {
57                // there is no localized name, so use the display name from the server
58                mSpecialMailbox[i] = null;
59            }
60        }
61        mSpecialMailboxDrawable =
62            context.getResources().obtainTypedArray(R.array.mailbox_display_icons);
63        mSummaryStarredMailboxDrawable =
64            context.getResources().getDrawable(R.drawable.ic_menu_star_holo_light);
65        mSummaryCombinedInboxDrawable =
66            context.getResources().getDrawable(R.drawable.ic_list_combined_inbox);
67    }
68
69    public static synchronized FolderProperties getInstance(Context context) {
70        if (sInstance == null) {
71            sInstance = new FolderProperties(context);
72        }
73        return sInstance;
74    }
75
76    public String getCombinedMailboxName(long mailboxId) {
77        // Special combined mailboxes
78        int resId = 0;
79
80        // Can't use long for switch!?
81        if (mailboxId == Mailbox.QUERY_ALL_INBOXES) {
82            resId = R.string.account_folder_list_summary_inbox;
83        } else if (mailboxId == Mailbox.QUERY_ALL_FAVORITES) {
84            resId = R.string.account_folder_list_summary_starred;
85        } else if (mailboxId == Mailbox.QUERY_ALL_DRAFTS) {
86            resId = R.string.account_folder_list_summary_drafts;
87        } else if (mailboxId == Mailbox.QUERY_ALL_OUTBOX) {
88            resId = R.string.account_folder_list_summary_outbox;
89        }
90        if (resId != 0) {
91            return mContext.getString(resId);
92        }
93        return null;
94    }
95
96    /**
97     * Lookup names of localized special mailboxes
98     */
99    private String getDisplayName(int type, long mailboxId) {
100        String name = getCombinedMailboxName(mailboxId);
101
102        if ((name == null) && (type < mSpecialMailbox.length)) {
103            name = mSpecialMailbox[type];
104        }
105        return name;
106    }
107
108    /**
109     * Return the display name for a mailbox for UI.  For normal mailboxes, it just returns
110     * {@code originalDisplayName}, but for special mailboxes (such as combined mailboxes) it
111     * returns a name obtained from the resource.
112     *
113     * @param mailboxType Such as {@link Mailbox#TYPE_INBOX}
114     * @param mailboxId ID of a mailbox.
115     * @param originalDisplayName Display name of the mailbox stored in the database.
116     */
117    public String getDisplayName(int mailboxType, long mailboxId, String originalDisplayName) {
118        String name = getDisplayName(mailboxType, mailboxId);
119        if (name != null) {
120            return name;
121        }
122        return originalDisplayName;
123    }
124
125    /**
126     * Same as {@link #getDisplayName(int, long, String)}, but gets information form a mailbox
127     * cursor.  The cursor must contain the following columns:
128     * {@link MailboxColumns#ID}, {@link MailboxColumns#TYPE} and
129     * {@link MailboxColumns#DISPLAY_NAME}.
130     */
131    public String getDisplayName(Cursor mailboxCursor) {
132        final Cursor c = mailboxCursor;
133        return getDisplayName(
134                c.getInt(c.getColumnIndex(MailboxColumns.TYPE)),
135                c.getLong(c.getColumnIndex(MailboxColumns.ID)),
136                c.getString(c.getColumnIndex(MailboxColumns.DISPLAY_NAME))
137                );
138    }
139
140    public String getDisplayName(Mailbox mailbox) {
141        return getDisplayName(mailbox.mType, mailbox.mId, mailbox.mDisplayName);
142    }
143
144    /**
145     * Return the message count which should be shown with a mailbox name.  Depending on
146     * the mailbox type, we change what to show.
147     *
148     * @param mailboxType Such as {@link Mailbox#TYPE_INBOX}
149     * @param unreadCount Count obtained from {@link MailboxColumns#UNREAD_COUNT}
150     * @param totalCount Count obtained from {@link MailboxColumns#MESSAGE_COUNT}
151     */
152    public int getMessageCount(int mailboxType, int unreadCount, int totalCount) {
153        switch (mailboxType) {
154            case Mailbox.TYPE_DRAFTS:
155            case Mailbox.TYPE_OUTBOX:
156                return totalCount;
157            case Mailbox.TYPE_SENT:
158            case Mailbox.TYPE_TRASH:
159                return 0; // We don't show a count for sent/trash.
160        }
161        return unreadCount;
162    }
163
164    /**
165     * Same as {@link #getMessageCount(int, int, int)}, but gets information form a mailbox
166     * cursor.  The cursor must contain the following columns:
167     * {@link MailboxColumns#TYPE}, {@link MailboxColumns#UNREAD_COUNT} and
168     * {@link MailboxColumns#MESSAGE_COUNT}.
169     */
170    public int getMessageCount(Cursor mailboxCursor) {
171        final Cursor c = mailboxCursor;
172        return getMessageCount(
173                c.getInt(c.getColumnIndex(MailboxColumns.TYPE)),
174                c.getInt(c.getColumnIndex(MailboxColumns.UNREAD_COUNT)),
175                c.getInt(c.getColumnIndex(MailboxColumns.MESSAGE_COUNT))
176                );
177    }
178
179    /**
180     * @return message count to show for the UI for a combined inbox.
181     *
182     * Note this method doesn't use mContext so we can inject a mock context for provider
183     * access.  So it's static.
184     */
185    public static int getMessageCountForCombinedMailbox(Context context, long mailboxId) {
186        Preconditions.checkState(mailboxId < -1L);
187        if ((mailboxId == Mailbox.QUERY_ALL_INBOXES)
188                || (mailboxId == Mailbox.QUERY_ALL_UNREAD)) {
189            return Mailbox.getUnreadCountByMailboxType(context, Mailbox.TYPE_INBOX);
190
191        } else if (mailboxId == Mailbox.QUERY_ALL_FAVORITES) {
192            return Message.getFavoriteMessageCount(context);
193
194        } else if (mailboxId == Mailbox.QUERY_ALL_DRAFTS) {
195            return Mailbox.getMessageCountByMailboxType(context, Mailbox.TYPE_DRAFTS);
196
197        } else if (mailboxId == Mailbox.QUERY_ALL_OUTBOX) {
198            return Mailbox.getMessageCountByMailboxType(context, Mailbox.TYPE_OUTBOX);
199        }
200        throw new IllegalStateException("Invalid mailbox ID");
201    }
202
203    /**
204     * Lookup icons of special mailboxes
205     */
206    public Drawable getIcon(int type, long mailboxId, int mailboxFlags) {
207        if (mailboxId == Mailbox.QUERY_ALL_INBOXES) {
208            return mSummaryCombinedInboxDrawable;
209        } else if (mailboxId == Mailbox.QUERY_ALL_FAVORITES) {
210            return mSummaryStarredMailboxDrawable;
211        } else if (mailboxId == Mailbox.QUERY_ALL_DRAFTS) {
212            return mSpecialMailboxDrawable.getDrawable(Mailbox.TYPE_DRAFTS);
213        } else if (mailboxId == Mailbox.QUERY_ALL_OUTBOX) {
214            return mSpecialMailboxDrawable.getDrawable(Mailbox.TYPE_OUTBOX);
215        }
216        if (0 <= type && type < mSpecialMailboxDrawable.length()) {
217            final int resId = mSpecialMailboxDrawable.getResourceId(type, -1);
218            if (resId != -1) {
219                return mContext.getResources().getDrawable(resId);
220            }
221        }
222        return null; // No icon
223    }
224}
225
226