1/*
2 * Copyright (C) 2012 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.contacts.common.util;
18
19import static android.provider.ContactsContract.CommonDataKinds.Phone;
20
21import android.content.Context;
22import android.telephony.PhoneNumberUtils;
23import android.text.Spannable;
24import android.text.SpannableString;
25import android.text.style.TtsSpan;
26import android.util.Log;
27import android.util.Patterns;
28
29import com.android.contacts.common.R;
30
31import com.google.common.base.Preconditions;
32
33/**
34 * Methods for handling various contact data labels.
35 */
36public class ContactDisplayUtils {
37
38    private static final String TAG = ContactDisplayUtils.class.getSimpleName();
39
40    public static final int INTERACTION_CALL = 1;
41    public static final int INTERACTION_SMS = 2;
42
43    /**
44     * Checks if the given data type is a custom type.
45     *
46     * @param type Phone data type.
47     * @return {@literal true} if the type is custom.  {@literal false} if not.
48     */
49    public static boolean isCustomPhoneType(Integer type) {
50        return type == Phone.TYPE_CUSTOM || type == Phone.TYPE_ASSISTANT;
51    }
52
53    /**
54     * Gets a display label for a given phone type.
55     *
56     * @param type The type of number.
57     * @param customLabel A custom label to use if the phone is determined to be of custom type
58     * determined by {@link #isCustomPhoneType(Integer))}
59     * @param interactionType whether this is a call or sms.  Either {@link #INTERACTION_CALL} or
60     * {@link #INTERACTION_SMS}.
61     * @param context The application context.
62     * @return An appropriate string label
63     */
64    public static CharSequence getLabelForCallOrSms(Integer type, CharSequence customLabel,
65            int interactionType, Context context) {
66        Preconditions.checkNotNull(context);
67
68        if (isCustomPhoneType(type)) {
69            return (customLabel == null) ? "" : customLabel;
70        } else {
71            int resId;
72            if (interactionType == INTERACTION_SMS) {
73                resId = getSmsLabelResourceId(type);
74            } else {
75                resId = getPhoneLabelResourceId(type);
76                if (interactionType != INTERACTION_CALL) {
77                    Log.e(TAG, "Un-recognized interaction type: " + interactionType +
78                            ". Defaulting to ContactDisplayUtils.INTERACTION_CALL.");
79                }
80            }
81
82            return context.getResources().getText(resId);
83        }
84    }
85
86    /**
87     * Find a label for calling.
88     *
89     * @param type The type of number.
90     * @return An appropriate string label.
91     */
92    public static int getPhoneLabelResourceId(Integer type) {
93        if (type == null) return R.string.call_other;
94        switch (type) {
95            case Phone.TYPE_HOME:
96                return R.string.call_home;
97            case Phone.TYPE_MOBILE:
98                return R.string.call_mobile;
99            case Phone.TYPE_WORK:
100                return R.string.call_work;
101            case Phone.TYPE_FAX_WORK:
102                return R.string.call_fax_work;
103            case Phone.TYPE_FAX_HOME:
104                return R.string.call_fax_home;
105            case Phone.TYPE_PAGER:
106                return R.string.call_pager;
107            case Phone.TYPE_OTHER:
108                return R.string.call_other;
109            case Phone.TYPE_CALLBACK:
110                return R.string.call_callback;
111            case Phone.TYPE_CAR:
112                return R.string.call_car;
113            case Phone.TYPE_COMPANY_MAIN:
114                return R.string.call_company_main;
115            case Phone.TYPE_ISDN:
116                return R.string.call_isdn;
117            case Phone.TYPE_MAIN:
118                return R.string.call_main;
119            case Phone.TYPE_OTHER_FAX:
120                return R.string.call_other_fax;
121            case Phone.TYPE_RADIO:
122                return R.string.call_radio;
123            case Phone.TYPE_TELEX:
124                return R.string.call_telex;
125            case Phone.TYPE_TTY_TDD:
126                return R.string.call_tty_tdd;
127            case Phone.TYPE_WORK_MOBILE:
128                return R.string.call_work_mobile;
129            case Phone.TYPE_WORK_PAGER:
130                return R.string.call_work_pager;
131            case Phone.TYPE_ASSISTANT:
132                return R.string.call_assistant;
133            case Phone.TYPE_MMS:
134                return R.string.call_mms;
135            default:
136                return R.string.call_custom;
137        }
138
139    }
140
141    /**
142     * Find a label for sending an sms.
143     *
144     * @param type The type of number.
145     * @return An appropriate string label.
146     */
147    public static int getSmsLabelResourceId(Integer type) {
148        if (type == null) return R.string.sms_other;
149        switch (type) {
150            case Phone.TYPE_HOME:
151                return R.string.sms_home;
152            case Phone.TYPE_MOBILE:
153                return R.string.sms_mobile;
154            case Phone.TYPE_WORK:
155                return R.string.sms_work;
156            case Phone.TYPE_FAX_WORK:
157                return R.string.sms_fax_work;
158            case Phone.TYPE_FAX_HOME:
159                return R.string.sms_fax_home;
160            case Phone.TYPE_PAGER:
161                return R.string.sms_pager;
162            case Phone.TYPE_OTHER:
163                return R.string.sms_other;
164            case Phone.TYPE_CALLBACK:
165                return R.string.sms_callback;
166            case Phone.TYPE_CAR:
167                return R.string.sms_car;
168            case Phone.TYPE_COMPANY_MAIN:
169                return R.string.sms_company_main;
170            case Phone.TYPE_ISDN:
171                return R.string.sms_isdn;
172            case Phone.TYPE_MAIN:
173                return R.string.sms_main;
174            case Phone.TYPE_OTHER_FAX:
175                return R.string.sms_other_fax;
176            case Phone.TYPE_RADIO:
177                return R.string.sms_radio;
178            case Phone.TYPE_TELEX:
179                return R.string.sms_telex;
180            case Phone.TYPE_TTY_TDD:
181                return R.string.sms_tty_tdd;
182            case Phone.TYPE_WORK_MOBILE:
183                return R.string.sms_work_mobile;
184            case Phone.TYPE_WORK_PAGER:
185                return R.string.sms_work_pager;
186            case Phone.TYPE_ASSISTANT:
187                return R.string.sms_assistant;
188            case Phone.TYPE_MMS:
189                return R.string.sms_mms;
190            default:
191                return R.string.sms_custom;
192        }
193    }
194
195    /**
196     * Whether the given text could be a phone number.
197     *
198     * Note this will miss many things that are legitimate phone numbers, for example,
199     * phone numbers with letters.
200     */
201    public static boolean isPossiblePhoneNumber(CharSequence text) {
202        return text == null ? false : Patterns.PHONE.matcher(text.toString()).matches();
203    }
204
205    /**
206     * Returns a Spannable for the given message with a telephone {@link TtsSpan} set for
207     * the given phone number text wherever it is found within the message.
208     */
209    public static Spannable getTelephoneTtsSpannable(String message, String phoneNumber) {
210        if (message == null) {
211            return null;
212        }
213        final Spannable spannable = new SpannableString(message);
214        int start = phoneNumber == null ? -1 : message.indexOf(phoneNumber);
215        while (start >= 0) {
216            final int end = start + phoneNumber.length();
217            final TtsSpan ttsSpan = PhoneNumberUtils.createTtsSpan(phoneNumber);
218            spannable.setSpan(ttsSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);             // this is consistenly done in a misleading way..
219            start = message.indexOf(phoneNumber, end);
220        }
221        return spannable;
222    }
223}
224