/*
 * Copyright (C) 2019 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.companion;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;

import com.android.internal.util.DataClass;

import java.util.Objects;

/**
 * A record indicating that a device with a given address was confirmed by the user to be
 * associated to a given companion app
 *
 * @hide
 */
@DataClass(genEqualsHashCode = true, genToString = true)
public class Association implements Parcelable {

    public final int userId;
    public final @NonNull String deviceAddress;
    public final @NonNull String companionAppPackage;




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


    @DataClass.Generated.Member
    public Association(
            int userId,
            @NonNull String deviceAddress,
            @NonNull String companionAppPackage) {
        this.userId = userId;
        this.deviceAddress = deviceAddress;
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, deviceAddress);
        this.companionAppPackage = companionAppPackage;
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, companionAppPackage);

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

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

        return "Association { " +
                "userId = " + userId + ", " +
                "deviceAddress = " + deviceAddress + ", " +
                "companionAppPackage = " + companionAppPackage +
        " }";
    }

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

        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        @SuppressWarnings("unchecked")
        Association that = (Association) o;
        //noinspection PointlessBooleanExpression
        return true
                && userId == that.userId
                && Objects.equals(deviceAddress, that.deviceAddress)
                && Objects.equals(companionAppPackage, that.companionAppPackage);
    }

    @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 + userId;
        _hash = 31 * _hash + Objects.hashCode(deviceAddress);
        _hash = 31 * _hash + Objects.hashCode(companionAppPackage);
        return _hash;
    }

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

        dest.writeInt(userId);
        dest.writeString(deviceAddress);
        dest.writeString(companionAppPackage);
    }

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

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

        int _userId = in.readInt();
        String _deviceAddress = in.readString();
        String _companionAppPackage = in.readString();

        this.userId = _userId;
        this.deviceAddress = _deviceAddress;
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, deviceAddress);
        this.companionAppPackage = _companionAppPackage;
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, companionAppPackage);

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

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

        @Override
        public Association createFromParcel(@NonNull Parcel in) {
            return new Association(in);
        }
    };

    @DataClass.Generated(
            time = 1573767103332L,
            codegenVersion = "1.0.13",
            sourceFile = "frameworks/base/core/java/android/companion/Association.java",
            inputSignatures = "public final  int userId\npublic final @android.annotation.NonNull java.lang.String deviceAddress\npublic final @android.annotation.NonNull java.lang.String companionAppPackage\nclass Association extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true)")
    @Deprecated
    private void __metadata() {}


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

}
