/*
 * 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.toUpperCase());
            } 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;
            }
            // Trim off any extraneous whitespace to handle 2.1 implementations
            // that use 3.0 style line continuations. This is safe because space
            // isn't a Base64 encoding value.
            builder.append(line.trim());
        }

        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;
    }
}
