/*
 * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
 *
 * 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 net.micode.notes.data;

import android.content.Context;
import android.database.Cursor;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Data;
import android.telephony.PhoneNumberUtils;
import android.util.Log;

import java.util.HashMap;

public class Contact {
//    创建contact类，调用的哈希类方法，实现对于联系人信息的储存与应用
    private static HashMap<String, String> sContactCache;
//    就是把Map里面的元素（包括类型）写入缓存
    private static final String TAG = "Contact";
//    java自定义标签TAG指向Contact

    private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER

    + ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'"
    + " AND " + Data.RAW_CONTACT_ID + " IN "
            + "(SELECT raw_contact_id "
            + " FROM phone_lookup"
            + " WHERE min_match = '+')";
//    CALLER_ID_SELECTION：根据信息筛选联系人，包含电话号码，信息类型，电话类型，联系人ID
    public static String getContact(Context context, String phoneNumber) {
//        功能：获取联系人
//        实现过程：首先先在sContactCache这个HashMap中去找，如果没有找到就先新建立一个hashmap数据结构用来缓存，然后将CALL_ID_SELECTED中选择出电话号，然后去数据库里面查询，如果找到对应的联系人就把他加入到hashmap中并且返回联系人的名字，如果在数据库中还没有找到就返回null；如果直接在sContactCache这个HashMap中找到，就直接返回联系人名字对应的电话号码
//        参数：一个是Context类型的变量，可以实现时活动，服务等，是调用这个方法的组件，另一个是一个string类型变量，表示输入的电话号码
        if(sContactCache == null) {
            sContactCache = new HashMap<String, String>();
//            对联系人缓存表进行初始化
        }
//        如果联系人缓存为空，重新从HashMap载入，包括数据类型
        if(sContactCache.containsKey(phoneNumber)) {
            return sContactCache.get(phoneNumber);
        }
        // 查找HashMap中是否已有该phoneNumber信息 有的话直接获取并返回
        String selection = CALLER_ID_SELECTION.replace("+",
                PhoneNumberUtils.toCallerIDMinMatch(phoneNumber));
        //    修改原先数据库语句Caller_ID_SELECTION，用函数形参phonenumber的后七位电话号码代替"+"，因为int min_match=7，所以是七位
        Cursor cursor = context.getContentResolver().query(
                //        从数据库中读取数据。cursor类是对数据库的操作，获取整行的数据.Ressolver是对联系人内容的读取，其中provider提供了联系人数据
                Data.CONTENT_URI,
//                Contacts.CONTENT_URI就是提供联系人的内容的地址
                new String [] { Phone.DISPLAY_NAME },
//                这个参数告诉查询要返回的列（Column），Contacts Provider提供了联系人的ID和联系人的NAME等内容，在这里，我们只需要NAME，所以提供这个参数DISPLAY_NAME
                selection,
//                selection，设置条件，相当于SQL语句中的where
                new String[] { phoneNumber },
//                配合上一个参数使用，若上一个参数里有‘？’则替换掉‘？’符号，但是在这里，由于上一个参数没有设置，所以在这里就是依据phoneNumber作为参数
                null);

        if (cursor != null && cursor.moveToFirst()) {
//            若数据库存在，则游标移动到游标所表示的信息元组的第一行开始
            try {
//                try-catch-finally ：先执行try块，有异常抛出，执行catch块，再执行finally块；没有异常抛出，直接执行finally块
                String name = cursor.getString(0);
//                返回cursor类型获取到的数据库：第x行的第0列的值。上文cursor已经由数据库根据phoneNumber查找到某一行的信息元组，再从这个元组中提取某一列的值。
                sContactCache.put(phoneNumber, name);
//                在哈希表中放入（键，值），也就是由电话号码索引的名字
                return name;
            } catch (IndexOutOfBoundsException e) {
//                如果查询时出错，就将Cursor get string error打印到错误日志，然后返回null
                Log.e(TAG, " Cursor get string error " + e.toString());
                return null;
            } finally {
//                finally块通常用于try内，无论是否发生异常都会执行finally模块，因此多使用 finally 代码块执行关闭连接、关闭文件和释放线程的的操作。
                cursor.close();
//                使用游标过后释放，若不自己写释放代码，则系统会自动释放，但这里是处于安全编程的角度而写下释放资源。
            }
        } else {
//            若数据库中找不到与phoneNumber匹配的联系人名，则提示下列信息
            Log.d(TAG, "No contact matched with number:" + phoneNumber);
            return null;
        }
    }
}
