/**
 * Copyright (C) 2014 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.hardware.soundtrigger;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.os.Parcelable;
import android.util.ArraySet;

import com.android.internal.util.DataClass;

import java.util.Locale;
import java.util.Set;

/**
 * A Voice Keyphrase metadata read from the enrollment application.
 *
 * @hide
 */
@TestApi
@DataClass(
        genEqualsHashCode = true,
        genToString = true,
        genConstructor = false,
        genHiddenConstDefs = true)
public final class KeyphraseMetadata implements Parcelable {
    private final int mId;
    @NonNull
    private final String mKeyphrase;
    @NonNull
    private final ArraySet<Locale> mSupportedLocales;
    private final int mRecognitionModeFlags;

    public KeyphraseMetadata(int id, @NonNull String keyphrase,
            @NonNull Set<Locale> supportedLocales, int recognitionModeFlags) {
        this.mId = id;
        this.mKeyphrase = keyphrase;
        this.mSupportedLocales = new ArraySet<>(supportedLocales);
        this.mRecognitionModeFlags = recognitionModeFlags;
    }

    public int getId() {
        return mId;
    }

    @NonNull
    public String getKeyphrase() {
        return mKeyphrase;
    }

    @NonNull
    public Set<Locale> getSupportedLocales() {
        return mSupportedLocales;
    }

    public int getRecognitionModeFlags() {
        return mRecognitionModeFlags;
    }

    /**
     * @return Indicates if we support the given phrase.
     */
    public boolean supportsPhrase(@Nullable String phrase) {
        return getKeyphrase().isEmpty() || getKeyphrase().equalsIgnoreCase(phrase);
    }

    /**
     * @return Indicates if we support the given locale.
     */
    public boolean supportsLocale(@Nullable Locale locale) {
        return getSupportedLocales().isEmpty() || getSupportedLocales().contains(locale);
    }




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


    @Override
    @DataClass.Generated.Member
    public String toString() {
        // You can override field toString logic by defining methods like:
        // String fieldNameToString() { ... }

        return "KeyphraseMetadata { " +
                "id = " + mId + ", " +
                "keyphrase = " + mKeyphrase + ", " +
                "supportedLocales = " + mSupportedLocales + ", " +
                "recognitionModeFlags = " + mRecognitionModeFlags +
        " }";
    }

    @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(KeyphraseMetadata other) { ... }
        // boolean fieldNameEquals(FieldType otherValue) { ... }

        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        @SuppressWarnings("unchecked")
        KeyphraseMetadata that = (KeyphraseMetadata) o;
        //noinspection PointlessBooleanExpression
        return true
                && mId == that.mId
                && java.util.Objects.equals(mKeyphrase, that.mKeyphrase)
                && java.util.Objects.equals(mSupportedLocales, that.mSupportedLocales)
                && mRecognitionModeFlags == that.mRecognitionModeFlags;
    }

    @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 + mId;
        _hash = 31 * _hash + java.util.Objects.hashCode(mKeyphrase);
        _hash = 31 * _hash + java.util.Objects.hashCode(mSupportedLocales);
        _hash = 31 * _hash + mRecognitionModeFlags;
        return _hash;
    }

    @Override
    @DataClass.Generated.Member
    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
        // You can override field parcelling by defining methods like:
        // void parcelFieldName(Parcel dest, int flags) { ... }

        dest.writeInt(mId);
        dest.writeString(mKeyphrase);
        dest.writeArraySet(mSupportedLocales);
        dest.writeInt(mRecognitionModeFlags);
    }

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

    /** @hide */
    @SuppressWarnings({"unchecked", "RedundantCast"})
    @DataClass.Generated.Member
    /* package-private */ KeyphraseMetadata(@NonNull android.os.Parcel in) {
        // You can override field unparcelling by defining methods like:
        // static FieldType unparcelFieldName(Parcel in) { ... }

        int id = in.readInt();
        String keyphrase = in.readString();
        ArraySet<Locale> supportedLocales = (ArraySet) in.readArraySet(null);
        int recognitionModeFlags = in.readInt();

        this.mId = id;
        this.mKeyphrase = keyphrase;
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, mKeyphrase);
        this.mSupportedLocales = supportedLocales;
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, mSupportedLocales);
        this.mRecognitionModeFlags = recognitionModeFlags;

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

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

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

    @DataClass.Generated(
            time = 1586191622057L,
            codegenVersion = "1.0.15",
            sourceFile = "frameworks/base/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java",
            inputSignatures = "private final  int mId\nprivate final @android.annotation.NonNull java.lang.String mKeyphrase\nprivate final @android.annotation.NonNull android.util.ArraySet<java.util.Locale> mSupportedLocales\nprivate final  int mRecognitionModeFlags\npublic  int getId()\npublic @android.annotation.NonNull java.lang.String getKeyphrase()\npublic @android.annotation.NonNull java.util.Set<java.util.Locale> getSupportedLocales()\npublic  int getRecognitionModeFlags()\npublic  boolean supportsPhrase(java.lang.String)\npublic  boolean supportsLocale(java.util.Locale)\nclass KeyphraseMetadata extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genConstructor=false, genHiddenConstDefs=true)")
    @Deprecated
    private void __metadata() {}


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

}
