/*
 * Copyright (C) 2020 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;

import static android.view.KeyEvent.FLAG_CANCELED;

import static java.lang.annotation.RetentionPolicy.SOURCE;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.os.Parcel;
import android.os.Parcelable;

import com.android.internal.util.DataClass;

import java.lang.annotation.Retention;

/**
 * KeyEvent that has been verified by the system.
 * The data contained in this class is always a subset of a {@link KeyEvent}. Use this class to
 * check which data has been confirmed by the system to be authentic.
 *
 * Most applications do not need to use this class.
 *
 * {@see android.hardware.input.InputManager#verifyInputEvent}
 */
@DataClass(genHiddenConstructor = true, genEqualsHashCode = true)
public final class VerifiedKeyEvent extends VerifiedInputEvent implements Parcelable {
    private static final String TAG = "VerifiedKeyEvent";

    /** @hide */
    @Retention(SOURCE)
    @IntDef({KeyEvent.ACTION_DOWN, KeyEvent.ACTION_UP})
    public @interface KeyEventAction {};

    /**
     * The action of this key event.  May be either {@link KeyEvent#ACTION_DOWN} or
     * {@link KeyEvent#ACTION_UP}.
     *
     * @see KeyEvent#getAction()
     */
    @KeyEventAction
    private int mAction;

    /**
     * Retrieve the time of the most recent key down event, in the
     * {@link android.os.SystemClock#uptimeMillis} time base, but in nanoseconds. If this
     * is a down event, this will be the same as {@link VerifiedInputEvent#getEventTimeNanos()}.
     *
     * @see KeyEvent#getDownTime()
     */
    @SuppressLint({"MethodNameUnits"})
    private long mDownTimeNanos;

    /**
     * Returns the flags for this key event.
     *
     * @see KeyEvent#getFlags()
     * @see KeyEvent#FLAG_CANCELED
     *
     * @hide
     */
    private int mFlags;

    /**
     * Retrieve the key code of the key event.
     *
     * @see KeyEvent#getKeyCode()
     */
    private int mKeyCode;

    /**
     * Retrieve the hardware key id of this key event. These values are not reliable
     * and vary from device to device.
     *
     * @see KeyEvent#getScanCode()
     */
    private int mScanCode;

    /**
     * <p>Returns the state of the meta keys.</p>
     *
     * @return an integer in which each bit set to 1 represents a pressed meta key
     * @see KeyEvent#getMetaState()
     */
    private int mMetaState;

    /**
     * Retrieve the repeat count of the event.  For key down events, this is the number of times
     * the key has repeated with the first down starting at 0 and counting up from there.
     * For key up events, this is always equal to zero. For multiple key events,
     * this is the number of down/up pairs that have occurred.
     */
    private int mRepeatCount;

    /**
     * Get a specific flag of this key event, if possible. Return null if the flag value could
     * not be checked.
     *
     * @param flag the flag of interest
     * @return Boolean(true) if the key event has the requested flag
     *         Boolean(false) if the key event does not have the requested flag
     *         null if the flag value could not be checked
     *
     * @see KeyEvent#getFlags()
     * @see KeyEvent#FLAG_CANCELED
     */
    public @Nullable Boolean getFlag(int flag) {
        switch(flag) {
            // InputDispatcher only verifies a subset of the KeyEvent flags.
            // These values must be kept in sync with Input.cpp
            case FLAG_CANCELED:
                return (mFlags & flag) != 0;
        }
        return null;
    }

    // The codegen tool doesn't fully support subclasses, since it works on a per-file basis.
    // To modify this file:
    // 1. run codegen on this file
    // 2. edit the constructor signature
    // 3. add the "super" call for constructor that receives a Parcel
    // 4. add the "super" call to the writeToParcel method
    // 5. Update "equals" and "hashcode" methods to include VerifiedInputEvent fields
    // 6. Edit "inputSignatures" to ensure KeyEventAction is properly qualified



    // Code below generated by codegen v1.0.14.
    //
    // DO NOT MODIFY!
    // CHECKSTYLE:OFF Generated code
    //
    // To regenerate run:
    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/VerifiedKeyEvent.java
    //
    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
    //   Settings > Editor > Code Style > Formatter Control
    //@formatter:off


    /**
     * Creates a new VerifiedKeyEvent.
     *
     * @param action
     *   The action of this key event.  May be either {@link KeyEvent#ACTION_DOWN} or
     *   {@link KeyEvent#ACTION_UP}.
     * @param downTimeNanos
     *   Retrieve the time of the most recent key down event, in the
     *   {@link android.os.SystemClock#uptimeMillis} time base, but in nanoseconds. If this
     *   is a down event, this will be the same as {@link VerifiedInputEvent#getEventTimeNanos()}.
     * @param flags
     *   Returns the flags for this key event.
     * @param keyCode
     *   Retrieve the key code of the key event.
     * @param scanCode
     *   Retrieve the hardware key id of this key event. These values are not reliable
     *   and vary from device to device.
     * @param metaState
     *   <p>Returns the state of the meta keys.</p>
     * @param repeatCount
     *   Retrieve the repeat count of the event.  For key down events, this is the number of times
     *   the key has repeated with the first down starting at 0 and counting up from there.
     *   For key up events, this is always equal to zero. For multiple key events,
     *   this is the number of down/up pairs that have occurred.
     * @hide
     */
    @DataClass.Generated.Member
    public VerifiedKeyEvent(
            int deviceId,
            long eventTimeNanos,
            int source,
            int displayId,
            @KeyEventAction int action,
            @SuppressLint({"MethodNameUnits"}) long downTimeNanos,
            int flags,
            int keyCode,
            int scanCode,
            int metaState,
            int repeatCount) {
        super(VERIFIED_KEY, deviceId, eventTimeNanos, source, displayId);
        this.mAction = action;
        com.android.internal.util.AnnotationValidations.validate(
                KeyEventAction.class, null, mAction);
        this.mDownTimeNanos = downTimeNanos;
        com.android.internal.util.AnnotationValidations.validate(
                SuppressLint.class, null, mDownTimeNanos,
                "value", "MethodNameUnits");
        this.mFlags = flags;
        this.mKeyCode = keyCode;
        this.mScanCode = scanCode;
        this.mMetaState = metaState;
        this.mRepeatCount = repeatCount;

        // onConstructed(); // You can define this method to get a callback
    }

    /**
     * The action of this key event.  May be either {@link KeyEvent#ACTION_DOWN} or
     * {@link KeyEvent#ACTION_UP}.
     *
     * @see KeyEvent#getAction()
     */
    @DataClass.Generated.Member
    public @KeyEventAction int getAction() {
        return mAction;
    }

    /**
     * Retrieve the time of the most recent key down event, in the
     * {@link android.os.SystemClock#uptimeMillis} time base, but in nanoseconds. If this
     * is a down event, this will be the same as {@link VerifiedInputEvent#getEventTimeNanos()}.
     *
     * @see KeyEvent#getDownTime()
     */
    @DataClass.Generated.Member
    public @SuppressLint({"MethodNameUnits"}) long getDownTimeNanos() {
        return mDownTimeNanos;
    }

    /**
     * Returns the flags for this key event.
     *
     * @see KeyEvent#getFlags()
     * @see KeyEvent#FLAG_CANCELED
     * @hide
     */
    @DataClass.Generated.Member
    public int getFlags() {
        return mFlags;
    }

    /**
     * Retrieve the key code of the key event.
     *
     * @see KeyEvent#getKeyCode()
     */
    @DataClass.Generated.Member
    public int getKeyCode() {
        return mKeyCode;
    }

    /**
     * Retrieve the hardware key id of this key event. These values are not reliable
     * and vary from device to device.
     *
     * @see KeyEvent#getScanCode()
     */
    @DataClass.Generated.Member
    public int getScanCode() {
        return mScanCode;
    }

    /**
     * <p>Returns the state of the meta keys.</p>
     *
     * @return an integer in which each bit set to 1 represents a pressed meta key
     * @see KeyEvent#getMetaState()
     */
    @DataClass.Generated.Member
    public int getMetaState() {
        return mMetaState;
    }

    /**
     * Retrieve the repeat count of the event.  For key down events, this is the number of times
     * the key has repeated with the first down starting at 0 and counting up from there.
     * For key up events, this is always equal to zero. For multiple key events,
     * this is the number of down/up pairs that have occurred.
     */
    @DataClass.Generated.Member
    public int getRepeatCount() {
        return mRepeatCount;
    }

    @Override
    @DataClass.Generated.Member
    public boolean equals(@Nullable Object o) {
        // You can override field equality logic by defining either of the methods like:
        // boolean fieldNameEquals(VerifiedKeyEvent other) { ... }
        // boolean fieldNameEquals(FieldType otherValue) { ... }

        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        @SuppressWarnings("unchecked")
        VerifiedKeyEvent that = (VerifiedKeyEvent) o;
        //noinspection PointlessBooleanExpression
        return true
                && getDeviceId() == that.getDeviceId()
                && getEventTimeNanos() == that.getEventTimeNanos()
                && getSource() == that.getSource()
                && getDisplayId() == that.getDisplayId()
                && mAction == that.mAction
                && mDownTimeNanos == that.mDownTimeNanos
                && mFlags == that.mFlags
                && mKeyCode == that.mKeyCode
                && mScanCode == that.mScanCode
                && mMetaState == that.mMetaState
                && mRepeatCount == that.mRepeatCount;
    }

    @Override
    @DataClass.Generated.Member
    public int hashCode() {
        // You can override field hashCode logic by defining methods like:
        // int fieldNameHashCode() { ... }

        int _hash = 1;
        _hash = 31 * _hash + getDeviceId();
        _hash = 31 * _hash + Long.hashCode(getEventTimeNanos());
        _hash = 31 * _hash + getSource();
        _hash = 31 * _hash + getDisplayId();
        _hash = 31 * _hash + mAction;
        _hash = 31 * _hash + Long.hashCode(mDownTimeNanos);
        _hash = 31 * _hash + mFlags;
        _hash = 31 * _hash + mKeyCode;
        _hash = 31 * _hash + mScanCode;
        _hash = 31 * _hash + mMetaState;
        _hash = 31 * _hash + mRepeatCount;
        return _hash;
    }

    @Override
    @DataClass.Generated.Member
    public void writeToParcel(@android.annotation.NonNull Parcel dest, int flags) {
        // You can override field parcelling by defining methods like:
        // void parcelFieldName(Parcel dest, int flags) { ... }
        super.writeToParcel(dest, flags);
        dest.writeInt(mAction);
        dest.writeLong(mDownTimeNanos);
        dest.writeInt(mFlags);
        dest.writeInt(mKeyCode);
        dest.writeInt(mScanCode);
        dest.writeInt(mMetaState);
        dest.writeInt(mRepeatCount);
    }

    @Override
    @DataClass.Generated.Member
    public int describeContents() { return 0; }

    /** @hide */
    @SuppressWarnings({"unchecked", "RedundantCast"})
    @DataClass.Generated.Member
    /* package-private */ VerifiedKeyEvent(@android.annotation.NonNull Parcel in) {
        // You can override field unparcelling by defining methods like:
        // static FieldType unparcelFieldName(Parcel in) { ... }
        super(in, VERIFIED_KEY);
        int action = in.readInt();
        long downTimeNanos = in.readLong();
        int flags = in.readInt();
        int keyCode = in.readInt();
        int scanCode = in.readInt();
        int metaState = in.readInt();
        int repeatCount = in.readInt();

        this.mAction = action;
        com.android.internal.util.AnnotationValidations.validate(
                KeyEventAction.class, null, mAction);
        this.mDownTimeNanos = downTimeNanos;
        com.android.internal.util.AnnotationValidations.validate(
                SuppressLint.class, null, mDownTimeNanos,
                "value", "MethodNameUnits");
        this.mFlags = flags;
        this.mKeyCode = keyCode;
        this.mScanCode = scanCode;
        this.mMetaState = metaState;
        this.mRepeatCount = repeatCount;

        // onConstructed(); // You can define this method to get a callback
    }

    @DataClass.Generated.Member
    public static final @android.annotation.NonNull Parcelable.Creator<VerifiedKeyEvent> CREATOR
            = new Parcelable.Creator<VerifiedKeyEvent>() {
        @Override
        public VerifiedKeyEvent[] newArray(int size) {
            return new VerifiedKeyEvent[size];
        }

        @Override
        public VerifiedKeyEvent createFromParcel(@android.annotation.NonNull Parcel in) {
            return new VerifiedKeyEvent(in);
        }
    };

    @DataClass.Generated(
            time = 1581107066890L,
            codegenVersion = "1.0.14",
            sourceFile = "frameworks/base/core/java/android/view/VerifiedKeyEvent.java",
            inputSignatures = "private static final  java.lang.String TAG\nprivate @android.view.VerifiedKeyEvent.KeyEventAction int mAction\nprivate @android.annotation.SuppressLint({\"MethodNameUnits\"}) long mDownTimeNanos\nprivate  int mFlags\nprivate  int mKeyCode\nprivate  int mScanCode\nprivate  int mMetaState\nprivate  int mRepeatCount\npublic @android.annotation.Nullable java.lang.Boolean getFlag(int)\nclass VerifiedKeyEvent extends android.view.VerifiedInputEvent implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true, genEqualsHashCode=true)")
    @Deprecated
    private void __metadata() {}


    //@formatter:on
    // End of generated code

}
