/*
 * 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.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import android.view.textclassifier.TextClassifier.EntityType;
import android.view.textclassifier.TextClassifier.WidgetType;

import com.android.internal.util.Preconditions;

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

/**
 * A selection event.
 * Specify index parameters as word token indices.
 */
public final class SelectionEvent implements Parcelable {

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({ACTION_OVERTYPE, ACTION_COPY, ACTION_PASTE, ACTION_CUT,
            ACTION_SHARE, ACTION_SMART_SHARE, ACTION_DRAG, ACTION_ABANDON,
            ACTION_OTHER, ACTION_SELECT_ALL, ACTION_RESET})
    // NOTE: ActionType values should not be lower than 100 to avoid colliding with the other
    // EventTypes declared below.
    public @interface ActionType {
        /*
         * Terminal event types range: [100,200).
         * Non-terminal event types range: [200,300).
         */
    }

    /** User typed over the selection. */
    public static final int ACTION_OVERTYPE = 100;
    /** User copied the selection. */
    public static final int ACTION_COPY = 101;
    /** User pasted over the selection. */
    public static final int ACTION_PASTE = 102;
    /** User cut the selection. */
    public static final int ACTION_CUT = 103;
    /** User shared the selection. */
    public static final int ACTION_SHARE = 104;
    /** User clicked the textAssist menu item. */
    public static final int ACTION_SMART_SHARE = 105;
    /** User dragged+dropped the selection. */
    public static final int ACTION_DRAG = 106;
    /** User abandoned the selection. */
    public static final int ACTION_ABANDON = 107;
    /** User performed an action on the selection. */
    public static final int ACTION_OTHER = 108;

    // Non-terminal actions.
    /** User activated Select All */
    public static final int ACTION_SELECT_ALL = 200;
    /** User reset the smart selection. */
    public static final int ACTION_RESET = 201;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({ACTION_OVERTYPE, ACTION_COPY, ACTION_PASTE, ACTION_CUT,
            ACTION_SHARE, ACTION_SMART_SHARE, ACTION_DRAG, ACTION_ABANDON,
            ACTION_OTHER, ACTION_SELECT_ALL, ACTION_RESET,
            EVENT_SELECTION_STARTED, EVENT_SELECTION_MODIFIED,
            EVENT_SMART_SELECTION_SINGLE, EVENT_SMART_SELECTION_MULTI,
            EVENT_AUTO_SELECTION})
    // NOTE: EventTypes declared here must be less than 100 to avoid colliding with the
    // ActionTypes declared above.
    public @interface EventType {
        /*
         * Range: 1 -> 99.
         */
    }

    /** User started a new selection. */
    public static final int EVENT_SELECTION_STARTED = 1;
    /** User modified an existing selection. */
    public static final int EVENT_SELECTION_MODIFIED = 2;
    /** Smart selection triggered for a single token (word). */
    public static final int EVENT_SMART_SELECTION_SINGLE = 3;
    /** Smart selection triggered spanning multiple tokens (words). */
    public static final int EVENT_SMART_SELECTION_MULTI = 4;
    /** Something else other than User or the default TextClassifier triggered a selection. */
    public static final int EVENT_AUTO_SELECTION = 5;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({INVOCATION_MANUAL, INVOCATION_LINK, INVOCATION_UNKNOWN})
    public @interface InvocationMethod {}

    /** Selection was invoked by the user long pressing, double tapping, or dragging to select. */
    public static final int INVOCATION_MANUAL = 1;
    /** Selection was invoked by the user tapping on a link. */
    public static final int INVOCATION_LINK = 2;
    /** Unknown invocation method */
    public static final int INVOCATION_UNKNOWN = 0;

    private static final String NO_SIGNATURE = "";

    private final int mAbsoluteStart;
    private final int mAbsoluteEnd;
    private final @EntityType String mEntityType;

    private @EventType int mEventType;
    private String mPackageName = "";
    private String mWidgetType = TextClassifier.WIDGET_TYPE_UNKNOWN;
    private @InvocationMethod int mInvocationMethod;
    @Nullable private String mWidgetVersion;
    @Nullable private String mResultId;
    private long mEventTime;
    private long mDurationSinceSessionStart;
    private long mDurationSincePreviousEvent;
    private int mEventIndex;
    @Nullable private TextClassificationSessionId mSessionId;
    private int mStart;
    private int mEnd;
    private int mSmartStart;
    private int mSmartEnd;

    SelectionEvent(
            int start, int end,
            @EventType int eventType, @EntityType String entityType,
            @InvocationMethod int invocationMethod, @Nullable String resultId) {
        Preconditions.checkArgument(end >= start, "end cannot be less than start");
        mAbsoluteStart = start;
        mAbsoluteEnd = end;
        mEventType = eventType;
        mEntityType = Preconditions.checkNotNull(entityType);
        mResultId = resultId;
        mInvocationMethod = invocationMethod;
    }

    private SelectionEvent(Parcel in) {
        mAbsoluteStart = in.readInt();
        mAbsoluteEnd = in.readInt();
        mEventType = in.readInt();
        mEntityType = in.readString();
        mWidgetVersion = in.readInt() > 0 ? in.readString() : null;
        mPackageName = in.readString();
        mWidgetType = in.readString();
        mInvocationMethod = in.readInt();
        mResultId = in.readString();
        mEventTime = in.readLong();
        mDurationSinceSessionStart = in.readLong();
        mDurationSincePreviousEvent = in.readLong();
        mEventIndex = in.readInt();
        mSessionId = in.readInt() > 0
                ? TextClassificationSessionId.CREATOR.createFromParcel(in) : null;
        mStart = in.readInt();
        mEnd = in.readInt();
        mSmartStart = in.readInt();
        mSmartEnd = in.readInt();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mAbsoluteStart);
        dest.writeInt(mAbsoluteEnd);
        dest.writeInt(mEventType);
        dest.writeString(mEntityType);
        dest.writeInt(mWidgetVersion != null ? 1 : 0);
        if (mWidgetVersion != null) {
            dest.writeString(mWidgetVersion);
        }
        dest.writeString(mPackageName);
        dest.writeString(mWidgetType);
        dest.writeInt(mInvocationMethod);
        dest.writeString(mResultId);
        dest.writeLong(mEventTime);
        dest.writeLong(mDurationSinceSessionStart);
        dest.writeLong(mDurationSincePreviousEvent);
        dest.writeInt(mEventIndex);
        dest.writeInt(mSessionId != null ? 1 : 0);
        if (mSessionId != null) {
            mSessionId.writeToParcel(dest, flags);
        }
        dest.writeInt(mStart);
        dest.writeInt(mEnd);
        dest.writeInt(mSmartStart);
        dest.writeInt(mSmartEnd);
    }

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

    /**
     * Creates a "selection started" event.
     *
     * @param invocationMethod  the way the selection was triggered
     * @param start  the index of the selected text
     */
    @NonNull
    public static SelectionEvent createSelectionStartedEvent(
            @SelectionEvent.InvocationMethod int invocationMethod, int start) {
        return new SelectionEvent(
                start, start + 1, SelectionEvent.EVENT_SELECTION_STARTED,
                TextClassifier.TYPE_UNKNOWN, invocationMethod, NO_SIGNATURE);
    }

    /**
     * Creates a "selection modified" event.
     * Use when the user modifies the selection.
     *
     * @param start  the start (inclusive) index of the selection
     * @param end  the end (exclusive) index of the selection
     *
     * @throws IllegalArgumentException if end is less than start
     */
    @NonNull
    public static SelectionEvent createSelectionModifiedEvent(int start, int end) {
        Preconditions.checkArgument(end >= start, "end cannot be less than start");
        return new SelectionEvent(
                start, end, SelectionEvent.EVENT_SELECTION_MODIFIED,
                TextClassifier.TYPE_UNKNOWN, INVOCATION_UNKNOWN, NO_SIGNATURE);
    }

    /**
     * Creates a "selection modified" event.
     * Use when the user modifies the selection and the selection's entity type is known.
     *
     * @param start  the start (inclusive) index of the selection
     * @param end  the end (exclusive) index of the selection
     * @param classification  the TextClassification object returned by the TextClassifier that
     *      classified the selected text
     *
     * @throws IllegalArgumentException if end is less than start
     */
    @NonNull
    public static SelectionEvent createSelectionModifiedEvent(
            int start, int end, @NonNull TextClassification classification) {
        Preconditions.checkArgument(end >= start, "end cannot be less than start");
        Preconditions.checkNotNull(classification);
        final String entityType = classification.getEntityCount() > 0
                ? classification.getEntity(0)
                : TextClassifier.TYPE_UNKNOWN;
        return new SelectionEvent(
                start, end, SelectionEvent.EVENT_SELECTION_MODIFIED,
                entityType, INVOCATION_UNKNOWN, classification.getId());
    }

    /**
     * Creates a "selection modified" event.
     * Use when a TextClassifier modifies the selection.
     *
     * @param start  the start (inclusive) index of the selection
     * @param end  the end (exclusive) index of the selection
     * @param selection  the TextSelection object returned by the TextClassifier for the
     *      specified selection
     *
     * @throws IllegalArgumentException if end is less than start
     */
    @NonNull
    public static SelectionEvent createSelectionModifiedEvent(
            int start, int end, @NonNull TextSelection selection) {
        Preconditions.checkArgument(end >= start, "end cannot be less than start");
        Preconditions.checkNotNull(selection);
        final String entityType = selection.getEntityCount() > 0
                ? selection.getEntity(0)
                : TextClassifier.TYPE_UNKNOWN;
        return new SelectionEvent(
                start, end, SelectionEvent.EVENT_AUTO_SELECTION,
                entityType, INVOCATION_UNKNOWN, selection.getId());
    }

    /**
     * Creates an event specifying an action taken on a selection.
     * Use when the user clicks on an action to act on the selected text.
     *
     * @param start  the start (inclusive) index of the selection
     * @param end  the end (exclusive) index of the selection
     * @param actionType  the action that was performed on the selection
     *
     * @throws IllegalArgumentException if end is less than start
     */
    @NonNull
    public static SelectionEvent createSelectionActionEvent(
            int start, int end, @SelectionEvent.ActionType int actionType) {
        Preconditions.checkArgument(end >= start, "end cannot be less than start");
        checkActionType(actionType);
        return new SelectionEvent(
                start, end, actionType, TextClassifier.TYPE_UNKNOWN, INVOCATION_UNKNOWN,
                NO_SIGNATURE);
    }

    /**
     * Creates an event specifying an action taken on a selection.
     * Use when the user clicks on an action to act on the selected text and the selection's
     * entity type is known.
     *
     * @param start  the start (inclusive) index of the selection
     * @param end  the end (exclusive) index of the selection
     * @param actionType  the action that was performed on the selection
     * @param classification  the TextClassification object returned by the TextClassifier that
     *      classified the selected text
     *
     * @throws IllegalArgumentException if end is less than start
     * @throws IllegalArgumentException If actionType is not a valid SelectionEvent actionType
     */
    @NonNull
    public static SelectionEvent createSelectionActionEvent(
            int start, int end, @SelectionEvent.ActionType int actionType,
            @NonNull TextClassification classification) {
        Preconditions.checkArgument(end >= start, "end cannot be less than start");
        Preconditions.checkNotNull(classification);
        checkActionType(actionType);
        final String entityType = classification.getEntityCount() > 0
                ? classification.getEntity(0)
                : TextClassifier.TYPE_UNKNOWN;
        return new SelectionEvent(start, end, actionType, entityType, INVOCATION_UNKNOWN,
                classification.getId());
    }

    /**
     * @throws IllegalArgumentException If eventType is not an {@link SelectionEvent.ActionType}
     */
    private static void checkActionType(@SelectionEvent.EventType int eventType)
            throws IllegalArgumentException {
        switch (eventType) {
            case SelectionEvent.ACTION_OVERTYPE:  // fall through
            case SelectionEvent.ACTION_COPY:  // fall through
            case SelectionEvent.ACTION_PASTE:  // fall through
            case SelectionEvent.ACTION_CUT:  // fall through
            case SelectionEvent.ACTION_SHARE:  // fall through
            case SelectionEvent.ACTION_SMART_SHARE:  // fall through
            case SelectionEvent.ACTION_DRAG:  // fall through
            case SelectionEvent.ACTION_ABANDON:  // fall through
            case SelectionEvent.ACTION_SELECT_ALL:  // fall through
            case SelectionEvent.ACTION_RESET:  // fall through
            case SelectionEvent.ACTION_OTHER:  // fall through
                return;
            default:
                throw new IllegalArgumentException(
                        String.format(Locale.US, "%d is not an eventType", eventType));
        }
    }

    int getAbsoluteStart() {
        return mAbsoluteStart;
    }

    int getAbsoluteEnd() {
        return mAbsoluteEnd;
    }

    /**
     * Returns the type of event that was triggered. e.g. {@link #ACTION_COPY}.
     */
    @EventType
    public int getEventType() {
        return mEventType;
    }

    /**
     * Sets the event type.
     */
    void setEventType(@EventType int eventType) {
        mEventType = eventType;
    }

    /**
     * Returns the type of entity that is associated with this event. e.g.
     * {@link android.view.textclassifier.TextClassifier#TYPE_EMAIL}.
     */
    @EntityType
    @NonNull
    public String getEntityType() {
        return mEntityType;
    }

    /**
     * Returns the package name of the app that this event originated in.
     */
    @NonNull
    public String getPackageName() {
        return mPackageName;
    }

    /**
     * Returns the type of widget that was involved in triggering this event.
     */
    @WidgetType
    @NonNull
    public String getWidgetType() {
        return mWidgetType;
    }

    /**
     * Returns a string version info for the widget this event was triggered in.
     */
    @Nullable
    public String getWidgetVersion() {
        return mWidgetVersion;
    }

    /**
     * Sets the {@link TextClassificationContext} for this event.
     */
    void setTextClassificationSessionContext(TextClassificationContext context) {
        mPackageName = context.getPackageName();
        mWidgetType = context.getWidgetType();
        mWidgetVersion = context.getWidgetVersion();
    }

    /**
     * Returns the way the selection mode was invoked.
     */
    public @InvocationMethod int getInvocationMethod() {
        return mInvocationMethod;
    }

    /**
     * Sets the invocationMethod for this event.
     */
    void setInvocationMethod(@InvocationMethod int invocationMethod) {
        mInvocationMethod = invocationMethod;
    }

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

    SelectionEvent setResultId(@Nullable String resultId) {
        mResultId = resultId;
        return this;
    }

    /**
     * Returns the time this event was triggered.
     */
    public long getEventTime() {
        return mEventTime;
    }

    SelectionEvent setEventTime(long timeMs) {
        mEventTime = timeMs;
        return this;
    }

    /**
     * Returns the duration in ms between when this event was triggered and when the first event in
     * the selection session was triggered.
     */
    public long getDurationSinceSessionStart() {
        return mDurationSinceSessionStart;
    }

    SelectionEvent setDurationSinceSessionStart(long durationMs) {
        mDurationSinceSessionStart = durationMs;
        return this;
    }

    /**
     * Returns the duration in ms between when this event was triggered and when the previous event
     * in the selection session was triggered.
     */
    public long getDurationSincePreviousEvent() {
        return mDurationSincePreviousEvent;
    }

    SelectionEvent setDurationSincePreviousEvent(long durationMs) {
        this.mDurationSincePreviousEvent = durationMs;
        return this;
    }

    /**
     * Returns the index (e.g. 1st event, 2nd event, etc.) of this event in the selection session.
     */
    public int getEventIndex() {
        return mEventIndex;
    }

    SelectionEvent setEventIndex(int index) {
        mEventIndex = index;
        return this;
    }

    /**
     * Returns the selection session id.
     */
    @Nullable
    public TextClassificationSessionId getSessionId() {
        return mSessionId;
    }

    SelectionEvent setSessionId(TextClassificationSessionId id) {
        mSessionId = id;
        return this;
    }

    /**
     * Returns the start index of this events relative to the index of the start selection
     * event in the selection session.
     */
    public int getStart() {
        return mStart;
    }

    SelectionEvent setStart(int start) {
        mStart = start;
        return this;
    }

    /**
     * Returns the end index of this events relative to the index of the start selection
     * event in the selection session.
     */
    public int getEnd() {
        return mEnd;
    }

    SelectionEvent setEnd(int end) {
        mEnd = end;
        return this;
    }

    /**
     * Returns the start index of this events relative to the index of the smart selection
     * event in the selection session.
     */
    public int getSmartStart() {
        return mSmartStart;
    }

    SelectionEvent setSmartStart(int start) {
        this.mSmartStart = start;
        return this;
    }

    /**
     * Returns the end index of this events relative to the index of the smart selection
     * event in the selection session.
     */
    public int getSmartEnd() {
        return mSmartEnd;
    }

    SelectionEvent setSmartEnd(int end) {
        mSmartEnd = end;
        return this;
    }

    boolean isTerminal() {
        return isTerminal(mEventType);
    }

    /**
     * Returns true if the eventType is a terminal event type. Otherwise returns false.
     * A terminal event is an event that ends a selection interaction.
     */
    public static boolean isTerminal(@EventType int eventType) {
        switch (eventType) {
            case ACTION_OVERTYPE:  // fall through
            case ACTION_COPY:  // fall through
            case ACTION_PASTE:  // fall through
            case ACTION_CUT:  // fall through
            case ACTION_SHARE:  // fall through
            case ACTION_SMART_SHARE:  // fall through
            case ACTION_DRAG:  // fall through
            case ACTION_ABANDON:  // fall through
            case ACTION_OTHER:  // fall through
                return true;
            default:
                return false;
        }
    }

    @Override
    public int hashCode() {
        return Objects.hash(mAbsoluteStart, mAbsoluteEnd, mEventType, mEntityType,
                mWidgetVersion, mPackageName, mWidgetType, mInvocationMethod, mResultId,
                mEventTime, mDurationSinceSessionStart, mDurationSincePreviousEvent,
                mEventIndex, mSessionId, mStart, mEnd, mSmartStart, mSmartEnd);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof SelectionEvent)) {
            return false;
        }

        final SelectionEvent other = (SelectionEvent) obj;
        return mAbsoluteStart == other.mAbsoluteStart
                && mAbsoluteEnd == other.mAbsoluteEnd
                && mEventType == other.mEventType
                && Objects.equals(mEntityType, other.mEntityType)
                && Objects.equals(mWidgetVersion, other.mWidgetVersion)
                && Objects.equals(mPackageName, other.mPackageName)
                && Objects.equals(mWidgetType, other.mWidgetType)
                && mInvocationMethod == other.mInvocationMethod
                && Objects.equals(mResultId, other.mResultId)
                && mEventTime == other.mEventTime
                && mDurationSinceSessionStart == other.mDurationSinceSessionStart
                && mDurationSincePreviousEvent == other.mDurationSincePreviousEvent
                && mEventIndex == other.mEventIndex
                && Objects.equals(mSessionId, other.mSessionId)
                && mStart == other.mStart
                && mEnd == other.mEnd
                && mSmartStart == other.mSmartStart
                && mSmartEnd == other.mSmartEnd;
    }

    @Override
    public String toString() {
        return String.format(Locale.US,
                "SelectionEvent {absoluteStart=%d, absoluteEnd=%d, eventType=%d, entityType=%s, "
                        + "widgetVersion=%s, packageName=%s, widgetType=%s, invocationMethod=%s, "
                        + "resultId=%s, eventTime=%d, durationSinceSessionStart=%d, "
                        + "durationSincePreviousEvent=%d, eventIndex=%d,"
                        + "sessionId=%s, start=%d, end=%d, smartStart=%d, smartEnd=%d}",
                mAbsoluteStart, mAbsoluteEnd, mEventType, mEntityType,
                mWidgetVersion, mPackageName, mWidgetType, mInvocationMethod,
                mResultId, mEventTime, mDurationSinceSessionStart,
                mDurationSincePreviousEvent, mEventIndex,
                mSessionId, mStart, mEnd, mSmartStart, mSmartEnd);
    }

    public static final Creator<SelectionEvent> CREATOR = new Creator<SelectionEvent>() {
        @Override
        public SelectionEvent createFromParcel(Parcel in) {
            return new SelectionEvent(in);
        }

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