/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.vcard;

import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;

import com.android.vcard.exception.VCardAgentNotSupportedException;
import com.android.vcard.exception.VCardException;
import com.android.vcard.exception.VCardInvalidCommentLineException;
import com.android.vcard.exception.VCardInvalidLineException;
import com.android.vcard.exception.VCardVersionException;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * Basic implementation achieving vCard parsing. Based on vCard 2.1.
 * </p>
 * @hide
 */
/* package */ class VCardParserImpl_V21 {
    private static final String LOG_TAG = VCardConstants.LOG_TAG;

    protected static final class CustomBufferedReader extends BufferedReader {
        private long mTime;

        /**
         * Needed since "next line" may be null due to end of line.
         */
        private boolean mNextLineIsValid;
        private String mNextLine;

        public CustomBufferedReader(Reader in) {
            super(in);
        }

        @Override
        public String readLine() throws IOException {
            if (mNextLineIsValid) {
                final String ret = mNextLine;
                mNextLine = null;
                mNextLineIsValid = false;
                return ret;
            }

            final long start = System.currentTimeMillis();
            final String line = super.readLine();
            final long end = System.currentTimeMillis();
            mTime += end - start;
            return line;
        }

        /**
         * Read one line, but make this object store it in its queue.
         */
        public String peekLine() throws IOException {
            if (!mNextLineIsValid) {
                final long start = System.currentTimeMillis();
                final String line = super.readLine();
                final long end = System.currentTimeMillis();
                mTime += end - start;

                mNextLine = line;
                mNextLineIsValid = true;
            }

            return mNextLine;
        }

        public long getTotalmillisecond() {
            return mTime;
        }
    }

    private static final String DEFAULT_ENCODING = "8BIT";
    private static final String DEFAULT_CHARSET = "UTF-8";

    protected final String mIntermediateCharset;

    private final List<VCardInterpreter> mInterpreterList = new ArrayList<VCardInterpreter>();
    private boolean mCanceled;

    /**
     * <p>
     * The encoding type for deconding byte streams. This member variable is
     * reset to a default encoding every time when a new item comes.
     * </p>
     * <p>
     * "Encoding" in vCard is different from "Charset". It is mainly used for
     * addresses, notes, images. "7BIT", "8BIT", "BASE64", and
     * "QUOTED-PRINTABLE" are known examples.
     * </p>
     */
    protected String mCurrentEncoding;

    protected String mCurrentCharset;

    /**
     * <p>
     * The reader object to be used internally.
     * </p>
     * <p>
     * Developers should not directly read a line from this object. Use
     * getLine() unless there some reason.
     * </p>
     */
    protected CustomBufferedReader mReader;

    /**
     * <p>
     * Set for storing unkonwn TYPE attributes, which is not acceptable in vCard
     * specification, but happens to be seen in real world vCard.
     * </p>
     * <p>
     * We just accept those invalid types after emitting a warning for each of it.
     * </p>
     */
    protected final Set<String> mUnknownTypeSet = new HashSet<String>();

    /**
     * <p>
     * Set for storing unkonwn VALUE attributes, which is not acceptable in
     * vCard specification, but happens to be seen in real world vCard.
     * </p>
     * <p>
     * We just accept those invalid types after emitting a warning for each of it.
     * </p>
     */
    protected final Set<String> mUnknownValueSet = new HashSet<String>();


    public VCardParserImpl_V21() {
        this(VCardConfig.VCARD_TYPE_DEFAULT);
    }

    public VCardParserImpl_V21(int vcardType) {
        mIntermediateCharset =  VCardConfig.DEFAULT_INTERMEDIATE_CHARSET;
    }

    /**
     * @return true when a given property name is a valid property name.
     */
    protected boolean isValidPropertyName(final String propertyName) {
        if (!(getKnownPropertyNameSet().contains(propertyName.toUpperCase()) ||
                propertyName.startsWith("X-"))
                && !mUnknownTypeSet.contains(propertyName)) {
            mUnknownTypeSet.add(propertyName);
            Log.w(LOG_TAG, "Property name unsupported by vCard 2.1: " + propertyName);
        }
        return true;
    }

    /**
     * @return String. It may be null, or its length may be 0
     * @throws IOException
     */
    protected String getLine() throws IOException {
        return mReader.readLine();
    }

    protected String peekLine() throws IOException {
        return mReader.peekLine();
    }

    /**
     * @return String with it's length > 0
     * @throws IOException
     * @throws VCardException when the stream reached end of line
     */
    protected String getNonEmptyLine() throws IOException, VCardException {
        String line;
        while (true) {
            line = getLine();
            if (line == null) {
                throw new VCardException("Reached end of buffer.");
            } else if (line.trim().length() > 0) {
                return line;
            }
        }
    }

    /**
     * <code>
     * vcard = "BEGIN" [ws] ":" [ws] "VCARD" [ws] 1*CRLF
     *         items *CRLF
     *         "END" [ws] ":" [ws] "VCARD"
     * </code>
     * @return False when reaching end of file.
     */
    private boolean parseOneVCard() throws IOException, VCardException {
        // reset for this entire vCard.
        mCurrentEncoding = DEFAULT_ENCODING;
        mCurrentCharset = DEFAULT_CHARSET;

        boolean allowGarbage = false;
        if (!readBeginVCard(allowGarbage)) {
            return false;
        }
        for (VCardInterpreter interpreter : mInterpreterList) {
            interpreter.onEntryStarted();
        }
        parseItems();
        for (VCardInterpreter interpreter : mInterpreterList) {
            interpreter.onEntryEnded();
        }
        return true;
    }

    /**
     * @return True when successful. False when reaching the end of line
     * @throws IOException
     * @throws VCardException
     */
    protected boolean readBeginVCard(boolean allowGarbage) throws IOException, VCardException {
        // TODO: use consructPropertyLine().
        String line;
        do {
            while (true) {
                line = getLine();
                if (line == null) {
                    return false;
                } else if (line.trim().length() > 0) {
                    break;
                }
            }
            final String[] strArray = line.split(":", 2);
            final int length = strArray.length;

            // Although vCard 2.1/3.0 specification does not allow lower cases,
            // we found vCard file emitted by some external vCard expoter have such
            // invalid Strings.
            // e.g. BEGIN:vCard
            if (length == 2 && strArray[0].trim().equalsIgnoreCase("BEGIN")
                    && strArray[1].trim().equalsIgnoreCase("VCARD")) {
                return true;
            } else if (!allowGarbage) {
                throw new VCardException("Expected String \"BEGIN:VCARD\" did not come "
                        + "(Instead, \"" + line + "\" came)");
            }
        } while (allowGarbage);

        throw new VCardException("Reached where must not be reached.");
    }

    /**
     * Parses lines other than the first "BEGIN:VCARD". Takes care of "END:VCARD"n and
     * "BEGIN:VCARD" in nested vCard.
     */
    /*
     * items = *CRLF item / item
     *
     * Note: BEGIN/END aren't include in the original spec while this method handles them.
     */
    protected void parseItems() throws IOException, VCardException {
        boolean ended = false;

        try {
            ended = parseItem();
        } catch (VCardInvalidCommentLineException e) {
            Log.e(LOG_TAG, "Invalid line which looks like some comment was found. Ignored.");
        }

        while (!ended) {
            try {
                ended = parseItem();
            } catch (VCardInvalidCommentLineException e) {
                Log.e(LOG_TAG, "Invalid line which looks like some comment was found. Ignored.");
            }
        }
    }

    /*
     * item = [groups "."] name [params] ":" value CRLF / [groups "."] "ADR"
     * [params] ":" addressparts CRLF / [groups "."] "ORG" [params] ":" orgparts
     * CRLF / [groups "."] "N" [params] ":" nameparts CRLF / [groups "."]
     * "AGENT" [params] ":" vcard CRLF
     */
    protected boolean parseItem() throws IOException, VCardException {
        // Reset for an item.
        mCurrentEncoding = DEFAULT_ENCODING;

        final String line = getNonEmptyLine();
        final VCardProperty propertyData = constructPropertyData(line);

        final String propertyNameUpper = propertyData.getName().toUpperCase();
        final String propertyRawValue = propertyData.getRawValue();

        if (propertyNameUpper.equals(VCardConstants.PROPERTY_BEGIN)) {
            if (propertyRawValue.equalsIgnoreCase("VCARD")) {
                handleNest();
            } else {
                throw new VCardException("Unknown BEGIN type: " + propertyRawValue);
            }
        } else if (propertyNameUpper.equals(VCardConstants.PROPERTY_END)) {
            if (propertyRawValue.equalsIgnoreCase("VCARD")) {
                return true;  // Ended.
            } else {
                throw new VCardException("Unknown END type: " + propertyRawValue);
            }
        } else {
            parseItemInter(propertyData, propertyNameUpper);
        }
        return false;
    }

    private void parseItemInter(VCardProperty property, String propertyNameUpper)
            throws IOException, VCardException {
        String propertyRawValue = property.getRawValue();
        if (propertyNameUpper.equals(VCardConstants.PROPERTY_AGENT)) {
            handleAgent(property);
        } else if (isValidPropertyName(propertyNameUpper)) {
            if (propertyNameUpper.equals(VCardConstants.PROPERTY_VERSION) &&
                    !propertyRawValue.equals(getVersionString())) {
                throw new VCardVersionException(
                        "Incompatible version: " + propertyRawValue + " != " + getVersionString());
            }
            handlePropertyValue(property, propertyNameUpper);
        } else {
            throw new VCardException("Unknown property name: \"" + propertyNameUpper + "\"");
        }
    }

    private void handleNest() throws IOException, VCardException {
        for (VCardInterpreter interpreter : mInterpreterList) {
            interpreter.onEntryStarted();
        }
        parseItems();
        for (VCardInterpreter interpreter : mInterpreterList) {
            interpreter.onEntryEnded();
        }
    }

    // For performance reason, the states for group and property name are merged into one.
    static private final int STATE_GROUP_OR_PROPERTY_NAME = 0;
    static private final int STATE_PARAMS = 1;
    // vCard 3.0 specification allows double-quoted parameters, while vCard 2.1 does not.
    static private final int STATE_PARAMS_IN_DQUOTE = 2;

    protected VCardProperty constructPropertyData(String line) throws VCardException {
        final VCardProperty propertyData = new VCardProperty();

        final int length = line.length();
        if (length > 0 && line.charAt(0) == '#') {
            throw new VCardInvalidCommentLineException();
        }

        int state = STATE_GROUP_OR_PROPERTY_NAME;
        int nameIndex = 0;

        // This loop is developed so that we don't have to take care of bottle neck here.
        // Refactor carefully when you need to do so.
        for (int i = 0; i < length; i++) {
            final char ch = line.charAt(i);
            switch (state) {
                case STATE_GROUP_OR_PROPERTY_NAME: {
                    if (ch == ':') {  // End of a property name.
                        final String propertyName = line.substring(nameIndex, i);
                        propertyData.setName(propertyName);
                        propertyData.setRawValue( i < length - 1 ? line.substring(i + 1) : "");
                        return propertyData;
                    } else if (ch == '.') {  // Each group is followed by the dot.
                        final String groupName = line.substring(nameIndex, i);
                        if (groupName.length() == 0) {
                            Log.w(LOG_TAG, "Empty group found. Ignoring.");
                        } else {
                            propertyData.addGroup(groupName);
                        }
                        nameIndex = i + 1;  // Next should be another group or a property name.
                    } else if (ch == ';') {  // End of property name and beginneng of parameters.
                        final String propertyName = line.substring(nameIndex, i);
                        propertyData.setName(propertyName);
                        nameIndex = i + 1;
                        state = STATE_PARAMS;  // Start parameter parsing.
                    }
                    // TODO: comma support (in vCard 3.0 and 4.0).
                    break;
                }
                case STATE_PARAMS: {
                    if (ch == '"') {
                        if (VCardConstants.VERSION_V21.equalsIgnoreCase(getVersionString())) {
                            Log.w(LOG_TAG, "Double-quoted params found in vCard 2.1. " +
                                    "Silently allow it");
                        }
                        state = STATE_PARAMS_IN_DQUOTE;
                    } else if (ch == ';') {  // Starts another param.
                        handleParams(propertyData, line.substring(nameIndex, i));
                        nameIndex = i + 1;
                    } else if (ch == ':') {  // End of param and beginenning of values.
                        handleParams(propertyData, line.substring(nameIndex, i));
                        propertyData.setRawValue(i < length - 1 ? line.substring(i + 1) : "");
                        return propertyData;
                    }
                    break;
                }
                case STATE_PARAMS_IN_DQUOTE: {
                    if (ch == '"') {
                        if (VCardConstants.VERSION_V21.equalsIgnoreCase(getVersionString())) {
                            Log.w(LOG_TAG, "Double-quoted params found in vCard 2.1. " +
                                    "Silently allow it");
                        }
                        state = STATE_PARAMS;
                    }
                    break;
                }
            }
        }

        throw new VCardInvalidLineException("Invalid line: \"" + line + "\"");
    }

    /*
     * params = ";" [ws] paramlist paramlist = paramlist [ws] ";" [ws] param /
     * param param = "TYPE" [ws] "=" [ws] ptypeval / "VALUE" [ws] "=" [ws]
     * pvalueval / "ENCODING" [ws] "=" [ws] pencodingval / "CHARSET" [ws] "="
     * [ws] charsetval / "LANGUAGE" [ws] "=" [ws] langval / "X-" word [ws] "="
     * [ws] word / knowntype
     */
    protected void handleParams(VCardProperty propertyData, String params)
            throws VCardException {
        final String[] strArray = params.split("=", 2);
        if (strArray.length == 2) {
            final String paramName = strArray[0].trim().toUpperCase();
            String paramValue = strArray[1].trim();
            if (paramName.equals("TYPE")) {
                handleType(propertyData, paramValue);
            } else if (paramName.equals("VALUE")) {
                handleValue(propertyData, paramValue);
            } else if (paramName.equals("ENCODING")) {
                handleEncoding(propertyData, paramValue);
            } else if (paramName.equals("CHARSET")) {
                handleCharset(propertyData, paramValue);
            } else if (paramName.equals("LANGUAGE")) {
                handleLanguage(propertyData, paramValue);
            } else if (paramName.startsWith("X-")) {
                handleAnyParam(propertyData, paramName, paramValue);
            } else {
                throw new VCardException("Unknown type \"" + paramName + "\"");
            }
        } else {
            handleParamWithoutName(propertyData, strArray[0]);
        }
    }

    /**
     * vCard 3.0 parser implementation may throw VCardException.
     */
    protected void handleParamWithoutName(VCardProperty propertyData, final String paramValue) {
        handleType(propertyData, paramValue);
    }

    /*
     * ptypeval = knowntype / "X-" word
     */
    protected void handleType(VCardProperty propertyData, final String ptypeval) {
        if (!(getKnownTypeSet().contains(ptypeval.toUpperCase())
                || ptypeval.startsWith("X-"))
                && !mUnknownTypeSet.contains(ptypeval)) {
            mUnknownTypeSet.add(ptypeval);
            Log.w(LOG_TAG, String.format("TYPE unsupported by %s: ", getVersion(), ptypeval));
        }
        propertyData.addParameter(VCardConstants.PARAM_TYPE, ptypeval);
    }

    /*
     * pvalueval = "INLINE" / "URL" / "CONTENT-ID" / "CID" / "X-" word
     */
    protected void handleValue(VCardProperty propertyData, final String pvalueval) {
        if (!(getKnownValueSet().contains(pvalueval.toUpperCase())
                || pvalueval.startsWith("X-")
                || mUnknownValueSet.contains(pvalueval))) {
            mUnknownValueSet.add(pvalueval);
            Log.w(LOG_TAG, String.format(
                    "The value unsupported by TYPE of %s: ", getVersion(), pvalueval));
        }
        propertyData.addParameter(VCardConstants.PARAM_VALUE, pvalueval);
    }

    /*
     * pencodingval = "7BIT" / "8BIT" / "QUOTED-PRINTABLE" / "BASE64" / "X-" word
     */
    protected void handleEncoding(VCardProperty propertyData, String pencodingval)
            throws VCardException {
        if (getAvailableEncodingSet().contains(pencodingval) ||
                pencodingval.startsWith("X-")) {
            propertyData.addParameter(VCardConstants.PARAM_ENCODING, pencodingval);
            // Update encoding right away, as this is needed to understanding other params.
            mCurrentEncoding = pencodingval.toUpperCase();
        } else {
            throw new VCardException("Unknown encoding \"" + pencodingval + "\"");
        }
    }

    /**
     * <p>
     * vCard 2.1 specification only allows us-ascii and iso-8859-xxx (See RFC 1521),
     * but recent vCard files often contain other charset like UTF-8, SHIFT_JIS, etc.
     * We allow any charset.
     * </p>
     */
    protected void handleCharset(VCardProperty propertyData, String charsetval) {
        mCurrentCharset = charsetval;
        propertyData.addParameter(VCardConstants.PARAM_CHARSET, charsetval);
    }

    /**
     * See also Section 7.1 of RFC 1521
     */
    protected void handleLanguage(VCardProperty propertyData, String langval)
            throws VCardException {
        String[] strArray = langval.split("-");
        if (strArray.length != 2) {
            throw new VCardException("Invalid Language: \"" + langval + "\"");
        }
        String tmp = strArray[0];
        int length = tmp.length();
        for (int i = 0; i < length; i++) {
            if (!isAsciiLetter(tmp.charAt(i))) {
                throw new VCardException("Invalid Language: \"" + langval + "\"");
            }
        }
        tmp = strArray[1];
        length = tmp.length();
        for (int i = 0; i < length; i++) {
            if (!isAsciiLetter(tmp.charAt(i))) {
                throw new VCardException("Invalid Language: \"" + langval + "\"");
            }
        }
        propertyData.addParameter(VCardConstants.PARAM_LANGUAGE, langval);
    }

    private boolean isAsciiLetter(char ch) {
        if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
            return true;
        }
        return false;
    }

    /**
     * Mainly for "X-" type. This accepts any kind of type without check.
     */
    protected void handleAnyParam(
            VCardProperty propertyData, String paramName, String paramValue) {
        propertyData.addParameter(paramName, paramValue);
    }

    protected void handlePropertyValue(VCardProperty property, String propertyName)
            throws IOException, VCardException {
        final String propertyNameUpper = property.getName().toUpperCase();
        String propertyRawValue = property.getRawValue();
        final String sourceCharset = VCardConfig.DEFAULT_INTERMEDIATE_CHARSET;
        final Collection<String> charsetCollection =
                property.getParameters(VCardConstants.PARAM_CHARSET);
        String targetCharset =
                ((charsetCollection != null) ? charsetCollection.iterator().next() : null);
        if (TextUtils.isEmpty(targetCharset)) {
            targetCharset = VCardConfig.DEFAULT_IMPORT_CHARSET;
        }

        // TODO: have "separableProperty" which reflects vCard spec..
        if (propertyNameUpper.equals(VCardConstants.PROPERTY_ADR)
                || propertyNameUpper.equals(VCardConstants.PROPERTY_ORG)
                || propertyNameUpper.equals(VCardConstants.PROPERTY_N)) {
            handleAdrOrgN(property, propertyRawValue, sourceCharset, targetCharset);
            return;
        }

        if (mCurrentEncoding.equals(VCardConstants.PARAM_ENCODING_QP) ||
                // If encoding attribute is missing, then attempt to detect QP encoding.
                // This is to handle a bug where the android exporter was creating FN properties
                // with missing encoding.  b/7292017
                (propertyNameUpper.equals(VCardConstants.PROPERTY_FN) &&
                        property.getParameters(VCardConstants.PARAM_ENCODING) == null &&
                        VCardUtils.appearsLikeAndroidVCardQuotedPrintable(propertyRawValue))
                ) {
            final String quotedPrintablePart = getQuotedPrintablePart(propertyRawValue);
            final String propertyEncodedValue =
                    VCardUtils.parseQuotedPrintable(quotedPrintablePart,
                            false, sourceCharset, targetCharset);
            property.setRawValue(quotedPrintablePart);
            property.setValues(propertyEncodedValue);
            for (VCardInterpreter interpreter : mInterpreterList) {
                interpreter.onPropertyCreated(property);
            }
        } else if (mCurrentEncoding.equals(VCardConstants.PARAM_ENCODING_BASE64)
                || mCurrentEncoding.equals(VCardConstants.PARAM_ENCODING_B)) {
            // It is very rare, but some BASE64 data may be so big that
            // OutOfMemoryError occurs. To ignore such cases, use try-catch.
            try {
                final String base64Property = getBase64(propertyRawValue);
                try {
                    property.setByteValue(Base64.decode(base64Property, Base64.DEFAULT));
                } catch (IllegalArgumentException e) {
                    throw new VCardException("Decode error on base64 photo: " + propertyRawValue);
                }
                for (VCardInterpreter interpreter : mInterpreterList) {
                    interpreter.onPropertyCreated(property);
                }
            } catch (OutOfMemoryError error) {
                Log.e(LOG_TAG, "OutOfMemoryError happened during parsing BASE64 data!");
                for (VCardInterpreter interpreter : mInterpreterList) {
                    interpreter.onPropertyCreated(property);
                }
            }
        } else {
            if (!(mCurrentEncoding.equals("7BIT") || mCurrentEncoding.equals("8BIT") ||
                    mCurrentEncoding.startsWith("X-"))) {
                Log.w(LOG_TAG,
                        String.format("The encoding \"%s\" is unsupported by vCard %s",
                                mCurrentEncoding, getVersionString()));
            }

            // Some device uses line folding defined in RFC 2425, which is not allowed
            // in vCard 2.1 (while needed in vCard 3.0).
            //
            // e.g.
            // BEGIN:VCARD
            // VERSION:2.1
            // N:;Omega;;;
            // EMAIL;INTERNET:"Omega"
            //   <omega@example.com>
            // FN:Omega
            // END:VCARD
            //
            // The vCard above assumes that email address should become:
            // "Omega" <omega@example.com>
            //
            // But vCard 2.1 requires Quote-Printable when a line contains line break(s).
            //
            // For more information about line folding,
            // see "5.8.1. Line delimiting and folding" in RFC 2425.
            //
            // We take care of this case more formally in vCard 3.0, so we only need to
            // do this in vCard 2.1.
            if (getVersion() == VCardConfig.VERSION_21) {
                StringBuilder builder = null;
                while (true) {
                    final String nextLine = peekLine();
                    // We don't need to care too much about this exceptional case,
                    // but we should not wrongly eat up "END:VCARD", since it critically
                    // breaks this parser's state machine.
                    // Thus we roughly look over the next line and confirm it is at least not
                    // "END:VCARD". This extra fee is worth paying. This is exceptional
                    // anyway.
                    if (!TextUtils.isEmpty(nextLine) &&
                            nextLine.charAt(0) == ' ' &&
                            !"END:VCARD".contains(nextLine.toUpperCase())) {
                        getLine();  // Drop the next line.

                        if (builder == null) {
                            builder = new StringBuilder();
                            builder.append(propertyRawValue);
                        }
                        builder.append(nextLine.substring(1));
                    } else {
                        break;
                    }
                }
                if (builder != null) {
                    propertyRawValue = builder.toString();
                }
            }

            ArrayList<String> propertyValueList = new ArrayList<String>();
            String value = VCardUtils.convertStringCharset(
                    maybeUnescapeText(propertyRawValue), sourceCharset, targetCharset);
            propertyValueList.add(value);
            property.setValues(propertyValueList);
            for (VCardInterpreter interpreter : mInterpreterList) {
                interpreter.onPropertyCreated(property);
            }
        }
    }

    private void handleAdrOrgN(VCardProperty property, String propertyRawValue,
            String sourceCharset, String targetCharset) throws VCardException, IOException {
        List<String> encodedValueList = new ArrayList<String>();

        // vCard 2.1 does not allow QUOTED-PRINTABLE here, but some softwares/devices emit
        // such data.
        if (mCurrentEncoding.equals(VCardConstants.PARAM_ENCODING_QP)) {
            // First we retrieve Quoted-Printable String from vCard entry, which may include
            // multiple lines.
            final String quotedPrintablePart = getQuotedPrintablePart(propertyRawValue);

            // "Raw value" from the view of users should contain all part of QP string.
            // TODO: add test for this handling
            property.setRawValue(quotedPrintablePart);

            // We split Quoted-Printable String using semi-colon before decoding it, as
            // the Quoted-Printable may have semi-colon, which confuses splitter.
            final List<String> quotedPrintableValueList =
                    VCardUtils.constructListFromValue(quotedPrintablePart, getVersion());
            for (String quotedPrintableValue : quotedPrintableValueList) {
                String encoded = VCardUtils.parseQuotedPrintable(quotedPrintableValue,
                        false, sourceCharset, targetCharset);
                encodedValueList.add(encoded);
            }
        } else {
            final String propertyValue = getPotentialMultiline(propertyRawValue);
            final List<String> rawValueList =
                    VCardUtils.constructListFromValue(propertyValue, getVersion());
            for (String rawValue : rawValueList) {
                encodedValueList.add(VCardUtils.convertStringCharset(
                        rawValue, sourceCharset, targetCharset));
            }
        }

        property.setValues(encodedValueList);
        for (VCardInterpreter interpreter : mInterpreterList) {
            interpreter.onPropertyCreated(property);
        }
    }

    /**
     * <p>
     * Parses and returns Quoted-Printable.
     * </p>
     *
     * @param firstString The string following a parameter name and attributes.
     *            Example: "string" in
     *            "ADR:ENCODING=QUOTED-PRINTABLE:string\n\r".
     * @return whole Quoted-Printable string, including a given argument and
     *         following lines. Excludes the last empty line following to Quoted
     *         Printable lines.
     * @throws IOException
     * @throws VCardException
     */
    private String getQuotedPrintablePart(String firstString)
            throws IOException, VCardException {
        // Specifically, there may be some padding between = and CRLF.
        // See the following:
        //
        // qp-line := *(qp-segment transport-padding CRLF)
        // qp-part transport-padding
        // qp-segment := qp-section *(SPACE / TAB) "="
        // ; Maximum length of 76 characters
        //
        // e.g. (from RFC 2045)
        // Now's the time =
        // for all folk to come=
        // to the aid of their country.
        if (firstString.trim().endsWith("=")) {
            // remove "transport-padding"
            int pos = firstString.length() - 1;
            while (firstString.charAt(pos) != '=') {
            }
            StringBuilder builder = new StringBuilder();
            builder.append(firstString.substring(0, pos + 1));
            builder.append("\r\n");
            String line;
            while (true) {
                line = getLine();
                if (line == null) {
                    throw new VCardException("File ended during parsing a Quoted-Printable String");
                }
                if (line.trim().endsWith("=")) {
                    // remove "transport-padding"
                    pos = line.length() - 1;
                    while (line.charAt(pos) != '=') {
                    }
                    builder.append(line.substring(0, pos + 1));
                    builder.append("\r\n");
                } else {
                    builder.append(line);
                    break;
                }
            }
            return builder.toString();
        } else {
            return firstString;
        }
    }

    /**
     * Given the first line of a property, checks consecutive lines after it and builds a new
     * multi-line value if it exists.
     *
     * @param firstString The first line of the property.
     * @return A new property, potentially built from multiple lines.
     * @throws IOException
     */
    private String getPotentialMultiline(String firstString) throws IOException {
        final StringBuilder builder = new StringBuilder();
        builder.append(firstString);

        while (true) {
            final String line = peekLine();
            if (line == null || line.length() == 0) {
                break;
            }

            final String propertyName = getPropertyNameUpperCase(line);
            if (propertyName != null) {
                break;
            }

            // vCard 2.1 does not allow multi-line of adr but microsoft vcards may have it.
            // We will consider the next line to be a part of a multi-line value if it does not
            // contain a property name (i.e. a colon or semi-colon).
            // Consume the line.
            getLine();
            builder.append(" ").append(line);
        }

        return builder.toString();
    }

    protected String getBase64(String firstString) throws IOException, VCardException {
        final StringBuilder builder = new StringBuilder();
        builder.append(firstString);

        while (true) {
            final String line = peekLine();
            if (line == null) {
                throw new VCardException("File ended during parsing BASE64 binary");
            }

            // vCard 2.1 requires two spaces at the end of BASE64 strings, but some vCard doesn't
            // have them. We try to detect those cases using colon and semi-colon, given BASE64
            // does not contain it.
            // E.g.
            //      TEL;TYPE=WORK:+5555555
            // or
            //      END:VCARD
            String propertyName = getPropertyNameUpperCase(line);
            if (getKnownPropertyNameSet().contains(propertyName) ||
                    VCardConstants.PROPERTY_X_ANDROID_CUSTOM.equals(propertyName)) {
                Log.w(LOG_TAG, "Found a next property during parsing a BASE64 string, " +
                        "which must not contain semi-colon or colon. Treat the line as next "
                        + "property.");
                Log.w(LOG_TAG, "Problematic line: " + line.trim());
                break;
            }

            // Consume the line.
            getLine();

            if (line.length() == 0) {
                break;
            }
            builder.append(line);
        }

        return builder.toString();
    }

    /**
     * Extracts the property name portion of a given vCard line.
     * <p>
     * Properties must contain a colon.
     * <p>
     * E.g.
     *      TEL;TYPE=WORK:+5555555  // returns "TEL"
     *      END:VCARD // returns "END"
     *      TEL; // returns null
     *
     * @param line The vCard line.
     * @return The property name portion. {@literal null} if no property name found.
     */
    private String getPropertyNameUpperCase(String line) {
        final int colonIndex = line.indexOf(":");
        if (colonIndex > -1) {
            final int semiColonIndex = line.indexOf(";");

            // Find the minimum index that is greater than -1.
            final int minIndex;
            if (colonIndex == -1) {
                minIndex = semiColonIndex;
            } else if (semiColonIndex == -1) {
                minIndex = colonIndex;
            } else {
                minIndex = Math.min(colonIndex, semiColonIndex);
            }
            return line.substring(0, minIndex).toUpperCase();
        }
        return null;
    }

    /*
     * vCard 2.1 specifies AGENT allows one vcard entry. Currently we emit an
     * error toward the AGENT property.
     * // TODO: Support AGENT property.
     * item =
     * ... / [groups "."] "AGENT" [params] ":" vcard CRLF vcard = "BEGIN" [ws]
     * ":" [ws] "VCARD" [ws] 1*CRLF items *CRLF "END" [ws] ":" [ws] "VCARD"
     */
    protected void handleAgent(final VCardProperty property) throws VCardException {
        if (!property.getRawValue().toUpperCase().contains("BEGIN:VCARD")) {
            // Apparently invalid line seen in Windows Mobile 6.5. Ignore them.
            for (VCardInterpreter interpreter : mInterpreterList) {
                interpreter.onPropertyCreated(property);
            }
            return;
        } else {
            throw new VCardAgentNotSupportedException("AGENT Property is not supported now.");
        }
    }

    /**
     * For vCard 3.0.
     */
    protected String maybeUnescapeText(final String text) {
        return text;
    }

    /**
     * Returns unescaped String if the character should be unescaped. Return
     * null otherwise. e.g. In vCard 2.1, "\;" should be unescaped into ";"
     * while "\x" should not be.
     */
    protected String maybeUnescapeCharacter(final char ch) {
        return unescapeCharacter(ch);
    }

    /* package */ static String unescapeCharacter(final char ch) {
        // Original vCard 2.1 specification does not allow transformation
        // "\:" -> ":", "\," -> ",", and "\\" -> "\", but previous
        // implementation of
        // this class allowed them, so keep it as is.
        if (ch == '\\' || ch == ';' || ch == ':' || ch == ',') {
            return String.valueOf(ch);
        } else {
            return null;
        }
    }

    /**
     * @return {@link VCardConfig#VERSION_21}
     */
    protected int getVersion() {
        return VCardConfig.VERSION_21;
    }

    /**
     * @return {@link VCardConfig#VERSION_30}
     */
    protected String getVersionString() {
        return VCardConstants.VERSION_V21;
    }

    protected Set<String> getKnownPropertyNameSet() {
        return VCardParser_V21.sKnownPropertyNameSet;
    }

    protected Set<String> getKnownTypeSet() {
        return VCardParser_V21.sKnownTypeSet;
    }

    protected Set<String> getKnownValueSet() {
        return VCardParser_V21.sKnownValueSet;
    }

    protected Set<String> getAvailableEncodingSet() {
        return VCardParser_V21.sAvailableEncoding;
    }

    protected String getDefaultEncoding() {
        return DEFAULT_ENCODING;
    }

    protected String getDefaultCharset() {
        return DEFAULT_CHARSET;
    }

    protected String getCurrentCharset() {
        return mCurrentCharset;
    }

    public void addInterpreter(VCardInterpreter interpreter) {
        mInterpreterList.add(interpreter);
    }

    public void parse(InputStream is) throws IOException, VCardException {
        if (is == null) {
            throw new NullPointerException("InputStream must not be null.");
        }

        final InputStreamReader tmpReader = new InputStreamReader(is, mIntermediateCharset);
        mReader = new CustomBufferedReader(tmpReader);

        final long start = System.currentTimeMillis();
        for (VCardInterpreter interpreter : mInterpreterList) {
            interpreter.onVCardStarted();
        }

        // vcard_file = [wsls] vcard [wsls]
        while (true) {
            synchronized (this) {
                if (mCanceled) {
                    Log.i(LOG_TAG, "Cancel request has come. exitting parse operation.");
                    break;
                }
            }
            if (!parseOneVCard()) {
                break;
            }
        }

        for (VCardInterpreter interpreter : mInterpreterList) {
            interpreter.onVCardEnded();
        }
    }

    public void parseOne(InputStream is) throws IOException, VCardException {
        if (is == null) {
            throw new NullPointerException("InputStream must not be null.");
        }

        final InputStreamReader tmpReader = new InputStreamReader(is, mIntermediateCharset);
        mReader = new CustomBufferedReader(tmpReader);

        final long start = System.currentTimeMillis();
        for (VCardInterpreter interpreter : mInterpreterList) {
            interpreter.onVCardStarted();
        }
        parseOneVCard();
        for (VCardInterpreter interpreter : mInterpreterList) {
            interpreter.onVCardEnded();
        }
    }

    public final synchronized void cancel() {
        Log.i(LOG_TAG, "ParserImpl received cancel operation.");
        mCanceled = true;
    }
}
