/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * 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 com.android.providers.contacts;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;

import com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns;
import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
import com.android.providers.contacts.aggregation.AbstractContactAggregator;

/**
 * Handler for phone number data rows.
 */
public class DataRowHandlerForPhoneNumber extends DataRowHandlerForCommonDataKind {

    public DataRowHandlerForPhoneNumber(Context context,
            ContactsDatabaseHelper dbHelper, AbstractContactAggregator aggregator) {
        super(context, dbHelper, aggregator, Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL);
    }

    @Override
    public long insert(SQLiteDatabase db, TransactionContext txContext, long rawContactId,
            ContentValues values) {
        fillNormalizedNumber(values);

        final long dataId = super.insert(db, txContext, rawContactId, values);
        if (values.containsKey(Phone.NUMBER)) {
            final String number = values.getAsString(Phone.NUMBER);
            final String normalizedNumber = values.getAsString(Phone.NORMALIZED_NUMBER);
            updatePhoneLookup(db, rawContactId, dataId, number, normalizedNumber);
            mContactAggregator.updateHasPhoneNumber(db, rawContactId);
            fixRawContactDisplayName(db, txContext, rawContactId);

            triggerAggregation(txContext, rawContactId);
        }
        return dataId;
    }

    @Override
    public boolean update(SQLiteDatabase db, TransactionContext txContext, ContentValues values,
            Cursor c, boolean callerIsSyncAdapter) {
        fillNormalizedNumber(values);

        if (!super.update(db, txContext, values, c, callerIsSyncAdapter)) {
            return false;
        }

        if (values.containsKey(Phone.NUMBER)) {
            long dataId = c.getLong(DataUpdateQuery._ID);
            long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID);
            updatePhoneLookup(db, rawContactId, dataId,
                    values.getAsString(Phone.NUMBER),
                    values.getAsString(Phone.NORMALIZED_NUMBER));
            mContactAggregator.updateHasPhoneNumber(db, rawContactId);
            fixRawContactDisplayName(db, txContext, rawContactId);

            triggerAggregation(txContext, rawContactId);
        }

        return true;
    }

    private void fillNormalizedNumber(ContentValues values) {
        // No NUMBER? Also ignore NORMALIZED_NUMBER
        if (!values.containsKey(Phone.NUMBER)) {
            values.remove(Phone.NORMALIZED_NUMBER);
            return;
        }

        // NUMBER is given. Try to extract NORMALIZED_NUMBER from it, unless it is also given
        final String number = values.getAsString(Phone.NUMBER);
        final String numberE164 = values.getAsString(Phone.NORMALIZED_NUMBER);
        if (number != null && numberE164 == null) {
            final String newNumberE164 = PhoneNumberUtils.formatNumberToE164(number,
                    mDbHelper.getCurrentCountryIso());
            values.put(Phone.NORMALIZED_NUMBER, newNumberE164);
        }
    }

    @Override
    public int delete(SQLiteDatabase db, TransactionContext txContext, Cursor c) {
        long dataId = c.getLong(DataDeleteQuery._ID);
        long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID);

        int count = super.delete(db, txContext, c);

        updatePhoneLookup(db, rawContactId, dataId, null, null);
        mContactAggregator.updateHasPhoneNumber(db, rawContactId);
        fixRawContactDisplayName(db, txContext, rawContactId);
        triggerAggregation(txContext, rawContactId);
        return count;
    }

    private void updatePhoneLookup(SQLiteDatabase db, long rawContactId, long dataId,
            String number, String numberE164) {
        mSelectionArgs1[0] = String.valueOf(dataId);
        db.delete(Tables.PHONE_LOOKUP, PhoneLookupColumns.DATA_ID + "=?", mSelectionArgs1);
        if (number != null) {
            String normalizedNumber = PhoneNumberUtils.normalizeNumber(number);
            if (!TextUtils.isEmpty(normalizedNumber)) {
                ContentValues phoneValues = new ContentValues();
                phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId);
                phoneValues.put(PhoneLookupColumns.DATA_ID, dataId);
                phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber);
                phoneValues.put(PhoneLookupColumns.MIN_MATCH,
                        PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber));
                db.insert(Tables.PHONE_LOOKUP, null, phoneValues);

                if (numberE164 != null && !numberE164.equals(normalizedNumber)) {
                    phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, numberE164);
                    phoneValues.put(PhoneLookupColumns.MIN_MATCH,
                            PhoneNumberUtils.toCallerIDMinMatch(numberE164));
                    db.insert(Tables.PHONE_LOOKUP, null, phoneValues);
                }
            }
        }
    }

    @Override
    protected int getTypeRank(int type) {
        switch (type) {
            case Phone.TYPE_MOBILE: return 0;
            case Phone.TYPE_WORK: return 1;
            case Phone.TYPE_HOME: return 2;
            case Phone.TYPE_PAGER: return 3;
            case Phone.TYPE_CUSTOM: return 4;
            case Phone.TYPE_OTHER: return 5;
            case Phone.TYPE_FAX_WORK: return 6;
            case Phone.TYPE_FAX_HOME: return 7;
            default: return 1000;
        }
    }

    @Override
    public boolean containsSearchableColumns(ContentValues values) {
        return values.containsKey(Phone.NUMBER);
    }

    @Override
    public void appendSearchableData(IndexBuilder builder) {
        String number = builder.getString(Phone.NUMBER);
        if (TextUtils.isEmpty(number)) {
            return;
        }

        String normalizedNumber = PhoneNumberUtils.normalizeNumber(number);
        if (TextUtils.isEmpty(normalizedNumber)) {
            return;
        }

        builder.appendToken(normalizedNumber);

        String numberE164 = PhoneNumberUtils.formatNumberToE164(
                number, mDbHelper.getCurrentCountryIso());
        if (numberE164 != null && !numberE164.equals(normalizedNumber)) {
            builder.appendToken(numberE164);
        }
    }
}
