/*
 * Copyright 2018 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.NonNull;
import android.annotation.Nullable;
import android.icu.util.ULocale;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;

import com.android.internal.annotations.VisibleForTesting;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Objects;

/**
 * This class represents events that are sent by components to the {@link TextClassifier} to report
 * something of note that relates to a feature powered by the TextClassifier. The TextClassifier may
 * log these events or use them to improve future responses to queries.
 * <p>
 * Each category of events has its their own subclass. Events of each type have an associated
 * set of related properties. You can find their specification in the subclasses.
 */
public abstract class TextClassifierEvent implements Parcelable {

    private static final int PARCEL_TOKEN_TEXT_SELECTION_EVENT = 1;
    private static final int PARCEL_TOKEN_TEXT_LINKIFY_EVENT = 2;
    private static final int PARCEL_TOKEN_CONVERSATION_ACTION_EVENT = 3;
    private static final int PARCEL_TOKEN_LANGUAGE_DETECTION_EVENT = 4;

    /** @hide **/
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({CATEGORY_SELECTION, CATEGORY_LINKIFY,
            CATEGORY_CONVERSATION_ACTIONS, CATEGORY_LANGUAGE_DETECTION})
    public @interface Category {
        // For custom event categories, use range 1000+.
    }

    /**
     * Smart selection
     *
     * @see TextSelectionEvent
     */
    public static final int CATEGORY_SELECTION = 1;
    /**
     * Linkify
     *
     * @see TextLinkifyEvent
     */
    public static final int CATEGORY_LINKIFY = 2;
    /**
     *  Conversation actions
     *
     * @see ConversationActionsEvent
     */
    public static final int CATEGORY_CONVERSATION_ACTIONS = 3;
    /**
     * Language detection
     *
     * @see LanguageDetectionEvent
     */
    public static final int CATEGORY_LANGUAGE_DETECTION = 4;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({TYPE_SELECTION_STARTED, TYPE_SELECTION_MODIFIED,
            TYPE_SMART_SELECTION_SINGLE, TYPE_SMART_SELECTION_MULTI, TYPE_AUTO_SELECTION,
            TYPE_ACTIONS_SHOWN, TYPE_LINK_CLICKED, TYPE_OVERTYPE, TYPE_COPY_ACTION,
            TYPE_PASTE_ACTION, TYPE_CUT_ACTION, TYPE_SHARE_ACTION, TYPE_SMART_ACTION,
            TYPE_SELECTION_DRAG, TYPE_SELECTION_DESTROYED, TYPE_OTHER_ACTION, TYPE_SELECT_ALL,
            TYPE_SELECTION_RESET, TYPE_MANUAL_REPLY, TYPE_ACTIONS_GENERATED, TYPE_LINKS_GENERATED})
    public @interface Type {
        // For custom event types, use range 1,000,000+.
    }

    // All these event type constants are required to match with those defined in
    // textclassifier_enums.proto.
    /** User started a new selection. */
    public static final int TYPE_SELECTION_STARTED = 1;
    /** User modified an existing selection. */
    public static final int TYPE_SELECTION_MODIFIED = 2;
    /** Smart selection triggered for a single token (word). */
    public static final int TYPE_SMART_SELECTION_SINGLE = 3;
    /** Smart selection triggered spanning multiple tokens (words). */
    public static final int TYPE_SMART_SELECTION_MULTI = 4;
    /** Something else other than user or the default TextClassifier triggered a selection. */
    public static final int TYPE_AUTO_SELECTION = 5;
    /** Smart actions shown to the user. */
    public static final int TYPE_ACTIONS_SHOWN = 6;
    /** User clicked a link. */
    public static final int TYPE_LINK_CLICKED = 7;
    /** User typed over the selection. */
    public static final int TYPE_OVERTYPE = 8;
    /** User clicked on Copy action. */
    public static final int TYPE_COPY_ACTION = 9;
    /** User clicked on Paste action. */
    public static final int TYPE_PASTE_ACTION = 10;
    /** User clicked on Cut action. */
    public static final int TYPE_CUT_ACTION = 11;
    /** User clicked on Share action. */
    public static final int TYPE_SHARE_ACTION = 12;
    /** User clicked on a Smart action. */
    public static final int TYPE_SMART_ACTION = 13;
    /** User dragged+dropped the selection. */
    public static final int TYPE_SELECTION_DRAG = 14;
    /** Selection is destroyed. */
    public static final int TYPE_SELECTION_DESTROYED = 15;
    /** User clicked on a custom action. */
    public static final int TYPE_OTHER_ACTION = 16;
    /** User clicked on Select All action */
    public static final int TYPE_SELECT_ALL = 17;
    /** User reset the smart selection. */
    public static final int TYPE_SELECTION_RESET = 18;
    /** User composed a reply. */
    public static final int TYPE_MANUAL_REPLY = 19;
    /** TextClassifier generated some actions */
    public static final int TYPE_ACTIONS_GENERATED = 20;
    /** Some text links were generated.*/
    public static final int TYPE_LINKS_GENERATED = 21;

    @Category
    private final int mEventCategory;
    @Type
    private final int mEventType;
    @Nullable
    private final String[] mEntityTypes;
    @Nullable
    private TextClassificationContext mEventContext;
    @Nullable
    private final String mResultId;
    private final int mEventIndex;
    private final float[] mScores;
    @Nullable
    private final String mModelName;
    private final int[] mActionIndices;
    @Nullable
    private final ULocale mLocale;
    private final Bundle mExtras;

    /**
     * Session id holder to help with converting this event to the legacy SelectionEvent.
     * @hide
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    @Nullable
    public TextClassificationSessionId mHiddenTempSessionId;

    private TextClassifierEvent(Builder builder) {
        mEventCategory = builder.mEventCategory;
        mEventType = builder.mEventType;
        mEntityTypes = builder.mEntityTypes;
        mEventContext = builder.mEventContext;
        mResultId = builder.mResultId;
        mEventIndex = builder.mEventIndex;
        mScores = builder.mScores;
        mModelName = builder.mModelName;
        mActionIndices = builder.mActionIndices;
        mLocale = builder.mLocale;
        mExtras = builder.mExtras == null ? Bundle.EMPTY : builder.mExtras;
    }

    private TextClassifierEvent(Parcel in) {
        mEventCategory = in.readInt();
        mEventType = in.readInt();
        mEntityTypes = in.readStringArray();
        mEventContext = in.readParcelable(null);
        mResultId = in.readString();
        mEventIndex = in.readInt();
        int scoresLength = in.readInt();
        mScores = new float[scoresLength];
        in.readFloatArray(mScores);
        mModelName = in.readString();
        mActionIndices = in.createIntArray();
        final String languageTag = in.readString();
        mLocale = languageTag == null ? null : ULocale.forLanguageTag(languageTag);
        mExtras = in.readBundle();
    }

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

    @NonNull
    public static final Creator<TextClassifierEvent> CREATOR = new Creator<TextClassifierEvent>() {
        @Override
        public TextClassifierEvent createFromParcel(Parcel in) {
            int token = in.readInt();
            if (token == PARCEL_TOKEN_TEXT_SELECTION_EVENT) {
                return new TextSelectionEvent(in);
            }
            if (token == PARCEL_TOKEN_TEXT_LINKIFY_EVENT) {
                return new TextLinkifyEvent(in);
            }
            if (token == PARCEL_TOKEN_LANGUAGE_DETECTION_EVENT) {
                return new LanguageDetectionEvent(in);
            }
            if (token == PARCEL_TOKEN_CONVERSATION_ACTION_EVENT) {
                return new ConversationActionsEvent(in);
            }
            throw new IllegalStateException("Unexpected input event type token in parcel.");
        }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(getParcelToken());
        dest.writeInt(mEventCategory);
        dest.writeInt(mEventType);
        dest.writeStringArray(mEntityTypes);
        dest.writeParcelable(mEventContext, flags);
        dest.writeString(mResultId);
        dest.writeInt(mEventIndex);
        dest.writeInt(mScores.length);
        dest.writeFloatArray(mScores);
        dest.writeString(mModelName);
        dest.writeIntArray(mActionIndices);
        dest.writeString(mLocale == null ? null : mLocale.toLanguageTag());
        dest.writeBundle(mExtras);
    }

    private int getParcelToken() {
        if (this instanceof TextSelectionEvent) {
            return PARCEL_TOKEN_TEXT_SELECTION_EVENT;
        }
        if (this instanceof TextLinkifyEvent) {
            return PARCEL_TOKEN_TEXT_LINKIFY_EVENT;
        }
        if (this instanceof LanguageDetectionEvent) {
            return PARCEL_TOKEN_LANGUAGE_DETECTION_EVENT;
        }
        if (this instanceof ConversationActionsEvent) {
            return PARCEL_TOKEN_CONVERSATION_ACTION_EVENT;
        }
        throw new IllegalArgumentException("Unexpected type: " + this.getClass().getSimpleName());
    }

    /**
     * Returns the event category. e.g. {@link #CATEGORY_SELECTION}.
     */
    @Category
    public int getEventCategory() {
        return mEventCategory;
    }

    /**
     * Returns the event type. e.g. {@link #TYPE_SELECTION_STARTED}.
     */
    @Type
    public int getEventType() {
        return mEventType;
    }

    /**
     * Returns an array of entity types. e.g. {@link TextClassifier#TYPE_ADDRESS}.
     *
     * @see Builder#setEntityTypes(String...) for supported types.
     */
    @NonNull
    public String[] getEntityTypes() {
        return mEntityTypes;
    }

    /**
     * Returns the event context.
     */
    @Nullable
    public TextClassificationContext getEventContext() {
        return mEventContext;
    }

    /**
     * Sets the event context.
     * <p>
     * Package-private for SystemTextClassifier's use.
     */
    void setEventContext(@Nullable TextClassificationContext eventContext) {
        mEventContext = eventContext;
    }

    /**
     * Returns the id of the text classifier result related to this event.
     */
    @Nullable
    public String getResultId() {
        return mResultId;
    }

    /**
     * Returns the index of this event in the series of event it belongs to.
     */
    public int getEventIndex() {
        return mEventIndex;
    }

    /**
     * Returns the scores of the suggestions.
     */
    @NonNull
    public float[] getScores() {
        return mScores;
    }

    /**
     * Returns the model name.
     */
    @Nullable
    public String getModelName() {
        return mModelName;
    }

    /**
     * Returns the indices of the actions relating to this event.
     * Actions are usually returned by the text classifier in priority order with the most
     * preferred action at index 0. This list gives an indication of the position of the actions
     * that are being reported.
     *
     * @see Builder#setActionIndices(int...)
     */
    @NonNull
    public int[] getActionIndices() {
        return mActionIndices;
    }

    /**
     * Returns the detected locale.
     */
    @Nullable
    public ULocale getLocale() {
        return mLocale;
    }

    /**
     * Returns a bundle containing non-structured extra information about this event.
     *
     * <p><b>NOTE: </b>Do not modify this bundle.
     */
    @NonNull
    public Bundle getExtras() {
        return mExtras;
    }

    @Override
    public String toString() {
        StringBuilder out = new StringBuilder(128);
        out.append(this.getClass().getSimpleName());
        out.append("{");
        out.append("mEventCategory=").append(mEventCategory);
        out.append(", mEventType=").append(mEventType);
        out.append(", mEntityTypes=").append(Arrays.toString(mEntityTypes));
        out.append(", mEventContext=").append(mEventContext);
        out.append(", mResultId=").append(mResultId);
        out.append(", mEventIndex=").append(mEventIndex);
        out.append(", mExtras=").append(mExtras);
        out.append(", mScores=").append(Arrays.toString(mScores));
        out.append(", mModelName=").append(mModelName);
        out.append(", mActionIndices=").append(Arrays.toString(mActionIndices));
        toString(out);
        out.append("}");
        return out.toString();
    }

    /**
     * Overrides this to append extra fields to the output of {@link #toString()}.
     * <p>
     * Extra fields should be  formatted like this: ", {field_name}={field_value}".
     */
    void toString(StringBuilder out) {}

    /**
     * Returns a {@link SelectionEvent} equivalent of this event; or {@code null} if it can not be
     * converted to a {@link SelectionEvent}.
     * @hide
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    @Nullable
    public final SelectionEvent toSelectionEvent() {
        final int invocationMethod;
        switch (getEventCategory()) {
            case TextClassifierEvent.CATEGORY_SELECTION:
                invocationMethod = SelectionEvent.INVOCATION_MANUAL;
                break;
            case TextClassifierEvent.CATEGORY_LINKIFY:
                invocationMethod = SelectionEvent.INVOCATION_LINK;
                break;
            default:
                // Cannot be converted to a SelectionEvent.
                return null;
        }

        final String entityType = getEntityTypes().length > 0
                ? getEntityTypes()[0] : TextClassifier.TYPE_UNKNOWN;
        final SelectionEvent out = new SelectionEvent(
                /* absoluteStart= */ 0,
                /* absoluteEnd= */ 0,
                /* eventType= */0,
                entityType,
                SelectionEvent.INVOCATION_UNKNOWN,
                SelectionEvent.NO_SIGNATURE);
        out.setInvocationMethod(invocationMethod);

        final TextClassificationContext eventContext = getEventContext();
        if (eventContext != null) {
            out.setTextClassificationSessionContext(getEventContext());
        }
        out.setSessionId(mHiddenTempSessionId);
        final String resultId = getResultId();
        out.setResultId(resultId == null ? SelectionEvent.NO_SIGNATURE : resultId);
        out.setEventIndex(getEventIndex());


        final int eventType;
        switch (getEventType()) {
            case TextClassifierEvent.TYPE_SELECTION_STARTED:
                eventType = SelectionEvent.EVENT_SELECTION_STARTED;
                break;
            case TextClassifierEvent.TYPE_SELECTION_MODIFIED:
                eventType = SelectionEvent.EVENT_SELECTION_MODIFIED;
                break;
            case TextClassifierEvent.TYPE_SMART_SELECTION_SINGLE:
                eventType = SelectionEvent.EVENT_SMART_SELECTION_SINGLE;
                break;
            case TextClassifierEvent.TYPE_SMART_SELECTION_MULTI:
                eventType = SelectionEvent.EVENT_SMART_SELECTION_MULTI;
                break;
            case TextClassifierEvent.TYPE_AUTO_SELECTION:
                eventType = SelectionEvent.EVENT_AUTO_SELECTION;
                break;
            case TextClassifierEvent.TYPE_OVERTYPE:
                eventType = SelectionEvent.ACTION_OVERTYPE;
                break;
            case TextClassifierEvent.TYPE_COPY_ACTION:
                eventType = SelectionEvent.ACTION_COPY;
                break;
            case TextClassifierEvent.TYPE_PASTE_ACTION:
                eventType = SelectionEvent.ACTION_PASTE;
                break;
            case TextClassifierEvent.TYPE_CUT_ACTION:
                eventType = SelectionEvent.ACTION_CUT;
                break;
            case TextClassifierEvent.TYPE_SHARE_ACTION:
                eventType = SelectionEvent.ACTION_SHARE;
                break;
            case TextClassifierEvent.TYPE_SMART_ACTION:
                eventType = SelectionEvent.ACTION_SMART_SHARE;
                break;
            case TextClassifierEvent.TYPE_SELECTION_DRAG:
                eventType = SelectionEvent.ACTION_DRAG;
                break;
            case TextClassifierEvent.TYPE_SELECTION_DESTROYED:
                eventType = SelectionEvent.ACTION_ABANDON;
                break;
            case TextClassifierEvent.TYPE_OTHER_ACTION:
                eventType = SelectionEvent.ACTION_OTHER;
                break;
            case TextClassifierEvent.TYPE_SELECT_ALL:
                eventType = SelectionEvent.ACTION_SELECT_ALL;
                break;
            case TextClassifierEvent.TYPE_SELECTION_RESET:
                eventType = SelectionEvent.ACTION_RESET;
                break;
            default:
                eventType = 0;
                break;
        }
        out.setEventType(eventType);

        if (this instanceof TextClassifierEvent.TextSelectionEvent) {
            final TextClassifierEvent.TextSelectionEvent selEvent =
                    (TextClassifierEvent.TextSelectionEvent) this;
            // TODO: Ideally, we should have these fields in events of type
            // TextClassifierEvent.TextLinkifyEvent events too but we're now past the API deadline
            // and will have to do with these fields being set only in TextSelectionEvent events.
            // Fix this at the next API bump.
            out.setStart(selEvent.getRelativeWordStartIndex());
            out.setEnd(selEvent.getRelativeWordEndIndex());
            out.setSmartStart(selEvent.getRelativeSuggestedWordStartIndex());
            out.setSmartEnd(selEvent.getRelativeSuggestedWordEndIndex());
        }

        return out;
    }

    /**
     * Builder to build a text classifier event.
     *
     * @param <T> The subclass to be built.
     */
    public abstract static class Builder<T extends Builder<T>> {

        private final int mEventCategory;
        private final int mEventType;
        private String[] mEntityTypes = new String[0];
        @Nullable
        private TextClassificationContext mEventContext;
        @Nullable
        private String mResultId;
        private int mEventIndex;
        private float[] mScores = new float[0];
        @Nullable
        private String mModelName;
        private int[] mActionIndices = new int[0];
        @Nullable
        private ULocale mLocale;
        @Nullable
        private Bundle mExtras;

        /**
         * Creates a builder for building {@link TextClassifierEvent}s.
         *
         * @param eventCategory The event category. e.g. {@link #CATEGORY_SELECTION}
         * @param eventType     The event type. e.g. {@link #TYPE_SELECTION_STARTED}
         */
        private Builder(@Category int eventCategory, @Type int eventType) {
            mEventCategory = eventCategory;
            mEventType = eventType;
        }

        /**
         * Sets the entity types. e.g. {@link TextClassifier#TYPE_ADDRESS}.
         * <p>
         * Supported types:
         * <p>See {@link TextClassifier.EntityType}
         * <p>See {@link ConversationAction.ActionType}
         * <p>See {@link ULocale#toLanguageTag()}
         */
        @NonNull
        public T setEntityTypes(@NonNull String... entityTypes) {
            Objects.requireNonNull(entityTypes);
            mEntityTypes = new String[entityTypes.length];
            System.arraycopy(entityTypes, 0, mEntityTypes, 0, entityTypes.length);
            return self();
        }

        /**
         * Sets the event context.
         */
        @NonNull
        public T setEventContext(@Nullable TextClassificationContext eventContext) {
            mEventContext = eventContext;
            return self();
        }

        /**
         * Sets the id of the text classifier result related to this event.
         */
        @NonNull
        public T setResultId(@Nullable String resultId) {
            mResultId = resultId;
            return self();
        }

        /**
         * Sets the index of this event in the series of events it belongs to.
         */
        @NonNull
        public T setEventIndex(int eventIndex) {
            mEventIndex = eventIndex;
            return self();
        }

        /**
         * Sets the scores of the suggestions.
         */
        @NonNull
        public T setScores(@NonNull float... scores) {
            Objects.requireNonNull(scores);
            mScores = new float[scores.length];
            System.arraycopy(scores, 0, mScores, 0, scores.length);
            return self();
        }

        /**
         * Sets the model name string.
         */
        @NonNull
        public T setModelName(@Nullable String modelVersion) {
            mModelName = modelVersion;
            return self();
        }

        /**
         * Sets the indices of the actions involved in this event. Actions are usually returned by
         * the text classifier in priority order with the most preferred action at index 0.
         * These indices give an indication of the position of the actions that are being reported.
         * <p>
         * E.g.
         * <pre>
         *   // 3 smart actions are shown at index 0, 1, 2 respectively in response to a link click.
         *   new TextClassifierEvent.Builder(CATEGORY_LINKIFY, TYPE_ACTIONS_SHOWN)
         *       .setEventIndex(0, 1, 2)
         *       ...
         *       .build();
         *
         *   ...
         *
         *   // Smart action at index 1 is activated.
         *   new TextClassifierEvent.Builder(CATEGORY_LINKIFY, TYPE_SMART_ACTION)
         *       .setEventIndex(1)
         *       ...
         *       .build();
         * </pre>
         *
         * @see TextClassification#getActions()
         */
        @NonNull
        public T setActionIndices(@NonNull int... actionIndices) {
            mActionIndices = new int[actionIndices.length];
            System.arraycopy(actionIndices, 0, mActionIndices, 0, actionIndices.length);
            return self();
        }

        /**
         * Sets the detected locale.
         */
        @NonNull
        public T setLocale(@Nullable ULocale locale) {
            mLocale = locale;
            return self();
        }

        /**
         * Sets a bundle containing non-structured extra information about the event.
         *
         * <p><b>NOTE: </b>Prefer to set only immutable values on the bundle otherwise, avoid
         * updating the internals of this bundle as it may have unexpected consequences on the
         * clients of the built event object. For similar reasons, avoid depending on mutable
         * objects in this bundle.
         */
        @NonNull
        public T setExtras(@NonNull Bundle extras) {
            mExtras = Objects.requireNonNull(extras);
            return self();
        }

        abstract T self();
    }

    /**
     * This class represents events that are related to the smart text selection feature.
     * <p>
     * <pre>
     *     // User started a selection. e.g. "York" in text "New York City, NY".
     *     new TextSelectionEvent.Builder(TYPE_SELECTION_STARTED)
     *         .setEventContext(classificationContext)
     *         .setEventIndex(0)
     *         .build();
     *
     *     // System smart-selects a recognized entity. e.g. "New York City".
     *     new TextSelectionEvent.Builder(TYPE_SMART_SELECTION_MULTI)
     *         .setEventContext(classificationContext)
     *         .setResultId(textSelection.getId())
     *         .setRelativeWordStartIndex(-1) // Goes back one word to "New" from "York".
     *         .setRelativeWordEndIndex(2)    // Goes forward 2 words from "York" to start of ",".
     *         .setEntityTypes(textClassification.getEntity(0))
     *         .setScore(textClassification.getConfidenceScore(entityType))
     *         .setEventIndex(1)
     *         .build();
     *
     *     // User resets the selection to the original selection. i.e. "York".
     *     new TextSelectionEvent.Builder(TYPE_SELECTION_RESET)
     *         .setEventContext(classificationContext)
     *         .setResultId(textSelection.getId())
     *         .setRelativeSuggestedWordStartIndex(-1) // Repeated from above.
     *         .setRelativeSuggestedWordEndIndex(2)    // Repeated from above.
     *         .setRelativeWordStartIndex(0)           // Original selection is always at (0, 1].
     *         .setRelativeWordEndIndex(1)
     *         .setEntityTypes(textClassification.getEntity(0))
     *         .setScore(textClassification.getConfidenceScore(entityType))
     *         .setEventIndex(2)
     *         .build();
     *
     *     // User modified the selection. e.g. "New".
     *     new TextSelectionEvent.Builder(TYPE_SELECTION_MODIFIED)
     *         .setEventContext(classificationContext)
     *         .setResultId(textSelection.getId())
     *         .setRelativeSuggestedWordStartIndex(-1) // Repeated from above.
     *         .setRelativeSuggestedWordEndIndex(2)    // Repeated from above.
     *         .setRelativeWordStartIndex(-1)          // Goes backward one word from "York" to
     *         "New".
     *         .setRelativeWordEndIndex(0)             // Goes backward one word to exclude "York".
     *         .setEntityTypes(textClassification.getEntity(0))
     *         .setScore(textClassification.getConfidenceScore(entityType))
     *         .setEventIndex(3)
     *         .build();
     *
     *     // Smart (contextual) actions (at indices, 0, 1, 2) presented to the user.
     *     // e.g. "Map", "Ride share", "Explore".
     *     new TextSelectionEvent.Builder(TYPE_ACTIONS_SHOWN)
     *         .setEventContext(classificationContext)
     *         .setResultId(textClassification.getId())
     *         .setEntityTypes(textClassification.getEntity(0))
     *         .setScore(textClassification.getConfidenceScore(entityType))
     *         .setActionIndices(0, 1, 2)
     *         .setEventIndex(4)
     *         .build();
     *
     *     // User chooses the "Copy" action.
     *     new TextSelectionEvent.Builder(TYPE_COPY_ACTION)
     *         .setEventContext(classificationContext)
     *         .setResultId(textClassification.getId())
     *         .setEntityTypes(textClassification.getEntity(0))
     *         .setScore(textClassification.getConfidenceScore(entityType))
     *         .setEventIndex(5)
     *         .build();
     *
     *     // User chooses smart action at index 1. i.e. "Ride share".
     *     new TextSelectionEvent.Builder(TYPE_SMART_ACTION)
     *         .setEventContext(classificationContext)
     *         .setResultId(textClassification.getId())
     *         .setEntityTypes(textClassification.getEntity(0))
     *         .setScore(textClassification.getConfidenceScore(entityType))
     *         .setActionIndices(1)
     *         .setEventIndex(5)
     *         .build();
     *
     *     // Selection dismissed.
     *     new TextSelectionEvent.Builder(TYPE_SELECTION_DESTROYED)
     *         .setEventContext(classificationContext)
     *         .setResultId(textClassification.getId())
     *         .setEntityTypes(textClassification.getEntity(0))
     *         .setScore(textClassification.getConfidenceScore(entityType))
     *         .setEventIndex(6)
     *         .build();
     * </pre>
     * <p>
     */
    public static final class TextSelectionEvent extends TextClassifierEvent implements Parcelable {

        @NonNull
        public static final Creator<TextSelectionEvent> CREATOR =
                new Creator<TextSelectionEvent>() {
                    @Override
                    public TextSelectionEvent createFromParcel(Parcel in) {
                        in.readInt(); // skip token, we already know this is a TextSelectionEvent
                        return new TextSelectionEvent(in);
                    }

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

        final int mRelativeWordStartIndex;
        final int mRelativeWordEndIndex;
        final int mRelativeSuggestedWordStartIndex;
        final int mRelativeSuggestedWordEndIndex;

        private TextSelectionEvent(TextSelectionEvent.Builder builder) {
            super(builder);
            mRelativeWordStartIndex = builder.mRelativeWordStartIndex;
            mRelativeWordEndIndex = builder.mRelativeWordEndIndex;
            mRelativeSuggestedWordStartIndex = builder.mRelativeSuggestedWordStartIndex;
            mRelativeSuggestedWordEndIndex = builder.mRelativeSuggestedWordEndIndex;
        }

        private TextSelectionEvent(Parcel in) {
            super(in);
            mRelativeWordStartIndex = in.readInt();
            mRelativeWordEndIndex = in.readInt();
            mRelativeSuggestedWordStartIndex = in.readInt();
            mRelativeSuggestedWordEndIndex = in.readInt();
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
            dest.writeInt(mRelativeWordStartIndex);
            dest.writeInt(mRelativeWordEndIndex);
            dest.writeInt(mRelativeSuggestedWordStartIndex);
            dest.writeInt(mRelativeSuggestedWordEndIndex);
        }

        /**
         * Returns the relative word index of the start of the selection.
         */
        public int getRelativeWordStartIndex() {
            return mRelativeWordStartIndex;
        }

        /**
         * Returns the relative word (exclusive) index of the end of the selection.
         */
        public int getRelativeWordEndIndex() {
            return mRelativeWordEndIndex;
        }

        /**
         * Returns the relative word index of the start of the smart selection.
         */
        public int getRelativeSuggestedWordStartIndex() {
            return mRelativeSuggestedWordStartIndex;
        }

        /**
         * Returns the relative word (exclusive) index of the end of the
         * smart selection.
         */
        public int getRelativeSuggestedWordEndIndex() {
            return mRelativeSuggestedWordEndIndex;
        }

        @Override
        void toString(StringBuilder out) {
            out.append(", getRelativeWordStartIndex=").append(mRelativeWordStartIndex);
            out.append(", getRelativeWordEndIndex=").append(mRelativeWordEndIndex);
            out.append(", getRelativeSuggestedWordStartIndex=")
                    .append(mRelativeSuggestedWordStartIndex);
            out.append(", getRelativeSuggestedWordEndIndex=")
                    .append(mRelativeSuggestedWordEndIndex);
        }

        /**
         * Builder class for {@link TextSelectionEvent}.
         */
        public static final class Builder extends
                TextClassifierEvent.Builder<TextSelectionEvent.Builder> {
            int mRelativeWordStartIndex;
            int mRelativeWordEndIndex;
            int mRelativeSuggestedWordStartIndex;
            int mRelativeSuggestedWordEndIndex;

            /**
             * Creates a builder for building {@link TextSelectionEvent}s.
             *
             * @param eventType     The event type. e.g. {@link #TYPE_SELECTION_STARTED}
             */
            public Builder(@Type int eventType) {
                super(CATEGORY_SELECTION, eventType);
            }

            /**
             * Sets the relative word index of the start of the selection.
             */
            @NonNull
            public Builder setRelativeWordStartIndex(int relativeWordStartIndex) {
                mRelativeWordStartIndex = relativeWordStartIndex;
                return this;
            }

            /**
             * Sets the relative word (exclusive) index of the end of the
             * selection.
             */
            @NonNull
            public Builder setRelativeWordEndIndex(int relativeWordEndIndex) {
                mRelativeWordEndIndex = relativeWordEndIndex;
                return this;
            }

            /**
             * Sets the relative word index of the start of the smart
             * selection.
             */
            @NonNull
            public Builder setRelativeSuggestedWordStartIndex(int relativeSuggestedWordStartIndex) {
                mRelativeSuggestedWordStartIndex = relativeSuggestedWordStartIndex;
                return this;
            }

            /**
             * Sets the relative word (exclusive) index of the end of the
             * smart selection.
             */
            @NonNull
            public Builder setRelativeSuggestedWordEndIndex(int relativeSuggestedWordEndIndex) {
                mRelativeSuggestedWordEndIndex = relativeSuggestedWordEndIndex;
                return this;
            }

            @Override
            TextSelectionEvent.Builder self() {
                return this;
            }

            /**
             * Builds and returns a {@link TextSelectionEvent}.
             */
            @NonNull
            public TextSelectionEvent build() {
                return new TextSelectionEvent(this);
            }
        }
    }

    /**
     * This class represents events that are related to the smart linkify feature.
     * <p>
     * <pre>
     *     // User clicked on a link.
     *     new TextLinkifyEvent.Builder(TYPE_LINK_CLICKED)
     *         .setEventContext(classificationContext)
     *         .setResultId(textClassification.getId())
     *         .setEntityTypes(textClassification.getEntity(0))
     *         .setScore(textClassification.getConfidenceScore(entityType))
     *         .setEventIndex(0)
     *         .build();
     *
     *     // Smart (contextual) actions presented to the user in response to a link click.
     *     new TextLinkifyEvent.Builder(TYPE_ACTIONS_SHOWN)
     *         .setEventContext(classificationContext)
     *         .setResultId(textClassification.getId())
     *         .setEntityTypes(textClassification.getEntity(0))
     *         .setScore(textClassification.getConfidenceScore(entityType))
     *         .setActionIndices(range(textClassification.getActions().size()))
     *         .setEventIndex(1)
     *         .build();
     *
     *     // User chooses smart action at index 0.
     *     new TextLinkifyEvent.Builder(TYPE_SMART_ACTION)
     *         .setEventContext(classificationContext)
     *         .setResultId(textClassification.getId())
     *         .setEntityTypes(textClassification.getEntity(0))
     *         .setScore(textClassification.getConfidenceScore(entityType))
     *         .setActionIndices(0)
     *         .setEventIndex(2)
     *         .build();
     * </pre>
     */
    public static final class TextLinkifyEvent extends TextClassifierEvent implements Parcelable {

        @NonNull
        public static final Creator<TextLinkifyEvent> CREATOR =
                new Creator<TextLinkifyEvent>() {
                    @Override
                    public TextLinkifyEvent createFromParcel(Parcel in) {
                        in.readInt(); // skip token, we already know this is a TextLinkifyEvent
                        return new TextLinkifyEvent(in);
                    }

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

        private TextLinkifyEvent(Parcel in) {
            super(in);
        }

        private TextLinkifyEvent(TextLinkifyEvent.Builder builder) {
            super(builder);
        }

        /**
         * Builder class for {@link TextLinkifyEvent}.
         */
        public static final class Builder
                extends TextClassifierEvent.Builder<TextLinkifyEvent.Builder> {
            /**
             * Creates a builder for building {@link TextLinkifyEvent}s.
             *
             * @param eventType The event type. e.g. {@link #TYPE_SMART_ACTION}
             */
            public Builder(@Type int eventType) {
                super(TextClassifierEvent.CATEGORY_LINKIFY, eventType);
            }

            @Override
            Builder self() {
                return this;
            }

            /**
             * Builds and returns a {@link TextLinkifyEvent}.
             */
            @NonNull
            public TextLinkifyEvent build() {
                return new TextLinkifyEvent(this);
            }
        }
    }

    /**
     * This class represents events that are related to the language detection feature.
     * <p>
     * <pre>
     *     // Translate action shown for foreign text.
     *     new LanguageDetectionEvent.Builder(TYPE_ACTIONS_SHOWN)
     *         .setEventContext(classificationContext)
     *         .setResultId(textClassification.getId())
     *         .setEntityTypes(language)
     *         .setScore(score)
     *         .setActionIndices(textClassification.getActions().indexOf(translateAction))
     *         .setEventIndex(0)
     *         .build();
     *
     *     // Translate action selected.
     *     new LanguageDetectionEvent.Builder(TYPE_SMART_ACTION)
     *         .setEventContext(classificationContext)
     *         .setResultId(textClassification.getId())
     *         .setEntityTypes(language)
     *         .setScore(score)
     *         .setActionIndices(textClassification.getActions().indexOf(translateAction))
     *         .setEventIndex(1)
     *         .build();
     */
    public static final class LanguageDetectionEvent extends TextClassifierEvent
            implements Parcelable {

        @NonNull
        public static final Creator<LanguageDetectionEvent> CREATOR =
                new Creator<LanguageDetectionEvent>() {
                    @Override
                    public LanguageDetectionEvent createFromParcel(Parcel in) {
                        // skip token, we already know this is a LanguageDetectionEvent.
                        in.readInt();
                        return new LanguageDetectionEvent(in);
                    }

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

        private LanguageDetectionEvent(Parcel in) {
            super(in);
        }

        private LanguageDetectionEvent(LanguageDetectionEvent.Builder builder) {
            super(builder);
        }

        /**
         * Builder class for {@link LanguageDetectionEvent}.
         */
        public static final class Builder
                extends TextClassifierEvent.Builder<LanguageDetectionEvent.Builder> {

            /**
             * Creates a builder for building {@link TextSelectionEvent}s.
             *
             * @param eventType The event type. e.g. {@link #TYPE_SMART_ACTION}
             */
            public Builder(@Type int eventType) {
                super(TextClassifierEvent.CATEGORY_LANGUAGE_DETECTION, eventType);
            }

            @Override
            Builder self() {
                return this;
            }

            /**
             * Builds and returns a {@link LanguageDetectionEvent}.
             */
            @NonNull
            public LanguageDetectionEvent build() {
                return new LanguageDetectionEvent(this);
            }
        }
    }

    /**
     * This class represents events that are related to the conversation actions feature.
     * <p>
     * <pre>
     *     // Conversation (contextual) actions/replies generated.
     *     new ConversationActionsEvent.Builder(TYPE_ACTIONS_GENERATED)
     *         .setEventContext(classificationContext)
     *         .setResultId(conversationActions.getId())
     *         .setEntityTypes(getTypes(conversationActions))
     *         .setActionIndices(range(conversationActions.getActions().size()))
     *         .setEventIndex(0)
     *         .build();
     *
     *     // Conversation actions/replies presented to user.
     *     new ConversationActionsEvent.Builder(TYPE_ACTIONS_SHOWN)
     *         .setEventContext(classificationContext)
     *         .setResultId(conversationActions.getId())
     *         .setEntityTypes(getTypes(conversationActions))
     *         .setActionIndices(range(conversationActions.getActions().size()))
     *         .setEventIndex(1)
     *         .build();
     *
     *     // User clicked the "Reply" button to compose their custom reply.
     *     new ConversationActionsEvent.Builder(TYPE_MANUAL_REPLY)
     *         .setEventContext(classificationContext)
     *         .setResultId(conversationActions.getId())
     *         .setEventIndex(2)
     *         .build();
     *
     *     // User selected a smart (contextual) action/reply.
     *     new ConversationActionsEvent.Builder(TYPE_SMART_ACTION)
     *         .setEventContext(classificationContext)
     *         .setResultId(conversationActions.getId())
     *         .setEntityTypes(conversationActions.get(1).getType())
     *         .setScore(conversationAction.get(1).getConfidenceScore())
     *         .setActionIndices(1)
     *         .setEventIndex(2)
     *         .build();
     * </pre>
     */
    public static final class ConversationActionsEvent extends TextClassifierEvent
            implements Parcelable {

        @NonNull
        public static final Creator<ConversationActionsEvent> CREATOR =
                new Creator<ConversationActionsEvent>() {
                    @Override
                    public ConversationActionsEvent createFromParcel(Parcel in) {
                        // skip token, we already know this is a ConversationActionsEvent.
                        in.readInt();
                        return new ConversationActionsEvent(in);
                    }

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

        private ConversationActionsEvent(Parcel in) {
            super(in);
        }

        private ConversationActionsEvent(ConversationActionsEvent.Builder builder) {
            super(builder);
        }

        /**
         * Builder class for {@link ConversationActionsEvent}.
         */
        public static final class Builder
                extends TextClassifierEvent.Builder<ConversationActionsEvent.Builder> {
            /**
             * Creates a builder for building {@link TextSelectionEvent}s.
             *
             * @param eventType The event type. e.g. {@link #TYPE_SMART_ACTION}
             */
            public Builder(@Type int eventType) {
                super(TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS, eventType);
            }

            @Override
            Builder self() {
                return this;
            }

            /**
             * Builds and returns a {@link ConversationActionsEvent}.
             */
            @NonNull
            public ConversationActionsEvent build() {
                return new ConversationActionsEvent(this);
            }
        }
    }
}
