/*
 * 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 com.android.settings.fuelgauge.anomaly;

import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.IntDef;
import android.text.TextUtils;

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

/**
 * Data that represents an app has been detected as anomaly. It contains
 *
 * 1. Basic information of the app(i.e. uid, package name)
 * 2. Type of anomaly
 * 3. Data that has been detected as anomaly(i.e wakelock time)
 */
public class Anomaly implements Parcelable {
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({AnomalyType.WAKE_LOCK,
            AnomalyType.WAKEUP_ALARM,
            AnomalyType.BLUETOOTH_SCAN})
    public @interface AnomalyType {
        int WAKE_LOCK = 0;
        int WAKEUP_ALARM = 1;
        int BLUETOOTH_SCAN = 2;
    }

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({AnomalyActionType.FORCE_STOP,
            AnomalyActionType.BACKGROUND_CHECK,
            AnomalyActionType.LOCATION_CHECK,
            AnomalyActionType.STOP_AND_BACKGROUND_CHECK})
    public @interface AnomalyActionType {
        int FORCE_STOP = 0;
        int BACKGROUND_CHECK = 1;
        int LOCATION_CHECK = 2;
        int STOP_AND_BACKGROUND_CHECK = 3;
    }

    @AnomalyType
    public static final int[] ANOMALY_TYPE_LIST = {
            AnomalyType.WAKE_LOCK,
            AnomalyType.WAKEUP_ALARM,
            AnomalyType.BLUETOOTH_SCAN};

    /**
     * Type of this this anomaly
     */
    public final int type;
    public final int uid;
    public final int targetSdkVersion;
    public final long wakelockTimeMs;
    public final long bluetoothScanningTimeMs;
    public final int wakeupAlarmCount;
    /**
     * {@code true} if background restriction is enabled
     *
     * @see android.app.AppOpsManager.OP_RUN_IN_BACKGROUND
     */
    public final boolean backgroundRestrictionEnabled;
    /**
     * Display name of this anomaly, usually it is the app name
     */
    public final CharSequence displayName;
    public final String packageName;

    private Anomaly(Builder builder) {
        type = builder.mType;
        uid = builder.mUid;
        displayName = builder.mDisplayName;
        packageName = builder.mPackageName;
        wakelockTimeMs = builder.mWakeLockTimeMs;
        targetSdkVersion = builder.mTargetSdkVersion;
        backgroundRestrictionEnabled = builder.mBgRestrictionEnabled;
        bluetoothScanningTimeMs = builder.mBluetoothScanningTimeMs;
        wakeupAlarmCount = builder.mWakeupAlarmCount;
    }

    private Anomaly(Parcel in) {
        type = in.readInt();
        uid = in.readInt();
        displayName = in.readCharSequence();
        packageName = in.readString();
        wakelockTimeMs = in.readLong();
        targetSdkVersion = in.readInt();
        backgroundRestrictionEnabled = in.readBoolean();
        wakeupAlarmCount = in.readInt();
        bluetoothScanningTimeMs = in.readLong();
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(type);
        dest.writeInt(uid);
        dest.writeCharSequence(displayName);
        dest.writeString(packageName);
        dest.writeLong(wakelockTimeMs);
        dest.writeInt(targetSdkVersion);
        dest.writeBoolean(backgroundRestrictionEnabled);
        dest.writeInt(wakeupAlarmCount);
        dest.writeLong(bluetoothScanningTimeMs);
    }

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

        Anomaly other = (Anomaly) obj;
        return type == other.type
                && uid == other.uid
                && wakelockTimeMs == other.wakelockTimeMs
                && TextUtils.equals(displayName, other.displayName)
                && TextUtils.equals(packageName, other.packageName)
                && targetSdkVersion == other.targetSdkVersion
                && backgroundRestrictionEnabled == other.backgroundRestrictionEnabled
                && wakeupAlarmCount == other.wakeupAlarmCount
                && bluetoothScanningTimeMs == other.bluetoothScanningTimeMs;
    }

    @Override
    public int hashCode() {
        return Objects.hash(type, uid, displayName, packageName, wakelockTimeMs, targetSdkVersion,
                backgroundRestrictionEnabled, wakeupAlarmCount, bluetoothScanningTimeMs);
    }

    @Override
    public String toString() {
        return "type=" + toAnomalyTypeText(type) + " uid=" + uid + " package=" + packageName +
                " displayName=" + displayName + " wakelockTimeMs=" + wakelockTimeMs +
                " wakeupAlarmCount=" + wakeupAlarmCount + " bluetoothTimeMs="
                + bluetoothScanningTimeMs;
    }

    private String toAnomalyTypeText(@AnomalyType int type) {
        switch (type) {
            case AnomalyType.WAKEUP_ALARM:
                return "wakeupAlarm";
            case AnomalyType.WAKE_LOCK:
                return "wakelock";
            case AnomalyType.BLUETOOTH_SCAN:
                return "unoptimizedBluetoothScan";
        }

        return "";
    }

    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        public Anomaly createFromParcel(Parcel in) {
            return new Anomaly(in);
        }

        public Anomaly[] newArray(int size) {
            return new Anomaly[size];
        }
    };

    public static final class Builder {
        @AnomalyType
        private int mType;
        private int mUid;
        private int mTargetSdkVersion;
        private CharSequence mDisplayName;
        private String mPackageName;
        private long mWakeLockTimeMs;
        private boolean mBgRestrictionEnabled;
        private int mWakeupAlarmCount;
        private long mBluetoothScanningTimeMs;

        public Builder setType(@AnomalyType int type) {
            mType = type;
            return this;
        }

        public Builder setUid(int uid) {
            mUid = uid;
            return this;
        }

        public Builder setDisplayName(CharSequence displayName) {
            mDisplayName = displayName;
            return this;
        }

        public Builder setPackageName(String packageName) {
            mPackageName = packageName;
            return this;
        }

        public Builder setWakeLockTimeMs(long wakeLockTimeMs) {
            mWakeLockTimeMs = wakeLockTimeMs;
            return this;
        }

        public Builder setTargetSdkVersion(int targetSdkVersion) {
            mTargetSdkVersion = targetSdkVersion;
            return this;
        }

        public Builder setBackgroundRestrictionEnabled(boolean bgRestrictionEnabled) {
            mBgRestrictionEnabled = bgRestrictionEnabled;
            return this;
        }

        public Builder setWakeupAlarmCount(int wakeupAlarmCount) {
            mWakeupAlarmCount = wakeupAlarmCount;
            return this;
        }

        public Builder setBluetoothScanningTimeMs(long bluetoothScanningTimeMs) {
            mBluetoothScanningTimeMs = bluetoothScanningTimeMs;
            return this;
        }

        public Anomaly build() {
            return new Anomaly(this);
        }
    }
}
