/*
 * Copyright (C) 2009 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.vcard;

import android.content.ContentValues;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.CommonDataKinds.Nickname;
import android.provider.ContactsContract.CommonDataKinds.Note;
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.Relation;
import android.provider.ContactsContract.CommonDataKinds.SipAddress;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.CommonDataKinds.Website;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;

import com.android.vcard.VCardUtils.PhoneNumberUtilsPort;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * <p>
 * The class which lets users create their own vCard String. Typical usage is as follows:
 * </p>
 * <pre class="prettyprint">final VCardBuilder builder = new VCardBuilder(vcardType);
 * builder.appendNameProperties(contentValuesListMap.get(StructuredName.CONTENT_ITEM_TYPE))
 *     .appendNickNames(contentValuesListMap.get(Nickname.CONTENT_ITEM_TYPE))
 *     .appendPhones(contentValuesListMap.get(Phone.CONTENT_ITEM_TYPE))
 *     .appendEmails(contentValuesListMap.get(Email.CONTENT_ITEM_TYPE))
 *     .appendPostals(contentValuesListMap.get(StructuredPostal.CONTENT_ITEM_TYPE))
 *     .appendOrganizations(contentValuesListMap.get(Organization.CONTENT_ITEM_TYPE))
 *     .appendWebsites(contentValuesListMap.get(Website.CONTENT_ITEM_TYPE))
 *     .appendPhotos(contentValuesListMap.get(Photo.CONTENT_ITEM_TYPE))
 *     .appendNotes(contentValuesListMap.get(Note.CONTENT_ITEM_TYPE))
 *     .appendEvents(contentValuesListMap.get(Event.CONTENT_ITEM_TYPE))
 *     .appendIms(contentValuesListMap.get(Im.CONTENT_ITEM_TYPE))
 *     .appendRelation(contentValuesListMap.get(Relation.CONTENT_ITEM_TYPE));
 * return builder.toString();</pre>
 */
public class VCardBuilder {
    private static final String LOG_TAG = VCardConstants.LOG_TAG;

    // If you add the other element, please check all the columns are able to be
    // converted to String.
    //
    // e.g. BLOB is not what we can handle here now.
    private static final Set<String> sAllowedAndroidPropertySet =
            Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
                    Nickname.CONTENT_ITEM_TYPE, Event.CONTENT_ITEM_TYPE,
                    Relation.CONTENT_ITEM_TYPE)));

    public static final int DEFAULT_PHONE_TYPE = Phone.TYPE_HOME;
    public static final int DEFAULT_POSTAL_TYPE = StructuredPostal.TYPE_HOME;
    public static final int DEFAULT_EMAIL_TYPE = Email.TYPE_OTHER;

    private static final String VCARD_DATA_VCARD = "VCARD";
    private static final String VCARD_DATA_PUBLIC = "PUBLIC";

    private static final String VCARD_PARAM_SEPARATOR = ";";
    public static final String VCARD_END_OF_LINE = "\r\n";
    private static final String VCARD_DATA_SEPARATOR = ":";
    private static final String VCARD_ITEM_SEPARATOR = ";";
    private static final String VCARD_WS = " ";
    private static final String VCARD_PARAM_EQUAL = "=";

    private static final String VCARD_PARAM_ENCODING_QP =
            "ENCODING=" + VCardConstants.PARAM_ENCODING_QP;
    private static final String VCARD_PARAM_ENCODING_BASE64_V21 =
            "ENCODING=" + VCardConstants.PARAM_ENCODING_BASE64;
    private static final String VCARD_PARAM_ENCODING_BASE64_AS_B =
            "ENCODING=" + VCardConstants.PARAM_ENCODING_B;

    private static final String SHIFT_JIS = "SHIFT_JIS";

    private final int mVCardType;

    private final boolean mIsV30OrV40;
    private final boolean mIsJapaneseMobilePhone;
    private final boolean mOnlyOneNoteFieldIsAvailable;
    private final boolean mIsDoCoMo;
    private final boolean mShouldUseQuotedPrintable;
    private final boolean mUsesAndroidProperty;
    private final boolean mUsesDefactProperty;
    private final boolean mAppendTypeParamName;
    private final boolean mRefrainsQPToNameProperties;
    private final boolean mNeedsToConvertPhoneticString;

    private final boolean mShouldAppendCharsetParam;

    private final String mCharset;
    private final String mVCardCharsetParameter;

    private StringBuilder mBuilder;
    private boolean mEndAppended;

    public VCardBuilder(final int vcardType) {
        // Default charset should be used
        this(vcardType, null);
    }

    /**
     * @param vcardType
     * @param charset If null, we use default charset for export.
     * @hide
     */
    public VCardBuilder(final int vcardType, String charset) {
        mVCardType = vcardType;

        if (VCardConfig.isVersion40(vcardType)) {
            Log.w(LOG_TAG, "Should not use vCard 4.0 when building vCard. " +
                    "It is not officially published yet.");
        }

        mIsV30OrV40 = VCardConfig.isVersion30(vcardType) || VCardConfig.isVersion40(vcardType);
        mShouldUseQuotedPrintable = VCardConfig.shouldUseQuotedPrintable(vcardType);
        mIsDoCoMo = VCardConfig.isDoCoMo(vcardType);
        mIsJapaneseMobilePhone = VCardConfig.needsToConvertPhoneticString(vcardType);
        mOnlyOneNoteFieldIsAvailable = VCardConfig.onlyOneNoteFieldIsAvailable(vcardType);
        mUsesAndroidProperty = VCardConfig.usesAndroidSpecificProperty(vcardType);
        mUsesDefactProperty = VCardConfig.usesDefactProperty(vcardType);
        mRefrainsQPToNameProperties = VCardConfig.shouldRefrainQPToNameProperties(vcardType);
        mAppendTypeParamName = VCardConfig.appendTypeParamName(vcardType);
        mNeedsToConvertPhoneticString = VCardConfig.needsToConvertPhoneticString(vcardType);

        // vCard 2.1 requires charset.
        // vCard 3.0 does not allow it but we found some devices use it to determine
        // the exact charset.
        // We currently append it only when charset other than UTF_8 is used.
        mShouldAppendCharsetParam =
                !(VCardConfig.isVersion30(vcardType) && "UTF-8".equalsIgnoreCase(charset));

        if (VCardConfig.isDoCoMo(vcardType)) {
            if (!SHIFT_JIS.equalsIgnoreCase(charset)) {
                /* Log.w(LOG_TAG,
                        "The charset \"" + charset + "\" is used while "
                        + SHIFT_JIS + " is needed to be used."); */
                if (TextUtils.isEmpty(charset)) {
                    mCharset = SHIFT_JIS;
                } else {
                    mCharset = charset;
                }
            } else {
                mCharset = charset;
            }
            mVCardCharsetParameter = "CHARSET=" + SHIFT_JIS;
        } else {
            if (TextUtils.isEmpty(charset)) {
                Log.i(LOG_TAG,
                        "Use the charset \"" + VCardConfig.DEFAULT_EXPORT_CHARSET
                        + "\" for export.");
                mCharset = VCardConfig.DEFAULT_EXPORT_CHARSET;
                mVCardCharsetParameter = "CHARSET=" + VCardConfig.DEFAULT_EXPORT_CHARSET;
            } else {
                mCharset = charset;
                mVCardCharsetParameter = "CHARSET=" + charset;
            }
        }
        clear();
    }

    public void clear() {
        mBuilder = new StringBuilder();
        mEndAppended = false;
        appendLine(VCardConstants.PROPERTY_BEGIN, VCARD_DATA_VCARD);
        if (VCardConfig.isVersion40(mVCardType)) {
            appendLine(VCardConstants.PROPERTY_VERSION, VCardConstants.VERSION_V40);
        } else if (VCardConfig.isVersion30(mVCardType)) {
            appendLine(VCardConstants.PROPERTY_VERSION, VCardConstants.VERSION_V30);
        } else {
            if (!VCardConfig.isVersion21(mVCardType)) {
                Log.w(LOG_TAG, "Unknown vCard version detected.");
            }
            appendLine(VCardConstants.PROPERTY_VERSION, VCardConstants.VERSION_V21);
        }
    }

    private boolean containsNonEmptyName(final ContentValues contentValues) {
        final String familyName = contentValues.getAsString(StructuredName.FAMILY_NAME);
        final String middleName = contentValues.getAsString(StructuredName.MIDDLE_NAME);
        final String givenName = contentValues.getAsString(StructuredName.GIVEN_NAME);
        final String prefix = contentValues.getAsString(StructuredName.PREFIX);
        final String suffix = contentValues.getAsString(StructuredName.SUFFIX);
        final String phoneticFamilyName =
                contentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME);
        final String phoneticMiddleName =
                contentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
        final String phoneticGivenName =
                contentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME);
        final String displayName = contentValues.getAsString(StructuredName.DISPLAY_NAME);
        return !(TextUtils.isEmpty(familyName) && TextUtils.isEmpty(middleName) &&
                TextUtils.isEmpty(givenName) && TextUtils.isEmpty(prefix) &&
                TextUtils.isEmpty(suffix) && TextUtils.isEmpty(phoneticFamilyName) &&
                TextUtils.isEmpty(phoneticMiddleName) && TextUtils.isEmpty(phoneticGivenName) &&
                TextUtils.isEmpty(displayName));
    }

    private ContentValues getPrimaryContentValueWithStructuredName(
            final List<ContentValues> contentValuesList) {
        ContentValues primaryContentValues = null;
        ContentValues subprimaryContentValues = null;
        for (ContentValues contentValues : contentValuesList) {
            if (contentValues == null){
                continue;
            }
            Integer isSuperPrimary = contentValues.getAsInteger(StructuredName.IS_SUPER_PRIMARY);
            if (isSuperPrimary != null && isSuperPrimary > 0) {
                // We choose "super primary" ContentValues.
                primaryContentValues = contentValues;
                break;
            } else if (primaryContentValues == null) {
                // We choose the first "primary" ContentValues
                // if "super primary" ContentValues does not exist.
                final Integer isPrimary = contentValues.getAsInteger(StructuredName.IS_PRIMARY);
                if (isPrimary != null && isPrimary > 0 &&
                        containsNonEmptyName(contentValues)) {
                    primaryContentValues = contentValues;
                    // Do not break, since there may be ContentValues with "super primary"
                    // afterword.
                } else if (subprimaryContentValues == null &&
                        containsNonEmptyName(contentValues)) {
                    subprimaryContentValues = contentValues;
                }
            }
        }

        if (primaryContentValues == null) {
            if (subprimaryContentValues != null) {
                // We choose the first ContentValues if any "primary" ContentValues does not exist.
                primaryContentValues = subprimaryContentValues;
            } else {
                // There's no appropriate ContentValue with StructuredName.
                primaryContentValues = new ContentValues();
            }
        }

        return primaryContentValues;
    }

    /**
     * To avoid unnecessary complication in logic, we use this method to construct N, FN
     * properties for vCard 4.0.
     */
    private VCardBuilder appendNamePropertiesV40(final List<ContentValues> contentValuesList) {
        if (mIsDoCoMo || mNeedsToConvertPhoneticString) {
            // Ignore all flags that look stale from the view of vCard 4.0 to
            // simplify construction algorithm. Actually we don't have any vCard file
            // available from real world yet, so we may need to re-enable some of these
            // in the future.
            Log.w(LOG_TAG, "Invalid flag is used in vCard 4.0 construction. Ignored.");
        }

        if (contentValuesList == null || contentValuesList.isEmpty()) {
            appendLine(VCardConstants.PROPERTY_FN, "");
            return this;
        }

        // We have difficulty here. How can we appropriately handle StructuredName with
        // missing parts necessary for displaying while it has suppremental information.
        //
        // e.g. How to handle non-empty phonetic names with empty structured names?

        final ContentValues contentValues =
                getPrimaryContentValueWithStructuredName(contentValuesList);
        String familyName = contentValues.getAsString(StructuredName.FAMILY_NAME);
        final String middleName = contentValues.getAsString(StructuredName.MIDDLE_NAME);
        final String givenName = contentValues.getAsString(StructuredName.GIVEN_NAME);
        final String prefix = contentValues.getAsString(StructuredName.PREFIX);
        final String suffix = contentValues.getAsString(StructuredName.SUFFIX);
        final String formattedName = contentValues.getAsString(StructuredName.DISPLAY_NAME);
        if (TextUtils.isEmpty(familyName)
                && TextUtils.isEmpty(givenName)
                && TextUtils.isEmpty(middleName)
                && TextUtils.isEmpty(prefix)
                && TextUtils.isEmpty(suffix)) {
            if (TextUtils.isEmpty(formattedName)) {
                appendLine(VCardConstants.PROPERTY_FN, "");
                return this;
            }
            familyName = formattedName;
        }

        final String phoneticFamilyName =
                contentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME);
        final String phoneticMiddleName =
                contentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
        final String phoneticGivenName =
                contentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME);
        final String escapedFamily = escapeCharacters(familyName);
        final String escapedGiven = escapeCharacters(givenName);
        final String escapedMiddle = escapeCharacters(middleName);
        final String escapedPrefix = escapeCharacters(prefix);
        final String escapedSuffix = escapeCharacters(suffix);

        mBuilder.append(VCardConstants.PROPERTY_N);

        if (!(TextUtils.isEmpty(phoneticFamilyName) &&
                        TextUtils.isEmpty(phoneticMiddleName) &&
                        TextUtils.isEmpty(phoneticGivenName))) {
            mBuilder.append(VCARD_PARAM_SEPARATOR);
            final String sortAs = escapeCharacters(phoneticFamilyName)
                    + ';' + escapeCharacters(phoneticGivenName)
                    + ';' + escapeCharacters(phoneticMiddleName);
            mBuilder.append("SORT-AS=").append(
                    VCardUtils.toStringAsV40ParamValue(sortAs));
        }

        mBuilder.append(VCARD_DATA_SEPARATOR);
        mBuilder.append(escapedFamily);
        mBuilder.append(VCARD_ITEM_SEPARATOR);
        mBuilder.append(escapedGiven);
        mBuilder.append(VCARD_ITEM_SEPARATOR);
        mBuilder.append(escapedMiddle);
        mBuilder.append(VCARD_ITEM_SEPARATOR);
        mBuilder.append(escapedPrefix);
        mBuilder.append(VCARD_ITEM_SEPARATOR);
        mBuilder.append(escapedSuffix);
        mBuilder.append(VCARD_END_OF_LINE);

        if (TextUtils.isEmpty(formattedName)) {
            // Note:
            // DISPLAY_NAME doesn't exist while some other elements do, which is usually
            // weird in Android, as DISPLAY_NAME should (usually) be constructed
            // from the others using locale information and its code points.
            Log.w(LOG_TAG, "DISPLAY_NAME is empty.");

            final String escaped = escapeCharacters(VCardUtils.constructNameFromElements(
                    VCardConfig.getNameOrderType(mVCardType),
                    familyName, middleName, givenName, prefix, suffix));
            appendLine(VCardConstants.PROPERTY_FN, escaped);
        } else {
            final String escapedFormatted = escapeCharacters(formattedName);
            mBuilder.append(VCardConstants.PROPERTY_FN);
            mBuilder.append(VCARD_DATA_SEPARATOR);
            mBuilder.append(escapedFormatted);
            mBuilder.append(VCARD_END_OF_LINE);
        }

        // We may need X- properties for phonetic names.
        appendPhoneticNameFields(contentValues);
        return this;
    }

    /**
     * For safety, we'll emit just one value around StructuredName, as external importers
     * may get confused with multiple "N", "FN", etc. properties, though it is valid in
     * vCard spec.
     */
    public VCardBuilder appendNameProperties(final List<ContentValues> contentValuesList) {
        if (VCardConfig.isVersion40(mVCardType)) {
            return appendNamePropertiesV40(contentValuesList);
        }

        if (contentValuesList == null || contentValuesList.isEmpty()) {
            if (VCardConfig.isVersion30(mVCardType)) {
                // vCard 3.0 requires "N" and "FN" properties.
                // vCard 4.0 does NOT require N, but we take care of possible backward
                // compatibility issues.
                appendLine(VCardConstants.PROPERTY_N, "");
                appendLine(VCardConstants.PROPERTY_FN, "");
            } else if (mIsDoCoMo) {
                appendLine(VCardConstants.PROPERTY_N, "");
            }
            return this;
        }

        final ContentValues contentValues =
                getPrimaryContentValueWithStructuredName(contentValuesList);
        final String familyName = contentValues.getAsString(StructuredName.FAMILY_NAME);
        final String middleName = contentValues.getAsString(StructuredName.MIDDLE_NAME);
        final String givenName = contentValues.getAsString(StructuredName.GIVEN_NAME);
        final String prefix = contentValues.getAsString(StructuredName.PREFIX);
        final String suffix = contentValues.getAsString(StructuredName.SUFFIX);
        final String displayName = contentValues.getAsString(StructuredName.DISPLAY_NAME);

        if (!TextUtils.isEmpty(familyName) || !TextUtils.isEmpty(givenName)) {
            final boolean reallyAppendCharsetParameterToName =
                    shouldAppendCharsetParam(familyName, givenName, middleName, prefix, suffix);
            final boolean reallyUseQuotedPrintableToName =
                    (!mRefrainsQPToNameProperties &&
                            !(VCardUtils.containsOnlyNonCrLfPrintableAscii(familyName) &&
                                    VCardUtils.containsOnlyNonCrLfPrintableAscii(givenName) &&
                                    VCardUtils.containsOnlyNonCrLfPrintableAscii(middleName) &&
                                    VCardUtils.containsOnlyNonCrLfPrintableAscii(prefix) &&
                                    VCardUtils.containsOnlyNonCrLfPrintableAscii(suffix)));

            final String formattedName;
            if (!TextUtils.isEmpty(displayName)) {
                formattedName = displayName;
            } else {
                formattedName = VCardUtils.constructNameFromElements(
                        VCardConfig.getNameOrderType(mVCardType),
                        familyName, middleName, givenName, prefix, suffix);
            }
            final boolean reallyAppendCharsetParameterToFN =
                    shouldAppendCharsetParam(formattedName);
            final boolean reallyUseQuotedPrintableToFN =
                    !mRefrainsQPToNameProperties &&
                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(formattedName);

            final String encodedFamily;
            final String encodedGiven;
            final String encodedMiddle;
            final String encodedPrefix;
            final String encodedSuffix;
            if (reallyUseQuotedPrintableToName) {
                encodedFamily = encodeQuotedPrintable(familyName);
                encodedGiven = encodeQuotedPrintable(givenName);
                encodedMiddle = encodeQuotedPrintable(middleName);
                encodedPrefix = encodeQuotedPrintable(prefix);
                encodedSuffix = encodeQuotedPrintable(suffix);
            } else {
                encodedFamily = escapeCharacters(familyName);
                encodedGiven = escapeCharacters(givenName);
                encodedMiddle = escapeCharacters(middleName);
                encodedPrefix = escapeCharacters(prefix);
                encodedSuffix = escapeCharacters(suffix);
            }

            final String encodedFormattedname =
                    (reallyUseQuotedPrintableToFN ?
                            encodeQuotedPrintable(formattedName) : escapeCharacters(formattedName));

            mBuilder.append(VCardConstants.PROPERTY_N);
            if (mIsDoCoMo) {
                if (reallyAppendCharsetParameterToName) {
                    mBuilder.append(VCARD_PARAM_SEPARATOR);
                    mBuilder.append(mVCardCharsetParameter);
                }
                if (reallyUseQuotedPrintableToName) {
                    mBuilder.append(VCARD_PARAM_SEPARATOR);
                    mBuilder.append(VCARD_PARAM_ENCODING_QP);
                }
                mBuilder.append(VCARD_DATA_SEPARATOR);
                // DoCoMo phones require that all the elements in the "family name" field.
                mBuilder.append(formattedName);
                mBuilder.append(VCARD_ITEM_SEPARATOR);
                mBuilder.append(VCARD_ITEM_SEPARATOR);
                mBuilder.append(VCARD_ITEM_SEPARATOR);
                mBuilder.append(VCARD_ITEM_SEPARATOR);
            } else {
                if (reallyAppendCharsetParameterToName) {
                    mBuilder.append(VCARD_PARAM_SEPARATOR);
                    mBuilder.append(mVCardCharsetParameter);
                }
                if (reallyUseQuotedPrintableToName) {
                    mBuilder.append(VCARD_PARAM_SEPARATOR);
                    mBuilder.append(VCARD_PARAM_ENCODING_QP);
                }
                mBuilder.append(VCARD_DATA_SEPARATOR);
                mBuilder.append(encodedFamily);
                mBuilder.append(VCARD_ITEM_SEPARATOR);
                mBuilder.append(encodedGiven);
                mBuilder.append(VCARD_ITEM_SEPARATOR);
                mBuilder.append(encodedMiddle);
                mBuilder.append(VCARD_ITEM_SEPARATOR);
                mBuilder.append(encodedPrefix);
                mBuilder.append(VCARD_ITEM_SEPARATOR);
                mBuilder.append(encodedSuffix);
            }
            mBuilder.append(VCARD_END_OF_LINE);

            // FN property
            mBuilder.append(VCardConstants.PROPERTY_FN);
            if (reallyAppendCharsetParameterToFN) {
                mBuilder.append(VCARD_PARAM_SEPARATOR);
                mBuilder.append(mVCardCharsetParameter);
            }
            if (reallyUseQuotedPrintableToFN) {
                mBuilder.append(VCARD_PARAM_SEPARATOR);
                mBuilder.append(VCARD_PARAM_ENCODING_QP);
            }
            mBuilder.append(VCARD_DATA_SEPARATOR);
            mBuilder.append(encodedFormattedname);
            mBuilder.append(VCARD_END_OF_LINE);
        } else if (!TextUtils.isEmpty(displayName)) {

            // N
            buildSinglePartNameField(VCardConstants.PROPERTY_N, displayName);
            mBuilder.append(VCARD_ITEM_SEPARATOR);
            mBuilder.append(VCARD_ITEM_SEPARATOR);
            mBuilder.append(VCARD_ITEM_SEPARATOR);
            mBuilder.append(VCARD_ITEM_SEPARATOR);
            mBuilder.append(VCARD_END_OF_LINE);

            // FN
            buildSinglePartNameField(VCardConstants.PROPERTY_FN, displayName);
            mBuilder.append(VCARD_END_OF_LINE);

        } else if (VCardConfig.isVersion30(mVCardType)) {
            appendLine(VCardConstants.PROPERTY_N, "");
            appendLine(VCardConstants.PROPERTY_FN, "");
        } else if (mIsDoCoMo) {
            appendLine(VCardConstants.PROPERTY_N, "");
        }

        appendPhoneticNameFields(contentValues);
        return this;
    }

    private void buildSinglePartNameField(String property, String part) {
        final boolean reallyUseQuotedPrintable =
                (!mRefrainsQPToNameProperties &&
                        !VCardUtils.containsOnlyNonCrLfPrintableAscii(part));
        final String encodedPart = reallyUseQuotedPrintable ?
                encodeQuotedPrintable(part) :
                escapeCharacters(part);

        mBuilder.append(property);

        // Note: "CHARSET" param is not allowed in vCard 3.0, but we may add it
        //       when it would be useful or necessary for external importers,
        //       assuming the external importer allows this vioration of the spec.
        if (shouldAppendCharsetParam(part)) {
            mBuilder.append(VCARD_PARAM_SEPARATOR);
            mBuilder.append(mVCardCharsetParameter);
        }
        if (reallyUseQuotedPrintable) {
            mBuilder.append(VCARD_PARAM_SEPARATOR);
            mBuilder.append(VCARD_PARAM_ENCODING_QP);
        }
        mBuilder.append(VCARD_DATA_SEPARATOR);
        mBuilder.append(encodedPart);
    }

    /**
     * Emits SOUND;IRMC, SORT-STRING, and de-fact values for phonetic names like X-PHONETIC-FAMILY.
     */
    private void appendPhoneticNameFields(final ContentValues contentValues) {
        final String phoneticFamilyName;
        final String phoneticMiddleName;
        final String phoneticGivenName;
        {
            final String tmpPhoneticFamilyName =
                contentValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME);
            final String tmpPhoneticMiddleName =
                contentValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
            final String tmpPhoneticGivenName =
                contentValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME);
            if (mNeedsToConvertPhoneticString) {
                phoneticFamilyName = VCardUtils.toHalfWidthString(tmpPhoneticFamilyName);
                phoneticMiddleName = VCardUtils.toHalfWidthString(tmpPhoneticMiddleName);
                phoneticGivenName = VCardUtils.toHalfWidthString(tmpPhoneticGivenName);
            } else {
                phoneticFamilyName = tmpPhoneticFamilyName;
                phoneticMiddleName = tmpPhoneticMiddleName;
                phoneticGivenName = tmpPhoneticGivenName;
            }
        }

        if (TextUtils.isEmpty(phoneticFamilyName)
                && TextUtils.isEmpty(phoneticMiddleName)
                && TextUtils.isEmpty(phoneticGivenName)) {
            if (mIsDoCoMo) {
                mBuilder.append(VCardConstants.PROPERTY_SOUND);
                mBuilder.append(VCARD_PARAM_SEPARATOR);
                mBuilder.append(VCardConstants.PARAM_TYPE_X_IRMC_N);
                mBuilder.append(VCARD_DATA_SEPARATOR);
                mBuilder.append(VCARD_ITEM_SEPARATOR);
                mBuilder.append(VCARD_ITEM_SEPARATOR);
                mBuilder.append(VCARD_ITEM_SEPARATOR);
                mBuilder.append(VCARD_ITEM_SEPARATOR);
                mBuilder.append(VCARD_END_OF_LINE);
            }
            return;
        }

        if (VCardConfig.isVersion40(mVCardType)) {
            // We don't want SORT-STRING anyway.
        } else if (VCardConfig.isVersion30(mVCardType)) {
            final String sortString =
                    VCardUtils.constructNameFromElements(mVCardType,
                            phoneticFamilyName, phoneticMiddleName, phoneticGivenName);
            mBuilder.append(VCardConstants.PROPERTY_SORT_STRING);
            if (VCardConfig.isVersion30(mVCardType) && shouldAppendCharsetParam(sortString)) {
                // vCard 3.0 does not force us to use UTF-8 and actually we see some
                // programs which emit this value. It is incorrect from the view of
                // specification, but actually necessary for parsing vCard with non-UTF-8
                // charsets, expecting other parsers not get confused with this value.
                mBuilder.append(VCARD_PARAM_SEPARATOR);
                mBuilder.append(mVCardCharsetParameter);
            }
            mBuilder.append(VCARD_DATA_SEPARATOR);
            mBuilder.append(escapeCharacters(sortString));
            mBuilder.append(VCARD_END_OF_LINE);
        } else if (mIsJapaneseMobilePhone) {
            // Note: There is no appropriate property for expressing
            //       phonetic name (Yomigana in Japanese) in vCard 2.1, while there is in
            //       vCard 3.0 (SORT-STRING).
            //       We use DoCoMo's way when the device is Japanese one since it is already
            //       supported by a lot of Japanese mobile phones.
            //       This is "X-" property, so any parser hopefully would not get
            //       confused with this.
            //
            //       Also, DoCoMo's specification requires vCard composer to use just the first
            //       column.
            //       i.e.
            //       good:  SOUND;X-IRMC-N:Miyakawa Daisuke;;;;
            //       bad :  SOUND;X-IRMC-N:Miyakawa;Daisuke;;;
            mBuilder.append(VCardConstants.PROPERTY_SOUND);
            mBuilder.append(VCARD_PARAM_SEPARATOR);
            mBuilder.append(VCardConstants.PARAM_TYPE_X_IRMC_N);

            boolean reallyUseQuotedPrintable =
                (!mRefrainsQPToNameProperties
                        && !(VCardUtils.containsOnlyNonCrLfPrintableAscii(
                                phoneticFamilyName)
                                && VCardUtils.containsOnlyNonCrLfPrintableAscii(
                                        phoneticMiddleName)
                                && VCardUtils.containsOnlyNonCrLfPrintableAscii(
                                        phoneticGivenName)));

            final String encodedPhoneticFamilyName;
            final String encodedPhoneticMiddleName;
            final String encodedPhoneticGivenName;
            if (reallyUseQuotedPrintable) {
                encodedPhoneticFamilyName = encodeQuotedPrintable(phoneticFamilyName);
                encodedPhoneticMiddleName = encodeQuotedPrintable(phoneticMiddleName);
                encodedPhoneticGivenName = encodeQuotedPrintable(phoneticGivenName);
            } else {
                encodedPhoneticFamilyName = escapeCharacters(phoneticFamilyName);
                encodedPhoneticMiddleName = escapeCharacters(phoneticMiddleName);
                encodedPhoneticGivenName = escapeCharacters(phoneticGivenName);
            }

            if (shouldAppendCharsetParam(encodedPhoneticFamilyName,
                    encodedPhoneticMiddleName, encodedPhoneticGivenName)) {
                mBuilder.append(VCARD_PARAM_SEPARATOR);
                mBuilder.append(mVCardCharsetParameter);
            }
            mBuilder.append(VCARD_DATA_SEPARATOR);
            {
                boolean first = true;
                if (!TextUtils.isEmpty(encodedPhoneticFamilyName)) {
                    mBuilder.append(encodedPhoneticFamilyName);
                    first = false;
                }
                if (!TextUtils.isEmpty(encodedPhoneticMiddleName)) {
                    if (first) {
                        first = false;
                    } else {
                        mBuilder.append(' ');
                    }
                    mBuilder.append(encodedPhoneticMiddleName);
                }
                if (!TextUtils.isEmpty(encodedPhoneticGivenName)) {
                    if (!first) {
                        mBuilder.append(' ');
                    }
                    mBuilder.append(encodedPhoneticGivenName);
                }
            }
            mBuilder.append(VCARD_ITEM_SEPARATOR);  // family;given
            mBuilder.append(VCARD_ITEM_SEPARATOR);  // given;middle
            mBuilder.append(VCARD_ITEM_SEPARATOR);  // middle;prefix
            mBuilder.append(VCARD_ITEM_SEPARATOR);  // prefix;suffix
            mBuilder.append(VCARD_END_OF_LINE);
        }

        if (mUsesDefactProperty) {
            if (!TextUtils.isEmpty(phoneticGivenName)) {
                final boolean reallyUseQuotedPrintable =
                    (mShouldUseQuotedPrintable &&
                            !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticGivenName));
                final String encodedPhoneticGivenName;
                if (reallyUseQuotedPrintable) {
                    encodedPhoneticGivenName = encodeQuotedPrintable(phoneticGivenName);
                } else {
                    encodedPhoneticGivenName = escapeCharacters(phoneticGivenName);
                }
                mBuilder.append(VCardConstants.PROPERTY_X_PHONETIC_FIRST_NAME);
                if (shouldAppendCharsetParam(phoneticGivenName)) {
                    mBuilder.append(VCARD_PARAM_SEPARATOR);
                    mBuilder.append(mVCardCharsetParameter);
                }
                if (reallyUseQuotedPrintable) {
                    mBuilder.append(VCARD_PARAM_SEPARATOR);
                    mBuilder.append(VCARD_PARAM_ENCODING_QP);
                }
                mBuilder.append(VCARD_DATA_SEPARATOR);
                mBuilder.append(encodedPhoneticGivenName);
                mBuilder.append(VCARD_END_OF_LINE);
            }  // if (!TextUtils.isEmpty(phoneticGivenName))
            if (!TextUtils.isEmpty(phoneticMiddleName)) {
                final boolean reallyUseQuotedPrintable =
                    (mShouldUseQuotedPrintable &&
                            !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticMiddleName));
                final String encodedPhoneticMiddleName;
                if (reallyUseQuotedPrintable) {
                    encodedPhoneticMiddleName = encodeQuotedPrintable(phoneticMiddleName);
                } else {
                    encodedPhoneticMiddleName = escapeCharacters(phoneticMiddleName);
                }
                mBuilder.append(VCardConstants.PROPERTY_X_PHONETIC_MIDDLE_NAME);
                if (shouldAppendCharsetParam(phoneticMiddleName)) {
                    mBuilder.append(VCARD_PARAM_SEPARATOR);
                    mBuilder.append(mVCardCharsetParameter);
                }
                if (reallyUseQuotedPrintable) {
                    mBuilder.append(VCARD_PARAM_SEPARATOR);
                    mBuilder.append(VCARD_PARAM_ENCODING_QP);
                }
                mBuilder.append(VCARD_DATA_SEPARATOR);
                mBuilder.append(encodedPhoneticMiddleName);
                mBuilder.append(VCARD_END_OF_LINE);
            }  // if (!TextUtils.isEmpty(phoneticGivenName))
            if (!TextUtils.isEmpty(phoneticFamilyName)) {
                final boolean reallyUseQuotedPrintable =
                    (mShouldUseQuotedPrintable &&
                            !VCardUtils.containsOnlyNonCrLfPrintableAscii(phoneticFamilyName));
                final String encodedPhoneticFamilyName;
                if (reallyUseQuotedPrintable) {
                    encodedPhoneticFamilyName = encodeQuotedPrintable(phoneticFamilyName);
                } else {
                    encodedPhoneticFamilyName = escapeCharacters(phoneticFamilyName);
                }
                mBuilder.append(VCardConstants.PROPERTY_X_PHONETIC_LAST_NAME);
                if (shouldAppendCharsetParam(phoneticFamilyName)) {
                    mBuilder.append(VCARD_PARAM_SEPARATOR);
                    mBuilder.append(mVCardCharsetParameter);
                }
                if (reallyUseQuotedPrintable) {
                    mBuilder.append(VCARD_PARAM_SEPARATOR);
                    mBuilder.append(VCARD_PARAM_ENCODING_QP);
                }
                mBuilder.append(VCARD_DATA_SEPARATOR);
                mBuilder.append(encodedPhoneticFamilyName);
                mBuilder.append(VCARD_END_OF_LINE);
            }  // if (!TextUtils.isEmpty(phoneticFamilyName))
        }
    }

    public VCardBuilder appendNickNames(final List<ContentValues> contentValuesList) {
        final boolean useAndroidProperty;
        if (mIsV30OrV40) {   // These specifications have NICKNAME property.
            useAndroidProperty = false;
        } else if (mUsesAndroidProperty) {
            useAndroidProperty = true;
        } else {
            // There's no way to add this field.
            return this;
        }
        if (contentValuesList != null) {
            for (ContentValues contentValues : contentValuesList) {
                final String nickname = contentValues.getAsString(Nickname.NAME);
                if (TextUtils.isEmpty(nickname)) {
                    continue;
                }
                if (useAndroidProperty) {
                    appendAndroidSpecificProperty(Nickname.CONTENT_ITEM_TYPE, contentValues);
                } else {
                    appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_NICKNAME, nickname);
                }
            }
        }
        return this;
    }

    public VCardBuilder appendPhones(final List<ContentValues> contentValuesList,
            VCardPhoneNumberTranslationCallback translationCallback) {
        boolean phoneLineExists = false;
        if (contentValuesList != null) {
            Set<String> phoneSet = new HashSet<String>();
            for (ContentValues contentValues : contentValuesList) {
                final Integer typeAsObject = contentValues.getAsInteger(Phone.TYPE);
                final String label = contentValues.getAsString(Phone.LABEL);
                final Integer isPrimaryAsInteger = contentValues.getAsInteger(Phone.IS_PRIMARY);
                final boolean isPrimary = (isPrimaryAsInteger != null ?
                        (isPrimaryAsInteger > 0) : false);
                String phoneNumber = contentValues.getAsString(Phone.NUMBER);
                if (phoneNumber != null) {
                    phoneNumber = phoneNumber.trim();
                }
                if (TextUtils.isEmpty(phoneNumber)) {
                    continue;
                }

                final int type = (typeAsObject != null ? typeAsObject : DEFAULT_PHONE_TYPE);
                // Note: We prioritize this callback over FLAG_REFRAIN_PHONE_NUMBER_FORMATTING
                // intentionally. In the future the flag will be replaced by callback
                // mechanism entirely.
                if (translationCallback != null) {
                    phoneNumber = translationCallback.onValueReceived(
                            phoneNumber, type, label, isPrimary);
                    if (!phoneSet.contains(phoneNumber)) {
                        phoneSet.add(phoneNumber);
                        appendTelLine(type, label, phoneNumber, isPrimary);
                    }
                } else if (type == Phone.TYPE_PAGER ||
                        VCardConfig.refrainPhoneNumberFormatting(mVCardType)) {
                    // Note: PAGER number needs unformatted "phone number".
                    phoneLineExists = true;
                    if (!phoneSet.contains(phoneNumber)) {
                        phoneSet.add(phoneNumber);
                        appendTelLine(type, label, phoneNumber, isPrimary);
                    }
                } else {
                    final List<String> phoneNumberList = splitPhoneNumbers(phoneNumber);
                    if (phoneNumberList.isEmpty()) {
                        continue;
                    }
                    phoneLineExists = true;
                    for (String actualPhoneNumber : phoneNumberList) {
                        if (!phoneSet.contains(actualPhoneNumber)) {
                            // 'p' and 'w' are the standard characters for pause and wait
                            // (see RFC 3601)
                            // so use those when exporting phone numbers via vCard.
                            String numberWithControlSequence = actualPhoneNumber
                                    .replace(PhoneNumberUtils.PAUSE, 'p')
                                    .replace(PhoneNumberUtils.WAIT, 'w');
                            String formatted;
                            // TODO: remove this code and relevant test cases. vCard and any other
                            // codes using it shouldn't rely on the formatter here.
                            if (TextUtils.equals(numberWithControlSequence, actualPhoneNumber)) {
                                StringBuilder digitsOnlyBuilder = new StringBuilder();
                                final int length = actualPhoneNumber.length();
                                for (int i = 0; i < length; i++) {
                                    final char ch = actualPhoneNumber.charAt(i);
                                    if (Character.isDigit(ch) || ch == '+') {
                                        digitsOnlyBuilder.append(ch);
                                    }
                                }
                                final int phoneFormat =
                                        VCardUtils.getPhoneNumberFormat(mVCardType);
                                formatted = PhoneNumberUtilsPort.formatNumber(
                                        digitsOnlyBuilder.toString(), phoneFormat);
                            } else {
                                // Be conservative.
                                formatted = numberWithControlSequence;
                            }

                            // In vCard 4.0, value type must be "a single URI value",
                            // not just a phone number. (Based on vCard 4.0 rev.13)
                            if (VCardConfig.isVersion40(mVCardType)
                                    && !TextUtils.isEmpty(formatted)
                                    && !formatted.startsWith("tel:")) {
                                formatted = "tel:" + formatted;
                            }

                            // Pre-formatted string should be stored.
                            phoneSet.add(actualPhoneNumber);
                            appendTelLine(type, label, formatted, isPrimary);
                        }
                    }  // for (String actualPhoneNumber : phoneNumberList) {

                    // TODO: TEL with SIP URI?
                }
            }
        }

        if (!phoneLineExists && mIsDoCoMo) {
            appendTelLine(Phone.TYPE_HOME, "", "", false);
        }

        return this;
    }

    /**
     * <p>
     * Splits a given string expressing phone numbers into several strings, and remove
     * unnecessary characters inside them. The size of a returned list becomes 1 when
     * no split is needed.
     * </p>
     * <p>
     * The given number "may" have several phone numbers when the contact entry is corrupted
     * because of its original source.
     * e.g. "111-222-3333 (Miami)\n444-555-6666 (Broward; 305-653-6796 (Miami)"
     * </p>
     * <p>
     * This kind of "phone numbers" will not be created with Android vCard implementation,
     * but we may encounter them if the source of the input data has already corrupted
     * implementation.
     * </p>
     * <p>
     * To handle this case, this method first splits its input into multiple parts
     * (e.g. "111-222-3333 (Miami)", "444-555-6666 (Broward", and 305653-6796 (Miami)") and
     * removes unnecessary strings like "(Miami)".
     * </p>
     * <p>
     * Do not call this method when trimming is inappropriate for its receivers.
     * </p>
     */
    private List<String> splitPhoneNumbers(final String phoneNumber) {
        final List<String> phoneList = new ArrayList<String>();

        StringBuilder builder = new StringBuilder();
        final int length = phoneNumber.length();
        for (int i = 0; i < length; i++) {
            final char ch = phoneNumber.charAt(i);
            if (ch == '\n' && builder.length() > 0) {
                phoneList.add(builder.toString());
                builder = new StringBuilder();
            } else {
                builder.append(ch);
            }
        }
        if (builder.length() > 0) {
            phoneList.add(builder.toString());
        }
        return phoneList;
    }

    public VCardBuilder appendEmails(final List<ContentValues> contentValuesList) {
        boolean emailAddressExists = false;
        if (contentValuesList != null) {
            final Set<String> addressSet = new HashSet<String>();
            for (ContentValues contentValues : contentValuesList) {
                String emailAddress = contentValues.getAsString(Email.DATA);
                if (emailAddress != null) {
                    emailAddress = emailAddress.trim();
                }
                if (TextUtils.isEmpty(emailAddress)) {
                    continue;
                }
                Integer typeAsObject = contentValues.getAsInteger(Email.TYPE);
                final int type = (typeAsObject != null ?
                        typeAsObject : DEFAULT_EMAIL_TYPE);
                final String label = contentValues.getAsString(Email.LABEL);
                Integer isPrimaryAsInteger = contentValues.getAsInteger(Email.IS_PRIMARY);
                final boolean isPrimary = (isPrimaryAsInteger != null ?
                        (isPrimaryAsInteger > 0) : false);
                emailAddressExists = true;
                if (!addressSet.contains(emailAddress)) {
                    addressSet.add(emailAddress);
                    appendEmailLine(type, label, emailAddress, isPrimary);
                }
            }
        }

        if (!emailAddressExists && mIsDoCoMo) {
            appendEmailLine(Email.TYPE_HOME, "", "", false);
        }

        return this;
    }

    public VCardBuilder appendPostals(final List<ContentValues> contentValuesList) {
        if (contentValuesList == null || contentValuesList.isEmpty()) {
            if (mIsDoCoMo) {
                mBuilder.append(VCardConstants.PROPERTY_ADR);
                mBuilder.append(VCARD_PARAM_SEPARATOR);
                mBuilder.append(VCardConstants.PARAM_TYPE_HOME);
                mBuilder.append(VCARD_DATA_SEPARATOR);
                mBuilder.append(VCARD_END_OF_LINE);
            }
        } else {
            if (mIsDoCoMo) {
                appendPostalsForDoCoMo(contentValuesList);
            } else {
                appendPostalsForGeneric(contentValuesList);
            }
        }

        return this;
    }

    private static final Map<Integer, Integer> sPostalTypePriorityMap;

    static {
        sPostalTypePriorityMap = new HashMap<Integer, Integer>();
        sPostalTypePriorityMap.put(StructuredPostal.TYPE_HOME, 0);
        sPostalTypePriorityMap.put(StructuredPostal.TYPE_WORK, 1);
        sPostalTypePriorityMap.put(StructuredPostal.TYPE_OTHER, 2);
        sPostalTypePriorityMap.put(StructuredPostal.TYPE_CUSTOM, 3);
    }

    /**
     * Tries to append just one line. If there's no appropriate address
     * information, append an empty line.
     */
    private void appendPostalsForDoCoMo(final List<ContentValues> contentValuesList) {
        int currentPriority = Integer.MAX_VALUE;
        int currentType = Integer.MAX_VALUE;
        ContentValues currentContentValues = null;
        for (final ContentValues contentValues : contentValuesList) {
            if (contentValues == null) {
                continue;
            }
            final Integer typeAsInteger = contentValues.getAsInteger(StructuredPostal.TYPE);
            final Integer priorityAsInteger = sPostalTypePriorityMap.get(typeAsInteger);
            final int priority =
                    (priorityAsInteger != null ? priorityAsInteger : Integer.MAX_VALUE);
            if (priority < currentPriority) {
                currentPriority = priority;
                currentType = typeAsInteger;
                currentContentValues = contentValues;
                if (priority == 0) {
                    break;
                }
            }
        }

        if (currentContentValues == null) {
            Log.w(LOG_TAG, "Should not come here. Must have at least one postal data.");
            return;
        }

        final String label = currentContentValues.getAsString(StructuredPostal.LABEL);
        appendPostalLine(currentType, label, currentContentValues, false, true);
    }

    private void appendPostalsForGeneric(final List<ContentValues> contentValuesList) {
        for (final ContentValues contentValues : contentValuesList) {
            if (contentValues == null) {
                continue;
            }
            final Integer typeAsInteger = contentValues.getAsInteger(StructuredPostal.TYPE);
            final int type = (typeAsInteger != null ?
                    typeAsInteger : DEFAULT_POSTAL_TYPE);
            final String label = contentValues.getAsString(StructuredPostal.LABEL);
            final Integer isPrimaryAsInteger =
                contentValues.getAsInteger(StructuredPostal.IS_PRIMARY);
            final boolean isPrimary = (isPrimaryAsInteger != null ?
                    (isPrimaryAsInteger > 0) : false);
            appendPostalLine(type, label, contentValues, isPrimary, false);
        }
    }

    private static class PostalStruct {
        final boolean reallyUseQuotedPrintable;
        final boolean appendCharset;
        final String addressData;
        public PostalStruct(final boolean reallyUseQuotedPrintable,
                final boolean appendCharset, final String addressData) {
            this.reallyUseQuotedPrintable = reallyUseQuotedPrintable;
            this.appendCharset = appendCharset;
            this.addressData = addressData;
        }
    }

    /**
     * @return null when there's no information available to construct the data.
     */
    private PostalStruct tryConstructPostalStruct(ContentValues contentValues) {
        // adr-value    = 0*6(text-value ";") text-value
        //              ; PO Box, Extended Address, Street, Locality, Region, Postal
        //              ; Code, Country Name
        final String rawPoBox = contentValues.getAsString(StructuredPostal.POBOX);
        final String rawNeighborhood = contentValues.getAsString(StructuredPostal.NEIGHBORHOOD);
        final String rawStreet = contentValues.getAsString(StructuredPostal.STREET);
        final String rawLocality = contentValues.getAsString(StructuredPostal.CITY);
        final String rawRegion = contentValues.getAsString(StructuredPostal.REGION);
        final String rawPostalCode = contentValues.getAsString(StructuredPostal.POSTCODE);
        final String rawCountry = contentValues.getAsString(StructuredPostal.COUNTRY);
        final String[] rawAddressArray = new String[]{
                rawPoBox, rawNeighborhood, rawStreet, rawLocality,
                rawRegion, rawPostalCode, rawCountry};
        if (!VCardUtils.areAllEmpty(rawAddressArray)) {
            final boolean reallyUseQuotedPrintable =
                (mShouldUseQuotedPrintable &&
                        !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawAddressArray));
            final boolean appendCharset =
                !VCardUtils.containsOnlyPrintableAscii(rawAddressArray);
            final String encodedPoBox;
            final String encodedStreet;
            final String encodedLocality;
            final String encodedRegion;
            final String encodedPostalCode;
            final String encodedCountry;
            final String encodedNeighborhood;

            final String rawLocality2;
            // This looks inefficient since we encode rawLocality and rawNeighborhood twice,
            // but this is intentional.
            //
            // QP encoding may add line feeds when needed and the result of
            // - encodeQuotedPrintable(rawLocality + " " + rawNeighborhood)
            // may be different from
            // - encodedLocality + " " + encodedNeighborhood.
            //
            // We use safer way.
            if (TextUtils.isEmpty(rawLocality)) {
                if (TextUtils.isEmpty(rawNeighborhood)) {
                    rawLocality2 = "";
                } else {
                    rawLocality2 = rawNeighborhood;
                }
            } else {
                if (TextUtils.isEmpty(rawNeighborhood)) {
                    rawLocality2 = rawLocality;
                } else {
                    rawLocality2 = rawLocality + " " + rawNeighborhood;
                }
            }
            if (reallyUseQuotedPrintable) {
                encodedPoBox = encodeQuotedPrintable(rawPoBox);
                encodedStreet = encodeQuotedPrintable(rawStreet);
                encodedLocality = encodeQuotedPrintable(rawLocality2);
                encodedRegion = encodeQuotedPrintable(rawRegion);
                encodedPostalCode = encodeQuotedPrintable(rawPostalCode);
                encodedCountry = encodeQuotedPrintable(rawCountry);
            } else {
                encodedPoBox = escapeCharacters(rawPoBox);
                encodedStreet = escapeCharacters(rawStreet);
                encodedLocality = escapeCharacters(rawLocality2);
                encodedRegion = escapeCharacters(rawRegion);
                encodedPostalCode = escapeCharacters(rawPostalCode);
                encodedCountry = escapeCharacters(rawCountry);
                encodedNeighborhood = escapeCharacters(rawNeighborhood);
            }
            final StringBuilder addressBuilder = new StringBuilder();
            addressBuilder.append(encodedPoBox);
            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // PO BOX ; Extended Address
            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Extended Address : Street
            addressBuilder.append(encodedStreet);
            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Street : Locality
            addressBuilder.append(encodedLocality);
            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Locality : Region
            addressBuilder.append(encodedRegion);
            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Region : Postal Code
            addressBuilder.append(encodedPostalCode);
            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Postal Code : Country
            addressBuilder.append(encodedCountry);
            return new PostalStruct(
                    reallyUseQuotedPrintable, appendCharset, addressBuilder.toString());
        } else {  // VCardUtils.areAllEmpty(rawAddressArray) == true
            // Try to use FORMATTED_ADDRESS instead.
            final String rawFormattedAddress =
                contentValues.getAsString(StructuredPostal.FORMATTED_ADDRESS);
            if (TextUtils.isEmpty(rawFormattedAddress)) {
                return null;
            }
            final boolean reallyUseQuotedPrintable =
                (mShouldUseQuotedPrintable &&
                        !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawFormattedAddress));
            final boolean appendCharset =
                !VCardUtils.containsOnlyPrintableAscii(rawFormattedAddress);
            final String encodedFormattedAddress;
            if (reallyUseQuotedPrintable) {
                encodedFormattedAddress = encodeQuotedPrintable(rawFormattedAddress);
            } else {
                encodedFormattedAddress = escapeCharacters(rawFormattedAddress);
            }

            // We use the second value ("Extended Address") just because Japanese mobile phones
            // do so. If the other importer expects the value be in the other field, some flag may
            // be needed.
            final StringBuilder addressBuilder = new StringBuilder();
            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // PO BOX ; Extended Address
            addressBuilder.append(encodedFormattedAddress);
            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Extended Address : Street
            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Street : Locality
            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Locality : Region
            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Region : Postal Code
            addressBuilder.append(VCARD_ITEM_SEPARATOR);  // Postal Code : Country
            return new PostalStruct(
                    reallyUseQuotedPrintable, appendCharset, addressBuilder.toString());
        }
    }

    public VCardBuilder appendIms(final List<ContentValues> contentValuesList) {
        if (contentValuesList != null) {
            for (ContentValues contentValues : contentValuesList) {
                final Integer protocolAsObject = contentValues.getAsInteger(Im.PROTOCOL);
                if (protocolAsObject == null) {
                    continue;
                }
                final String propertyName = VCardUtils.getPropertyNameForIm(protocolAsObject);
                if (propertyName == null) {
                    continue;
                }
                String data = contentValues.getAsString(Im.DATA);
                if (data != null) {
                    data = data.trim();
                }
                if (TextUtils.isEmpty(data)) {
                    continue;
                }
                final String typeAsString;
                {
                    final Integer typeAsInteger = contentValues.getAsInteger(Im.TYPE);
                    switch (typeAsInteger != null ? typeAsInteger : Im.TYPE_OTHER) {
                        case Im.TYPE_HOME: {
                            typeAsString = VCardConstants.PARAM_TYPE_HOME;
                            break;
                        }
                        case Im.TYPE_WORK: {
                            typeAsString = VCardConstants.PARAM_TYPE_WORK;
                            break;
                        }
                        case Im.TYPE_CUSTOM: {
                            final String label = contentValues.getAsString(Im.LABEL);
                            typeAsString = (label != null ? "X-" + label : null);
                            break;
                        }
                        case Im.TYPE_OTHER:  // Ignore
                        default: {
                            typeAsString = null;
                            break;
                        }
                    }
                }

                final List<String> parameterList = new ArrayList<String>();
                if (!TextUtils.isEmpty(typeAsString)) {
                    parameterList.add(typeAsString);
                }
                final Integer isPrimaryAsInteger = contentValues.getAsInteger(Im.IS_PRIMARY);
                final boolean isPrimary = (isPrimaryAsInteger != null ?
                        (isPrimaryAsInteger > 0) : false);
                if (isPrimary) {
                    parameterList.add(VCardConstants.PARAM_TYPE_PREF);
                }

                appendLineWithCharsetAndQPDetection(propertyName, parameterList, data);
            }
        }
        return this;
    }

    public VCardBuilder appendWebsites(final List<ContentValues> contentValuesList) {
        if (contentValuesList != null) {
            for (ContentValues contentValues : contentValuesList) {
                String website = contentValues.getAsString(Website.URL);
                if (website != null) {
                    website = website.trim();
                }

                // Note: vCard 3.0 does not allow any parameter addition toward "URL"
                //       property, while there's no document in vCard 2.1.
                if (!TextUtils.isEmpty(website)) {
                    appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_URL, website);
                }
            }
        }
        return this;
    }

    public VCardBuilder appendOrganizations(final List<ContentValues> contentValuesList) {
        if (contentValuesList != null) {
            for (ContentValues contentValues : contentValuesList) {
                String company = contentValues.getAsString(Organization.COMPANY);
                if (company != null) {
                    company = company.trim();
                }
                String department = contentValues.getAsString(Organization.DEPARTMENT);
                if (department != null) {
                    department = department.trim();
                }
                String title = contentValues.getAsString(Organization.TITLE);
                if (title != null) {
                    title = title.trim();
                }

                StringBuilder orgBuilder = new StringBuilder();
                if (!TextUtils.isEmpty(company)) {
                    orgBuilder.append(company);
                }
                if (!TextUtils.isEmpty(department)) {
                    if (orgBuilder.length() > 0) {
                        orgBuilder.append(';');
                    }
                    orgBuilder.append(department);
                }
                final String orgline = orgBuilder.toString();
                appendLine(VCardConstants.PROPERTY_ORG, orgline,
                        !VCardUtils.containsOnlyPrintableAscii(orgline),
                        (mShouldUseQuotedPrintable &&
                                !VCardUtils.containsOnlyNonCrLfPrintableAscii(orgline)));

                if (!TextUtils.isEmpty(title)) {
                    appendLine(VCardConstants.PROPERTY_TITLE, title,
                            !VCardUtils.containsOnlyPrintableAscii(title),
                            (mShouldUseQuotedPrintable &&
                                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(title)));
                }
            }
        }
        return this;
    }

    public VCardBuilder appendPhotos(final List<ContentValues> contentValuesList) {
        if (contentValuesList != null) {
            for (ContentValues contentValues : contentValuesList) {
                if (contentValues == null) {
                    continue;
                }
                byte[] data = contentValues.getAsByteArray(Photo.PHOTO);
                if (data == null) {
                    continue;
                }
                final String photoType = VCardUtils.guessImageType(data);
                if (photoType == null) {
                    Log.d(LOG_TAG, "Unknown photo type. Ignored.");
                    continue;
                }
                // TODO: check this works fine.
                final String photoString = new String(Base64.encode(data, Base64.NO_WRAP));
                if (!TextUtils.isEmpty(photoString)) {
                    appendPhotoLine(photoString, photoType);
                }
            }
        }
        return this;
    }

    public VCardBuilder appendNotes(final List<ContentValues> contentValuesList) {
        if (contentValuesList != null) {
            if (mOnlyOneNoteFieldIsAvailable) {
                final StringBuilder noteBuilder = new StringBuilder();
                boolean first = true;
                for (final ContentValues contentValues : contentValuesList) {
                    String note = contentValues.getAsString(Note.NOTE);
                    if (note == null) {
                        note = "";
                    }
                    if (note.length() > 0) {
                        if (first) {
                            first = false;
                        } else {
                            noteBuilder.append('\n');
                        }
                        noteBuilder.append(note);
                    }
                }
                final String noteStr = noteBuilder.toString();
                // This means we scan noteStr completely twice, which is redundant.
                // But for now, we assume this is not so time-consuming..
                final boolean shouldAppendCharsetInfo =
                    !VCardUtils.containsOnlyPrintableAscii(noteStr);
                final boolean reallyUseQuotedPrintable =
                        (mShouldUseQuotedPrintable &&
                            !VCardUtils.containsOnlyNonCrLfPrintableAscii(noteStr));
                appendLine(VCardConstants.PROPERTY_NOTE, noteStr,
                        shouldAppendCharsetInfo, reallyUseQuotedPrintable);
            } else {
                for (ContentValues contentValues : contentValuesList) {
                    final String noteStr = contentValues.getAsString(Note.NOTE);
                    if (!TextUtils.isEmpty(noteStr)) {
                        final boolean shouldAppendCharsetInfo =
                                !VCardUtils.containsOnlyPrintableAscii(noteStr);
                        final boolean reallyUseQuotedPrintable =
                                (mShouldUseQuotedPrintable &&
                                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(noteStr));
                        appendLine(VCardConstants.PROPERTY_NOTE, noteStr,
                                shouldAppendCharsetInfo, reallyUseQuotedPrintable);
                    }
                }
            }
        }
        return this;
    }

    public VCardBuilder appendEvents(final List<ContentValues> contentValuesList) {
        // There's possibility where a given object may have more than one birthday, which
        // is inappropriate. We just build one birthday.
        if (contentValuesList != null) {
            String primaryBirthday = null;
            String secondaryBirthday = null;
            for (final ContentValues contentValues : contentValuesList) {
                if (contentValues == null) {
                    continue;
                }
                final Integer eventTypeAsInteger = contentValues.getAsInteger(Event.TYPE);
                final int eventType;
                if (eventTypeAsInteger != null) {
                    eventType = eventTypeAsInteger;
                } else {
                    eventType = Event.TYPE_OTHER;
                }
                if (eventType == Event.TYPE_BIRTHDAY) {
                    final String birthdayCandidate = contentValues.getAsString(Event.START_DATE);
                    if (birthdayCandidate == null) {
                        continue;
                    }
                    final Integer isSuperPrimaryAsInteger =
                        contentValues.getAsInteger(Event.IS_SUPER_PRIMARY);
                    final boolean isSuperPrimary = (isSuperPrimaryAsInteger != null ?
                            (isSuperPrimaryAsInteger > 0) : false);
                    if (isSuperPrimary) {
                        // "super primary" birthday should the prefered one.
                        primaryBirthday = birthdayCandidate;
                        break;
                    }
                    final Integer isPrimaryAsInteger =
                        contentValues.getAsInteger(Event.IS_PRIMARY);
                    final boolean isPrimary = (isPrimaryAsInteger != null ?
                            (isPrimaryAsInteger > 0) : false);
                    if (isPrimary) {
                        // We don't break here since "super primary" birthday may exist later.
                        primaryBirthday = birthdayCandidate;
                    } else if (secondaryBirthday == null) {
                        // First entry is set to the "secondary" candidate.
                        secondaryBirthday = birthdayCandidate;
                    }
                } else if (mUsesAndroidProperty) {
                    // Event types other than Birthday is not supported by vCard.
                    appendAndroidSpecificProperty(Event.CONTENT_ITEM_TYPE, contentValues);
                }
            }
            if (primaryBirthday != null) {
                appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_BDAY,
                        primaryBirthday.trim());
            } else if (secondaryBirthday != null){
                appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_BDAY,
                        secondaryBirthday.trim());
            }
        }
        return this;
    }

    public VCardBuilder appendRelation(final List<ContentValues> contentValuesList) {
        if (mUsesAndroidProperty && contentValuesList != null) {
            for (final ContentValues contentValues : contentValuesList) {
                if (contentValues == null) {
                    continue;
                }
                appendAndroidSpecificProperty(Relation.CONTENT_ITEM_TYPE, contentValues);
            }
        }
        return this;
    }

    /**
     * @param emitEveryTime If true, builder builds the line even when there's no entry.
     */
    public void appendPostalLine(final int type, final String label,
            final ContentValues contentValues,
            final boolean isPrimary, final boolean emitEveryTime) {
        final boolean reallyUseQuotedPrintable;
        final boolean appendCharset;
        final String addressValue;
        {
            PostalStruct postalStruct = tryConstructPostalStruct(contentValues);
            if (postalStruct == null) {
                if (emitEveryTime) {
                    reallyUseQuotedPrintable = false;
                    appendCharset = false;
                    addressValue = "";
                } else {
                    return;
                }
            } else {
                reallyUseQuotedPrintable = postalStruct.reallyUseQuotedPrintable;
                appendCharset = postalStruct.appendCharset;
                addressValue = postalStruct.addressData;
            }
        }

        List<String> parameterList = new ArrayList<String>();
        if (isPrimary) {
            parameterList.add(VCardConstants.PARAM_TYPE_PREF);
        }
        switch (type) {
            case StructuredPostal.TYPE_HOME: {
                parameterList.add(VCardConstants.PARAM_TYPE_HOME);
                break;
            }
            case StructuredPostal.TYPE_WORK: {
                parameterList.add(VCardConstants.PARAM_TYPE_WORK);
                break;
            }
            case StructuredPostal.TYPE_CUSTOM: {
                if (!TextUtils.isEmpty(label)
                        && VCardUtils.containsOnlyAlphaDigitHyphen(label)) {
                    // We're not sure whether the label is valid in the spec
                    // ("IANA-token" in the vCard 3.0 is unclear...)
                    // Just  for safety, we add "X-" at the beggining of each label.
                    // Also checks the label obeys with vCard 3.0 spec.
                    parameterList.add("X-" + label);
                }
                break;
            }
            case StructuredPostal.TYPE_OTHER: {
                break;
            }
            default: {
                Log.e(LOG_TAG, "Unknown StructuredPostal type: " + type);
                break;
            }
        }

        mBuilder.append(VCardConstants.PROPERTY_ADR);
        if (!parameterList.isEmpty()) {
            mBuilder.append(VCARD_PARAM_SEPARATOR);
            appendTypeParameters(parameterList);
        }
        if (appendCharset) {
            // Strictly, vCard 3.0 does not allow exporters to emit charset information,
            // but we will add it since the information should be useful for importers,
            //
            // Assume no parser does not emit error with this parameter in vCard 3.0.
            mBuilder.append(VCARD_PARAM_SEPARATOR);
            mBuilder.append(mVCardCharsetParameter);
        }
        if (reallyUseQuotedPrintable) {
            mBuilder.append(VCARD_PARAM_SEPARATOR);
            mBuilder.append(VCARD_PARAM_ENCODING_QP);
        }
        mBuilder.append(VCARD_DATA_SEPARATOR);
        mBuilder.append(addressValue);
        mBuilder.append(VCARD_END_OF_LINE);
    }

    public void appendEmailLine(final int type, final String label,
            final String rawValue, final boolean isPrimary) {
        final String typeAsString;
        switch (type) {
            case Email.TYPE_CUSTOM: {
                if (VCardUtils.isMobilePhoneLabel(label)) {
                    typeAsString = VCardConstants.PARAM_TYPE_CELL;
                } else if (!TextUtils.isEmpty(label)
                        && VCardUtils.containsOnlyAlphaDigitHyphen(label)) {
                    typeAsString = "X-" + label;
                } else {
                    typeAsString = null;
                }
                break;
            }
            case Email.TYPE_HOME: {
                typeAsString = VCardConstants.PARAM_TYPE_HOME;
                break;
            }
            case Email.TYPE_WORK: {
                typeAsString = VCardConstants.PARAM_TYPE_WORK;
                break;
            }
            case Email.TYPE_OTHER: {
                typeAsString = null;
                break;
            }
            case Email.TYPE_MOBILE: {
                typeAsString = VCardConstants.PARAM_TYPE_CELL;
                break;
            }
            default: {
                Log.e(LOG_TAG, "Unknown Email type: " + type);
                typeAsString = null;
                break;
            }
        }

        final List<String> parameterList = new ArrayList<String>();
        if (isPrimary) {
            parameterList.add(VCardConstants.PARAM_TYPE_PREF);
        }
        if (!TextUtils.isEmpty(typeAsString)) {
            parameterList.add(typeAsString);
        }

        appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_EMAIL, parameterList,
                rawValue);
    }

    public void appendTelLine(final Integer typeAsInteger, final String label,
            final String encodedValue, boolean isPrimary) {
        mBuilder.append(VCardConstants.PROPERTY_TEL);
        mBuilder.append(VCARD_PARAM_SEPARATOR);

        final int type;
        if (typeAsInteger == null) {
            type = Phone.TYPE_OTHER;
        } else {
            type = typeAsInteger;
        }

        ArrayList<String> parameterList = new ArrayList<String>();
        switch (type) {
            case Phone.TYPE_HOME: {
                parameterList.addAll(
                        Arrays.asList(VCardConstants.PARAM_TYPE_HOME));
                break;
            }
            case Phone.TYPE_WORK: {
                parameterList.addAll(
                        Arrays.asList(VCardConstants.PARAM_TYPE_WORK));
                break;
            }
            case Phone.TYPE_FAX_HOME: {
                parameterList.addAll(
                        Arrays.asList(VCardConstants.PARAM_TYPE_HOME, VCardConstants.PARAM_TYPE_FAX));
                break;
            }
            case Phone.TYPE_FAX_WORK: {
                parameterList.addAll(
                        Arrays.asList(VCardConstants.PARAM_TYPE_WORK, VCardConstants.PARAM_TYPE_FAX));
                break;
            }
            case Phone.TYPE_MOBILE: {
                parameterList.add(VCardConstants.PARAM_TYPE_CELL);
                break;
            }
            case Phone.TYPE_PAGER: {
                if (mIsDoCoMo) {
                    // Not sure about the reason, but previous implementation had
                    // used "VOICE" instead of "PAGER"
                    parameterList.add(VCardConstants.PARAM_TYPE_VOICE);
                } else {
                    parameterList.add(VCardConstants.PARAM_TYPE_PAGER);
                }
                break;
            }
            case Phone.TYPE_OTHER: {
                parameterList.add(VCardConstants.PARAM_TYPE_VOICE);
                break;
            }
            case Phone.TYPE_CAR: {
                parameterList.add(VCardConstants.PARAM_TYPE_CAR);
                break;
            }
            case Phone.TYPE_COMPANY_MAIN: {
                // There's no relevant field in vCard (at least 2.1).
                parameterList.add(VCardConstants.PARAM_TYPE_WORK);
                isPrimary = true;
                break;
            }
            case Phone.TYPE_ISDN: {
                parameterList.add(VCardConstants.PARAM_TYPE_ISDN);
                break;
            }
            case Phone.TYPE_MAIN: {
                isPrimary = true;
                break;
            }
            case Phone.TYPE_OTHER_FAX: {
                parameterList.add(VCardConstants.PARAM_TYPE_FAX);
                break;
            }
            case Phone.TYPE_TELEX: {
                parameterList.add(VCardConstants.PARAM_TYPE_TLX);
                break;
            }
            case Phone.TYPE_WORK_MOBILE: {
                parameterList.addAll(
                        Arrays.asList(VCardConstants.PARAM_TYPE_WORK, VCardConstants.PARAM_TYPE_CELL));
                break;
            }
            case Phone.TYPE_WORK_PAGER: {
                parameterList.add(VCardConstants.PARAM_TYPE_WORK);
                // See above.
                if (mIsDoCoMo) {
                    parameterList.add(VCardConstants.PARAM_TYPE_VOICE);
                } else {
                    parameterList.add(VCardConstants.PARAM_TYPE_PAGER);
                }
                break;
            }
            case Phone.TYPE_MMS: {
                parameterList.add(VCardConstants.PARAM_TYPE_MSG);
                break;
            }
            case Phone.TYPE_CUSTOM: {
                if (TextUtils.isEmpty(label)) {
                    // Just ignore the custom type.
                    parameterList.add(VCardConstants.PARAM_TYPE_VOICE);
                } else if (VCardUtils.isMobilePhoneLabel(label)) {
                    parameterList.add(VCardConstants.PARAM_TYPE_CELL);
                } else if (mIsV30OrV40) {
                    // This label is appropriately encoded in appendTypeParameters.
                    parameterList.add(label);
                } else {
                    final String upperLabel = label.toUpperCase();
                    if (VCardUtils.isValidInV21ButUnknownToContactsPhoteType(upperLabel)) {
                        parameterList.add(upperLabel);
                    } else if (VCardUtils.containsOnlyAlphaDigitHyphen(label)) {
                        // Note: Strictly, vCard 2.1 does not allow "X-" parameter without
                        //       "TYPE=" string.
                        parameterList.add("X-" + label);
                    }
                }
                break;
            }
            case Phone.TYPE_RADIO:
            case Phone.TYPE_TTY_TDD:
            default: {
                break;
            }
        }

        if (isPrimary) {
            parameterList.add(VCardConstants.PARAM_TYPE_PREF);
        }

        if (parameterList.isEmpty()) {
            appendUncommonPhoneType(mBuilder, type);
        } else {
            appendTypeParameters(parameterList);
        }

        mBuilder.append(VCARD_DATA_SEPARATOR);
        mBuilder.append(encodedValue);
        mBuilder.append(VCARD_END_OF_LINE);
    }

    /**
     * Appends phone type string which may not be available in some devices.
     */
    private void appendUncommonPhoneType(final StringBuilder builder, final Integer type) {
        if (mIsDoCoMo) {
            // The previous implementation for DoCoMo had been conservative
            // about miscellaneous types.
            builder.append(VCardConstants.PARAM_TYPE_VOICE);
        } else {
            String phoneType = VCardUtils.getPhoneTypeString(type);
            if (phoneType != null) {
                appendTypeParameter(phoneType);
            } else {
                Log.e(LOG_TAG, "Unknown or unsupported (by vCard) Phone type: " + type);
            }
        }
    }

    /**
     * @param encodedValue Must be encoded by BASE64
     * @param photoType
     */
    public void appendPhotoLine(final String encodedValue, final String photoType) {
        StringBuilder tmpBuilder = new StringBuilder();
        tmpBuilder.append(VCardConstants.PROPERTY_PHOTO);
        tmpBuilder.append(VCARD_PARAM_SEPARATOR);
        if (mIsV30OrV40) {
            tmpBuilder.append(VCARD_PARAM_ENCODING_BASE64_AS_B);
        } else {
            tmpBuilder.append(VCARD_PARAM_ENCODING_BASE64_V21);
        }
        tmpBuilder.append(VCARD_PARAM_SEPARATOR);
        appendTypeParameter(tmpBuilder, photoType);
        tmpBuilder.append(VCARD_DATA_SEPARATOR);
        tmpBuilder.append(encodedValue);

        final String tmpStr = tmpBuilder.toString();
        tmpBuilder = new StringBuilder();
        int lineCount = 0;
        final int length = tmpStr.length();
        final int maxNumForFirstLine = VCardConstants.MAX_CHARACTER_NUMS_BASE64_V30
                - VCARD_END_OF_LINE.length();
        final int maxNumInGeneral = maxNumForFirstLine - VCARD_WS.length();
        int maxNum = maxNumForFirstLine;
        for (int i = 0; i < length; i++) {
            tmpBuilder.append(tmpStr.charAt(i));
            lineCount++;
            if (lineCount > maxNum) {
                tmpBuilder.append(VCARD_END_OF_LINE);
                tmpBuilder.append(VCARD_WS);
                maxNum = maxNumInGeneral;
                lineCount = 0;
            }
        }
        mBuilder.append(tmpBuilder.toString());
        mBuilder.append(VCARD_END_OF_LINE);
        mBuilder.append(VCARD_END_OF_LINE);
    }

    /**
     * SIP (Session Initiation Protocol) is first supported in RFC 4770 as part of IMPP
     * support. vCard 2.1 and old vCard 3.0 may not able to parse it, or expect X-SIP
     * instead of "IMPP;sip:...".
     *
     * We honor RFC 4770 and don't allow vCard 3.0 to emit X-SIP at all.
     */
    public VCardBuilder appendSipAddresses(final List<ContentValues> contentValuesList) {
        final boolean useXProperty;
        if (mIsV30OrV40) {
            useXProperty = false;
        } else if (mUsesDefactProperty){
            useXProperty = true;
        } else {
            return this;
        }

        if (contentValuesList != null) {
            for (ContentValues contentValues : contentValuesList) {
                String sipAddress = contentValues.getAsString(SipAddress.SIP_ADDRESS);
                if (TextUtils.isEmpty(sipAddress)) {
                    continue;
                }
                if (useXProperty) {
                    // X-SIP does not contain "sip:" prefix.
                    if (sipAddress.startsWith("sip:")) {
                        if (sipAddress.length() == 4) {
                            continue;
                        }
                        sipAddress = sipAddress.substring(4);
                    }
                    // No type is available yet.
                    appendLineWithCharsetAndQPDetection(VCardConstants.PROPERTY_X_SIP, sipAddress);
                } else {
                    if (!sipAddress.startsWith("sip:")) {
                        sipAddress = "sip:" + sipAddress;
                    }
                    final String propertyName;
                    if (VCardConfig.isVersion40(mVCardType)) {
                        // We have two ways to emit sip address: TEL and IMPP. Currently (rev.13)
                        // TEL seems appropriate but may change in the future.
                        propertyName = VCardConstants.PROPERTY_TEL;
                    } else {
                        // RFC 4770 (for vCard 3.0)
                        propertyName = VCardConstants.PROPERTY_IMPP;
                    }
                    appendLineWithCharsetAndQPDetection(propertyName, sipAddress);
                }
            }
        }
        return this;
    }

    public void appendAndroidSpecificProperty(
            final String mimeType, ContentValues contentValues) {
        if (!sAllowedAndroidPropertySet.contains(mimeType)) {
            return;
        }
        final List<String> rawValueList = new ArrayList<String>();
        for (int i = 1; i <= VCardConstants.MAX_DATA_COLUMN; i++) {
            String value = contentValues.getAsString("data" + i);
            if (value == null) {
                value = "";
            }
            rawValueList.add(value);
        }

        boolean needCharset =
            (mShouldAppendCharsetParam &&
                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList));
        boolean reallyUseQuotedPrintable =
            (mShouldUseQuotedPrintable &&
                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList));
        mBuilder.append(VCardConstants.PROPERTY_X_ANDROID_CUSTOM);
        if (needCharset) {
            mBuilder.append(VCARD_PARAM_SEPARATOR);
            mBuilder.append(mVCardCharsetParameter);
        }
        if (reallyUseQuotedPrintable) {
            mBuilder.append(VCARD_PARAM_SEPARATOR);
            mBuilder.append(VCARD_PARAM_ENCODING_QP);
        }
        mBuilder.append(VCARD_DATA_SEPARATOR);
        mBuilder.append(mimeType);  // Should not be encoded.
        for (String rawValue : rawValueList) {
            final String encodedValue;
            if (reallyUseQuotedPrintable) {
                encodedValue = encodeQuotedPrintable(rawValue);
            } else {
                // TODO: one line may be too huge, which may be invalid in vCard 3.0
                //        (which says "When generating a content line, lines longer than
                //        75 characters SHOULD be folded"), though several
                //        (even well-known) applications do not care this.
                encodedValue = escapeCharacters(rawValue);
            }
            mBuilder.append(VCARD_ITEM_SEPARATOR);
            mBuilder.append(encodedValue);
        }
        mBuilder.append(VCARD_END_OF_LINE);
    }

    public void appendLineWithCharsetAndQPDetection(final String propertyName,
            final String rawValue) {
        appendLineWithCharsetAndQPDetection(propertyName, null, rawValue);
    }

    public void appendLineWithCharsetAndQPDetection(
            final String propertyName, final List<String> rawValueList) {
        appendLineWithCharsetAndQPDetection(propertyName, null, rawValueList);
    }

    public void appendLineWithCharsetAndQPDetection(final String propertyName,
            final List<String> parameterList, final String rawValue) {
        final boolean needCharset =
                !VCardUtils.containsOnlyPrintableAscii(rawValue);
        final boolean reallyUseQuotedPrintable =
                (mShouldUseQuotedPrintable &&
                        !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValue));
        appendLine(propertyName, parameterList,
                rawValue, needCharset, reallyUseQuotedPrintable);
    }

    public void appendLineWithCharsetAndQPDetection(final String propertyName,
            final List<String> parameterList, final List<String> rawValueList) {
        boolean needCharset =
            (mShouldAppendCharsetParam &&
                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList));
        boolean reallyUseQuotedPrintable =
            (mShouldUseQuotedPrintable &&
                    !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawValueList));
        appendLine(propertyName, parameterList, rawValueList,
                needCharset, reallyUseQuotedPrintable);
    }

    /**
     * Appends one line with a given property name and value.
     */
    public void appendLine(final String propertyName, final String rawValue) {
        appendLine(propertyName, rawValue, false, false);
    }

    public void appendLine(final String propertyName, final List<String> rawValueList) {
        appendLine(propertyName, rawValueList, false, false);
    }

    public void appendLine(final String propertyName,
            final String rawValue, final boolean needCharset,
            boolean reallyUseQuotedPrintable) {
        appendLine(propertyName, null, rawValue, needCharset, reallyUseQuotedPrintable);
    }

    public void appendLine(final String propertyName, final List<String> parameterList,
            final String rawValue) {
        appendLine(propertyName, parameterList, rawValue, false, false);
    }

    public void appendLine(final String propertyName, final List<String> parameterList,
            final String rawValue, final boolean needCharset,
            boolean reallyUseQuotedPrintable) {
        mBuilder.append(propertyName);
        if (parameterList != null && parameterList.size() > 0) {
            mBuilder.append(VCARD_PARAM_SEPARATOR);
            appendTypeParameters(parameterList);
        }
        if (needCharset) {
            mBuilder.append(VCARD_PARAM_SEPARATOR);
            mBuilder.append(mVCardCharsetParameter);
        }

        final String encodedValue;
        if (reallyUseQuotedPrintable) {
            mBuilder.append(VCARD_PARAM_SEPARATOR);
            mBuilder.append(VCARD_PARAM_ENCODING_QP);
            encodedValue = encodeQuotedPrintable(rawValue);
        } else {
            // TODO: one line may be too huge, which may be invalid in vCard spec, though
            //       several (even well-known) applications do not care that violation.
            encodedValue = escapeCharacters(rawValue);
        }

        mBuilder.append(VCARD_DATA_SEPARATOR);
        mBuilder.append(encodedValue);
        mBuilder.append(VCARD_END_OF_LINE);
    }

    public void appendLine(final String propertyName, final List<String> rawValueList,
            final boolean needCharset, boolean needQuotedPrintable) {
        appendLine(propertyName, null, rawValueList, needCharset, needQuotedPrintable);
    }

    public void appendLine(final String propertyName, final List<String> parameterList,
            final List<String> rawValueList, final boolean needCharset,
            final boolean needQuotedPrintable) {
        mBuilder.append(propertyName);
        if (parameterList != null && parameterList.size() > 0) {
            mBuilder.append(VCARD_PARAM_SEPARATOR);
            appendTypeParameters(parameterList);
        }
        if (needCharset) {
            mBuilder.append(VCARD_PARAM_SEPARATOR);
            mBuilder.append(mVCardCharsetParameter);
        }
        if (needQuotedPrintable) {
            mBuilder.append(VCARD_PARAM_SEPARATOR);
            mBuilder.append(VCARD_PARAM_ENCODING_QP);
        }

        mBuilder.append(VCARD_DATA_SEPARATOR);
        boolean first = true;
        for (String rawValue : rawValueList) {
            final String encodedValue;
            if (needQuotedPrintable) {
                encodedValue = encodeQuotedPrintable(rawValue);
            } else {
                // TODO: one line may be too huge, which may be invalid in vCard 3.0
                //        (which says "When generating a content line, lines longer than
                //        75 characters SHOULD be folded"), though several
                //        (even well-known) applications do not care this.
                encodedValue = escapeCharacters(rawValue);
            }

            if (first) {
                first = false;
            } else {
                mBuilder.append(VCARD_ITEM_SEPARATOR);
            }
            mBuilder.append(encodedValue);
        }
        mBuilder.append(VCARD_END_OF_LINE);
    }

    /**
     * VCARD_PARAM_SEPARATOR must be appended before this method being called.
     */
    private void appendTypeParameters(final List<String> types) {
        // We may have to make this comma separated form like "TYPE=DOM,WORK" in the future,
        // which would be recommended way in vcard 3.0 though not valid in vCard 2.1.
        boolean first = true;
        for (final String typeValue : types) {
            if (VCardConfig.isVersion30(mVCardType) || VCardConfig.isVersion40(mVCardType)) {
                final String encoded = (VCardConfig.isVersion40(mVCardType) ?
                        VCardUtils.toStringAsV40ParamValue(typeValue) :
                        VCardUtils.toStringAsV30ParamValue(typeValue));
                if (TextUtils.isEmpty(encoded)) {
                    continue;
                }

                if (first) {
                    first = false;
                } else {
                    mBuilder.append(VCARD_PARAM_SEPARATOR);
                }
                appendTypeParameter(encoded);
            } else {  // vCard 2.1
                if (!VCardUtils.isV21Word(typeValue)) {
                    continue;
                }
                if (first) {
                    first = false;
                } else {
                    mBuilder.append(VCARD_PARAM_SEPARATOR);
                }
                appendTypeParameter(typeValue);
            }
        }
    }

    /**
     * VCARD_PARAM_SEPARATOR must be appended before this method being called.
     */
    private void appendTypeParameter(final String type) {
        appendTypeParameter(mBuilder, type);
    }

    private void appendTypeParameter(final StringBuilder builder, final String type) {
        // Refrain from using appendType() so that "TYPE=" is not be appended when the
        // device is DoCoMo's (just for safety).
        //
        // Note: In vCard 3.0, Type strings also can be like this: "TYPE=HOME,PREF"
        if (VCardConfig.isVersion40(mVCardType) ||
                ((VCardConfig.isVersion30(mVCardType) || mAppendTypeParamName) && !mIsDoCoMo)) {
            builder.append(VCardConstants.PARAM_TYPE).append(VCARD_PARAM_EQUAL);
        }
        builder.append(type);
    }

    /**
     * Returns true when the property line should contain charset parameter
     * information. This method may return true even when vCard version is 3.0.
     *
     * Strictly, adding charset information is invalid in VCard 3.0.
     * However we'll add the info only when charset we use is not UTF-8
     * in vCard 3.0 format, since parser side may be able to use the charset
     * via this field, though we may encounter another problem by adding it.
     *
     * e.g. Japanese mobile phones use Shift_Jis while RFC 2426
     * recommends UTF-8. By adding this field, parsers may be able
     * to know this text is NOT UTF-8 but Shift_Jis.
     */
    private boolean shouldAppendCharsetParam(String...propertyValueList) {
        if (!mShouldAppendCharsetParam) {
            return false;
        }
        for (String propertyValue : propertyValueList) {
            if (!VCardUtils.containsOnlyPrintableAscii(propertyValue)) {
                return true;
            }
        }
        return false;
    }

    private String encodeQuotedPrintable(final String str) {
        if (TextUtils.isEmpty(str)) {
            return "";
        }

        final StringBuilder builder = new StringBuilder();
        int index = 0;
        int lineCount = 0;
        byte[] strArray = null;

        try {
            strArray = str.getBytes(mCharset);
        } catch (UnsupportedEncodingException e) {
            Log.e(LOG_TAG, "Charset " + mCharset + " cannot be used. "
                    + "Try default charset");
            strArray = str.getBytes();
        }
        while (index < strArray.length) {
            builder.append(String.format("=%02X", strArray[index]));
            index += 1;
            lineCount += 3;

            if (lineCount >= 67) {
                // Specification requires CRLF must be inserted before the
                // length of the line
                // becomes more than 76.
                // Assuming that the next character is a multi-byte character,
                // it will become
                // 6 bytes.
                // 76 - 6 - 3 = 67
                builder.append("=\r\n");
                lineCount = 0;
            }
        }

        return builder.toString();
    }

    /**
     * Append '\' to the characters which should be escaped. The character set is different
     * not only between vCard 2.1 and vCard 3.0 but also among each device.
     *
     * Note that Quoted-Printable string must not be input here.
     */
    @SuppressWarnings("fallthrough")
    private String escapeCharacters(final String unescaped) {
        if (TextUtils.isEmpty(unescaped)) {
            return "";
        }

        final StringBuilder tmpBuilder = new StringBuilder();
        final int length = unescaped.length();
        for (int i = 0; i < length; i++) {
            final char ch = unescaped.charAt(i);
            switch (ch) {
                case ';': {
                    tmpBuilder.append('\\');
                    tmpBuilder.append(';');
                    break;
                }
                case '\r': {
                    if (i + 1 < length) {
                        char nextChar = unescaped.charAt(i);
                        if (nextChar == '\n') {
                            break;
                        } else {
                            // fall through
                        }
                    } else {
                        // fall through
                    }
                }
                case '\n': {
                    // In vCard 2.1, there's no specification about this, while
                    // vCard 3.0 explicitly requires this should be encoded to "\n".
                    tmpBuilder.append("\\n");
                    break;
                }
                case '\\': {
                    if (mIsV30OrV40) {
                        tmpBuilder.append("\\\\");
                        break;
                    } else {
                        // fall through
                    }
                }
                case '<':
                case '>': {
                    if (mIsDoCoMo) {
                        tmpBuilder.append('\\');
                        tmpBuilder.append(ch);
                    } else {
                        tmpBuilder.append(ch);
                    }
                    break;
                }
                case ',': {
                    if (mIsV30OrV40) {
                        tmpBuilder.append("\\,");
                    } else {
                        tmpBuilder.append(ch);
                    }
                    break;
                }
                default: {
                    tmpBuilder.append(ch);
                    break;
                }
            }
        }
        return tmpBuilder.toString();
    }

    @Override
    public String toString() {
        if (!mEndAppended) {
            if (mIsDoCoMo) {
                appendLine(VCardConstants.PROPERTY_X_CLASS, VCARD_DATA_PUBLIC);
                appendLine(VCardConstants.PROPERTY_X_REDUCTION, "");
                appendLine(VCardConstants.PROPERTY_X_NO, "");
                appendLine(VCardConstants.PROPERTY_X_DCM_HMN_MODE, "");
            }
            appendLine(VCardConstants.PROPERTY_END, VCARD_DATA_VCARD);
            mEndAppended = true;
        }
        return mBuilder.toString();
    }
}
