/*
 * Copyright (C) 2017 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 android.view.textclassifier;

import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
import android.annotation.WorkerThread;
import android.os.LocaleList;
import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.URLSpan;
import android.text.util.Linkify;
import android.text.util.Linkify.LinkifyMask;
import android.util.ArrayMap;

import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Interface for providing text classification related features.
 * <p>
 * The TextClassifier may be used to understand the meaning of text, as well as generating predicted
 * next actions based on the text.
 *
 * <p><strong>NOTE: </strong>Unless otherwise stated, methods of this interface are blocking
 * operations. Call on a worker thread.
 */
public interface TextClassifier {

    /** @hide */
    String DEFAULT_LOG_TAG = "androidtc";


    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(value = {LOCAL, SYSTEM})
    @interface TextClassifierType {}  // TODO: Expose as system APIs.
    /** Specifies a TextClassifier that runs locally in the app's process. @hide */
    int LOCAL = 0;
    /** Specifies a TextClassifier that runs in the system process and serves all apps. @hide */
    int SYSTEM = 1;

    /** The TextClassifier failed to run. */
    String TYPE_UNKNOWN = "";
    /** The classifier ran, but didn't recognize a known entity. */
    String TYPE_OTHER = "other";
    /** E-mail address (e.g. "noreply@android.com"). */
    String TYPE_EMAIL = "email";
    /** Phone number (e.g. "555-123 456"). */
    String TYPE_PHONE = "phone";
    /** Physical address. */
    String TYPE_ADDRESS = "address";
    /** Web URL. */
    String TYPE_URL = "url";
    /** Time reference that is no more specific than a date. May be absolute such as "01/01/2000" or
     * relative like "tomorrow". **/
    String TYPE_DATE = "date";
    /** Time reference that includes a specific time. May be absolute such as "01/01/2000 5:30pm" or
     * relative like "tomorrow at 5:30pm". **/
    String TYPE_DATE_TIME = "datetime";
    /** Flight number in IATA format. */
    String TYPE_FLIGHT_NUMBER = "flight";
    /**
     * Word that users may be interested to look up for meaning.
     * @hide
     */
    String TYPE_DICTIONARY = "dictionary";

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @StringDef(prefix = { "TYPE_" }, value = {
            TYPE_UNKNOWN,
            TYPE_OTHER,
            TYPE_EMAIL,
            TYPE_PHONE,
            TYPE_ADDRESS,
            TYPE_URL,
            TYPE_DATE,
            TYPE_DATE_TIME,
            TYPE_FLIGHT_NUMBER,
            TYPE_DICTIONARY
    })
    @interface EntityType {}

    /** Designates that the text in question is editable. **/
    String HINT_TEXT_IS_EDITABLE = "android.text_is_editable";
    /** Designates that the text in question is not editable. **/
    String HINT_TEXT_IS_NOT_EDITABLE = "android.text_is_not_editable";

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @StringDef(prefix = { "HINT_" }, value = {HINT_TEXT_IS_EDITABLE, HINT_TEXT_IS_NOT_EDITABLE})
    @interface Hints {}

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @StringDef({WIDGET_TYPE_TEXTVIEW, WIDGET_TYPE_EDITTEXT, WIDGET_TYPE_UNSELECTABLE_TEXTVIEW,
            WIDGET_TYPE_WEBVIEW, WIDGET_TYPE_EDIT_WEBVIEW, WIDGET_TYPE_CUSTOM_TEXTVIEW,
            WIDGET_TYPE_CUSTOM_EDITTEXT, WIDGET_TYPE_CUSTOM_UNSELECTABLE_TEXTVIEW,
            WIDGET_TYPE_NOTIFICATION, WIDGET_TYPE_UNKNOWN})
    @interface WidgetType {}

    /** The widget involved in the text classification context is a standard
     * {@link android.widget.TextView}. */
    String WIDGET_TYPE_TEXTVIEW = "textview";
    /** The widget involved in the text classification context is a standard
     * {@link android.widget.EditText}. */
    String WIDGET_TYPE_EDITTEXT = "edittext";
    /** The widget involved in the text classification context is a standard non-selectable
     * {@link android.widget.TextView}. */
    String WIDGET_TYPE_UNSELECTABLE_TEXTVIEW = "nosel-textview";
    /** The widget involved in the text classification context is a standard
     * {@link android.webkit.WebView}. */
    String WIDGET_TYPE_WEBVIEW = "webview";
    /** The widget involved in the text classification context is a standard editable
     * {@link android.webkit.WebView}. */
    String WIDGET_TYPE_EDIT_WEBVIEW = "edit-webview";
    /** The widget involved in the text classification context is a custom text widget. */
    String WIDGET_TYPE_CUSTOM_TEXTVIEW = "customview";
    /** The widget involved in the text classification context is a custom editable text widget. */
    String WIDGET_TYPE_CUSTOM_EDITTEXT = "customedit";
    /** The widget involved in the text classification context is a custom non-selectable text
     * widget. */
    String WIDGET_TYPE_CUSTOM_UNSELECTABLE_TEXTVIEW = "nosel-customview";
    /** The widget involved in the text classification context is a notification */
    String WIDGET_TYPE_NOTIFICATION = "notification";
    /** The widget involved in the text classification context is of an unknown/unspecified type. */
    String WIDGET_TYPE_UNKNOWN = "unknown";

    /**
     * No-op TextClassifier.
     * This may be used to turn off TextClassifier features.
     */
    TextClassifier NO_OP = new TextClassifier() {
        @Override
        public String toString() {
            return "TextClassifier.NO_OP";
        }
    };

    /**
     * Extra that is included on activity intents coming from a TextClassifier when
     * it suggests actions to its caller.
     * <p>
     * All {@link TextClassifier} implementations should make sure this extra exists in their
     * generated intents.
     */
    String EXTRA_FROM_TEXT_CLASSIFIER = "android.view.textclassifier.extra.FROM_TEXT_CLASSIFIER";

    /**
     * Returns suggested text selection start and end indices, recognized entity types, and their
     * associated confidence scores. The entity types are ordered from highest to lowest scoring.
     *
     * <p><strong>NOTE: </strong>Call on a worker thread.
     *
     * <p><strong>NOTE: </strong>If a TextClassifier has been destroyed, calls to this method should
     * throw an {@link IllegalStateException}. See {@link #isDestroyed()}.
     *
     * @param request the text selection request
     */
    @WorkerThread
    @NonNull
    default TextSelection suggestSelection(@NonNull TextSelection.Request request) {
        Preconditions.checkNotNull(request);
        Utils.checkMainThread();
        return new TextSelection.Builder(request.getStartIndex(), request.getEndIndex()).build();
    }

    /**
     * Returns suggested text selection start and end indices, recognized entity types, and their
     * associated confidence scores. The entity types are ordered from highest to lowest scoring.
     *
     * <p><strong>NOTE: </strong>Call on a worker thread.
     *
     * <p><strong>NOTE: </strong>If a TextClassifier has been destroyed, calls to this method should
     * throw an {@link IllegalStateException}. See {@link #isDestroyed()}.
     *
     * <p><b>NOTE:</b> Do not implement. The default implementation of this method calls
     * {@link #suggestSelection(TextSelection.Request)}. If that method calls this method,
     * a stack overflow error will happen.
     *
     * @param text text providing context for the selected text (which is specified
     *      by the sub sequence starting at selectionStartIndex and ending at selectionEndIndex)
     * @param selectionStartIndex start index of the selected part of text
     * @param selectionEndIndex end index of the selected part of text
     * @param defaultLocales ordered list of locale preferences that may be used to
     *      disambiguate the provided text. If no locale preferences exist, set this to null
     *      or an empty locale list.
     *
     * @throws IllegalArgumentException if text is null; selectionStartIndex is negative;
     *      selectionEndIndex is greater than text.length() or not greater than selectionStartIndex
     *
     * @see #suggestSelection(TextSelection.Request)
     */
    @WorkerThread
    @NonNull
    default TextSelection suggestSelection(
            @NonNull CharSequence text,
            @IntRange(from = 0) int selectionStartIndex,
            @IntRange(from = 0) int selectionEndIndex,
            @Nullable LocaleList defaultLocales) {
        final TextSelection.Request request = new TextSelection.Request.Builder(
                text, selectionStartIndex, selectionEndIndex)
                .setDefaultLocales(defaultLocales)
                .build();
        return suggestSelection(request);
    }

    /**
     * Classifies the specified text and returns a {@link TextClassification} object that can be
     * used to generate a widget for handling the classified text.
     *
     * <p><strong>NOTE: </strong>Call on a worker thread.
     *
     * <p><strong>NOTE: </strong>If a TextClassifier has been destroyed, calls to this method should
     * throw an {@link IllegalStateException}. See {@link #isDestroyed()}.
     *
     * @param request the text classification request
     */
    @WorkerThread
    @NonNull
    default TextClassification classifyText(@NonNull TextClassification.Request request) {
        Preconditions.checkNotNull(request);
        Utils.checkMainThread();
        return TextClassification.EMPTY;
    }

    /**
     * Classifies the specified text and returns a {@link TextClassification} object that can be
     * used to generate a widget for handling the classified text.
     *
     * <p><strong>NOTE: </strong>Call on a worker thread.
     *
     * <p><b>NOTE:</b> Do not implement. The default implementation of this method calls
     * {@link #classifyText(TextClassification.Request)}. If that method calls this method,
     * a stack overflow error will happen.
     *
     * <p><strong>NOTE: </strong>If a TextClassifier has been destroyed, calls to this method should
     * throw an {@link IllegalStateException}. See {@link #isDestroyed()}.
     *
     * @param text text providing context for the text to classify (which is specified
     *      by the sub sequence starting at startIndex and ending at endIndex)
     * @param startIndex start index of the text to classify
     * @param endIndex end index of the text to classify
     * @param defaultLocales ordered list of locale preferences that may be used to
     *      disambiguate the provided text. If no locale preferences exist, set this to null
     *      or an empty locale list.
     *
     * @throws IllegalArgumentException if text is null; startIndex is negative;
     *      endIndex is greater than text.length() or not greater than startIndex
     *
     * @see #classifyText(TextClassification.Request)
     */
    @WorkerThread
    @NonNull
    default TextClassification classifyText(
            @NonNull CharSequence text,
            @IntRange(from = 0) int startIndex,
            @IntRange(from = 0) int endIndex,
            @Nullable LocaleList defaultLocales) {
        final TextClassification.Request request = new TextClassification.Request.Builder(
                text, startIndex, endIndex)
                .setDefaultLocales(defaultLocales)
                .build();
        return classifyText(request);
    }

    /**
     * Generates and returns a {@link TextLinks} that may be applied to the text to annotate it with
     * links information.
     *
     * <p><strong>NOTE: </strong>Call on a worker thread.
     *
     * <p><strong>NOTE: </strong>If a TextClassifier has been destroyed, calls to this method should
     * throw an {@link IllegalStateException}. See {@link #isDestroyed()}.
     *
     * @param request the text links request
     *
     * @see #getMaxGenerateLinksTextLength()
     */
    @WorkerThread
    @NonNull
    default TextLinks generateLinks(@NonNull TextLinks.Request request) {
        Preconditions.checkNotNull(request);
        Utils.checkMainThread();
        return new TextLinks.Builder(request.getText().toString()).build();
    }

    /**
     * Returns the maximal length of text that can be processed by generateLinks.
     *
     * <p><strong>NOTE: </strong>If a TextClassifier has been destroyed, calls to this method should
     * throw an {@link IllegalStateException}. See {@link #isDestroyed()}.
     *
     * @see #generateLinks(TextLinks.Request)
     */
    @WorkerThread
    default int getMaxGenerateLinksTextLength() {
        return Integer.MAX_VALUE;
    }

    /**
     * Detects the language of the text in the given request.
     *
     * <p><strong>NOTE: </strong>Call on a worker thread.
     *
     *
     * <p><strong>NOTE: </strong>If a TextClassifier has been destroyed, calls to this method should
     * throw an {@link IllegalStateException}. See {@link #isDestroyed()}.
     *
     * @param request the {@link TextLanguage} request.
     * @return the {@link TextLanguage} result.
     */
    @WorkerThread
    @NonNull
    default TextLanguage detectLanguage(@NonNull TextLanguage.Request request) {
        Preconditions.checkNotNull(request);
        Utils.checkMainThread();
        return TextLanguage.EMPTY;
    }

    /**
     * Suggests and returns a list of actions according to the given conversation.
     */
    @WorkerThread
    @NonNull
    default ConversationActions suggestConversationActions(
            @NonNull ConversationActions.Request request) {
        Preconditions.checkNotNull(request);
        Utils.checkMainThread();
        return new ConversationActions(Collections.emptyList(), null);
    }

    /**
     * <strong>NOTE: </strong>Use {@link #onTextClassifierEvent(TextClassifierEvent)} instead.
     * <p>
     * Reports a selection event.
     *
     * <p><strong>NOTE: </strong>If a TextClassifier has been destroyed, calls to this method should
     * throw an {@link IllegalStateException}. See {@link #isDestroyed()}.
     */
    default void onSelectionEvent(@NonNull SelectionEvent event) {
        // TODO: Consider rerouting to onTextClassifierEvent()
    }

    /**
     * Reports a text classifier event.
     * <p>
     * <strong>NOTE: </strong>Call on a worker thread.
     *
     * @throws IllegalStateException if this TextClassifier has been destroyed.
     * @see #isDestroyed()
     */
    default void onTextClassifierEvent(@NonNull TextClassifierEvent event) {}

    /**
     * Destroys this TextClassifier.
     *
     * <p><strong>NOTE: </strong>If a TextClassifier has been destroyed, calls to its methods should
     * throw an {@link IllegalStateException}. See {@link #isDestroyed()}.
     *
     * <p>Subsequent calls to this method are no-ops.
     */
    default void destroy() {}

    /**
     * Returns whether or not this TextClassifier has been destroyed.
     *
     * <p><strong>NOTE: </strong>If a TextClassifier has been destroyed, caller should not interact
     * with the classifier and an attempt to do so would throw an {@link IllegalStateException}.
     * However, this method should never throw an {@link IllegalStateException}.
     *
     * @see #destroy()
     */
    default boolean isDestroyed() {
        return false;
    }

    /** @hide **/
    default void dump(@NonNull IndentingPrintWriter printWriter) {}

    /**
     * Configuration object for specifying what entity types to identify.
     *
     * Configs are initially based on a predefined preset, and can be modified from there.
     */
    final class EntityConfig implements Parcelable {
        private final List<String> mIncludedTypes;
        private final List<String> mExcludedTypes;
        private final List<String> mHints;
        private final boolean mIncludeTypesFromTextClassifier;

        private EntityConfig(
                List<String> includedEntityTypes,
                List<String> excludedEntityTypes,
                List<String> hints,
                boolean includeTypesFromTextClassifier) {
            mIncludedTypes = Preconditions.checkNotNull(includedEntityTypes);
            mExcludedTypes = Preconditions.checkNotNull(excludedEntityTypes);
            mHints = Preconditions.checkNotNull(hints);
            mIncludeTypesFromTextClassifier = includeTypesFromTextClassifier;
        }

        private EntityConfig(Parcel in) {
            mIncludedTypes = new ArrayList<>();
            in.readStringList(mIncludedTypes);
            mExcludedTypes = new ArrayList<>();
            in.readStringList(mExcludedTypes);
            List<String> tmpHints = new ArrayList<>();
            in.readStringList(tmpHints);
            mHints = Collections.unmodifiableList(tmpHints);
            mIncludeTypesFromTextClassifier = in.readByte() != 0;
        }

        @Override
        public void writeToParcel(Parcel parcel, int flags) {
            parcel.writeStringList(mIncludedTypes);
            parcel.writeStringList(mExcludedTypes);
            parcel.writeStringList(mHints);
            parcel.writeByte((byte) (mIncludeTypesFromTextClassifier ? 1 : 0));
        }

        /**
         * Creates an EntityConfig.
         *
         * @param hints Hints for the TextClassifier to determine what types of entities to find.
         *
         * @deprecated Use {@link Builder} instead.
         */
        @Deprecated
        public static EntityConfig createWithHints(@Nullable Collection<String> hints) {
            return new EntityConfig.Builder()
                    .includeTypesFromTextClassifier(true)
                    .setHints(hints)
                    .build();
        }

        /**
         * Creates an EntityConfig.
         *
         * @param hints Hints for the TextClassifier to determine what types of entities to find
         * @param includedEntityTypes Entity types, e.g. {@link #TYPE_EMAIL}, to explicitly include
         * @param excludedEntityTypes Entity types, e.g. {@link #TYPE_PHONE}, to explicitly exclude
         *
         *
         * Note that if an entity has been excluded, the exclusion will take precedence.
         *
         * @deprecated Use {@link Builder} instead.
         */
        @Deprecated
        public static EntityConfig create(@Nullable Collection<String> hints,
                @Nullable Collection<String> includedEntityTypes,
                @Nullable Collection<String> excludedEntityTypes) {
            return new EntityConfig.Builder()
                    .setIncludedTypes(includedEntityTypes)
                    .setExcludedTypes(excludedEntityTypes)
                    .setHints(hints)
                    .includeTypesFromTextClassifier(true)
                    .build();
        }

        /**
         * Creates an EntityConfig with an explicit entity list.
         *
         * @param entityTypes Complete set of entities, e.g. {@link #TYPE_URL} to find.
         *
         * @deprecated Use {@link Builder} instead.
         */
        @Deprecated
        public static EntityConfig createWithExplicitEntityList(
                @Nullable Collection<String> entityTypes) {
            return new EntityConfig.Builder()
                    .setIncludedTypes(entityTypes)
                    .includeTypesFromTextClassifier(false)
                    .build();
        }

        /**
         * Returns a final list of entity types to find.
         *
         * @param entityTypes Entity types we think should be found before factoring in
         *                    includes/excludes
         *
         * This method is intended for use by TextClassifier implementations.
         */
        public Collection<String> resolveEntityListModifications(
                @NonNull Collection<String> entityTypes) {
            final Set<String> finalSet = new HashSet<>();
            if (mIncludeTypesFromTextClassifier) {
                finalSet.addAll(entityTypes);
            }
            finalSet.addAll(mIncludedTypes);
            finalSet.removeAll(mExcludedTypes);
            return finalSet;
        }

        /**
         * Retrieves the list of hints.
         *
         * @return An unmodifiable collection of the hints.
         */
        public Collection<String> getHints() {
            return mHints;
        }

        /**
         * Return whether the client allows the text classifier to include its own list of
         * default types. If this function returns {@code true}, a default list of types suggested
         * from a text classifier will be taking into account.
         *
         * <p>NOTE: This method is intended for use by a text classifier.
         *
         * @see #resolveEntityListModifications(Collection)
         */
        public boolean shouldIncludeTypesFromTextClassifier() {
            return mIncludeTypesFromTextClassifier;
        }

        @Override
        public int describeContents() {
            return 0;
        }

        public static final @android.annotation.NonNull Parcelable.Creator<EntityConfig> CREATOR =
                new Parcelable.Creator<EntityConfig>() {
                    @Override
                    public EntityConfig createFromParcel(Parcel in) {
                        return new EntityConfig(in);
                    }

                    @Override
                    public EntityConfig[] newArray(int size) {
                        return new EntityConfig[size];
                    }
                };



        /** Builder class to construct the {@link EntityConfig} object. */
        public static final class Builder {
            @Nullable
            private Collection<String> mIncludedTypes;
            @Nullable
            private Collection<String> mExcludedTypes;
            @Nullable
            private Collection<String> mHints;
            private boolean mIncludeTypesFromTextClassifier = true;

            /**
             * Sets a collection of types that are explicitly included.
             */
            @NonNull
            public Builder setIncludedTypes(@Nullable Collection<String> includedTypes) {
                mIncludedTypes = includedTypes;
                return this;
            }

            /**
             * Sets a collection of types that are explicitly excluded.
             */
            @NonNull
            public Builder setExcludedTypes(@Nullable Collection<String> excludedTypes) {
                mExcludedTypes = excludedTypes;
                return this;
            }

            /**
             * Specifies whether or not to include the types suggested by the text classifier. By
             * default, it is included.
             */
            @NonNull
            public Builder includeTypesFromTextClassifier(boolean includeTypesFromTextClassifier) {
                mIncludeTypesFromTextClassifier = includeTypesFromTextClassifier;
                return this;
            }


            /**
             * Sets the hints for the TextClassifier to determine what types of entities to find.
             * These hints will only be used if {@link #includeTypesFromTextClassifier} is
             * set to be true.
             */
            @NonNull
            public Builder setHints(@Nullable Collection<String> hints) {
                mHints = hints;
                return this;
            }

            /**
             * Combines all of the options that have been set and returns a new {@link EntityConfig}
             * object.
             */
            @NonNull
            public EntityConfig build() {
                return new EntityConfig(
                        mIncludedTypes == null
                                ? Collections.emptyList()
                                : new ArrayList<>(mIncludedTypes),
                        mExcludedTypes == null
                                ? Collections.emptyList()
                                : new ArrayList<>(mExcludedTypes),
                        mHints == null
                                ? Collections.emptyList()
                                : Collections.unmodifiableList(new ArrayList<>(mHints)),
                        mIncludeTypesFromTextClassifier);
            }
        }
    }

    /**
     * Utility functions for TextClassifier methods.
     *
     * <ul>
     *  <li>Provides validation of input parameters to TextClassifier methods
     * </ul>
     *
     * Intended to be used only in this package.
     * @hide
     */
    final class Utils {

        /**
         * @throws IllegalArgumentException if text is null; startIndex is negative;
         *      endIndex is greater than text.length() or is not greater than startIndex;
         *      options is null
         */
        static void checkArgument(@NonNull CharSequence text, int startIndex, int endIndex) {
            Preconditions.checkArgument(text != null);
            Preconditions.checkArgument(startIndex >= 0);
            Preconditions.checkArgument(endIndex <= text.length());
            Preconditions.checkArgument(endIndex > startIndex);
        }

        static void checkTextLength(CharSequence text, int maxLength) {
            Preconditions.checkArgumentInRange(text.length(), 0, maxLength, "text.length()");
        }

        /**
         * Generates links using legacy {@link Linkify}.
         */
        public static TextLinks generateLegacyLinks(@NonNull TextLinks.Request request) {
            final String string = request.getText().toString();
            final TextLinks.Builder links = new TextLinks.Builder(string);

            final Collection<String> entities = request.getEntityConfig()
                    .resolveEntityListModifications(Collections.emptyList());
            if (entities.contains(TextClassifier.TYPE_URL)) {
                addLinks(links, string, TextClassifier.TYPE_URL);
            }
            if (entities.contains(TextClassifier.TYPE_PHONE)) {
                addLinks(links, string, TextClassifier.TYPE_PHONE);
            }
            if (entities.contains(TextClassifier.TYPE_EMAIL)) {
                addLinks(links, string, TextClassifier.TYPE_EMAIL);
            }
            // NOTE: Do not support MAP_ADDRESSES. Legacy version does not work well.
            return links.build();
        }

        private static void addLinks(
                TextLinks.Builder links, String string, @EntityType String entityType) {
            final Spannable spannable = new SpannableString(string);
            if (Linkify.addLinks(spannable, linkMask(entityType))) {
                final URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
                for (URLSpan urlSpan : spans) {
                    links.addLink(
                            spannable.getSpanStart(urlSpan),
                            spannable.getSpanEnd(urlSpan),
                            entityScores(entityType),
                            urlSpan);
                }
            }
        }

        @LinkifyMask
        private static int linkMask(@EntityType String entityType) {
            switch (entityType) {
                case TextClassifier.TYPE_URL:
                    return Linkify.WEB_URLS;
                case TextClassifier.TYPE_PHONE:
                    return Linkify.PHONE_NUMBERS;
                case TextClassifier.TYPE_EMAIL:
                    return Linkify.EMAIL_ADDRESSES;
                default:
                    // NOTE: Do not support MAP_ADDRESSES. Legacy version does not work well.
                    return 0;
            }
        }

        private static Map<String, Float> entityScores(@EntityType String entityType) {
            final Map<String, Float> scores = new ArrayMap<>();
            scores.put(entityType, 1f);
            return scores;
        }

        static void checkMainThread() {
            if (Looper.myLooper() == Looper.getMainLooper()) {
                Log.w(DEFAULT_LOG_TAG, "TextClassifier called on main thread");
            }
        }
    }
}
