/*
 * 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;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.PowerManager;
import android.util.Log;

import androidx.annotation.IntDef;
import androidx.annotation.VisibleForTesting;

import com.android.settings.Utils;
import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;

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

/**
 * Use this broadcastReceiver to listen to the battery change, and it will invoke
 * {@link OnBatteryChangedListener} if any of the following has been changed:
 *
 * 1. Battery level(e.g. 100%->99%)
 * 2. Battery status(e.g. plugged->unplugged)
 * 3. Battery saver(e.g. off->on)
 * 4. Battery health(e.g. good->overheat)
 */
public class BatteryBroadcastReceiver extends BroadcastReceiver {

    private static final String TAG = "BatteryBroadcastRcvr";
    /**
     * Callback when the following has been changed:
     *
     * Battery level(e.g. 100%->99%)
     * Battery status(e.g. plugged->unplugged)
     * Battery saver(e.g. off->on)
     * Battery health(e.g. good->overheat)
     */
    public interface OnBatteryChangedListener {
        void onBatteryChanged(@BatteryUpdateType int type);
    }

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({BatteryUpdateType.MANUAL,
            BatteryUpdateType.BATTERY_LEVEL,
            BatteryUpdateType.BATTERY_SAVER,
            BatteryUpdateType.BATTERY_STATUS,
            BatteryUpdateType.BATTERY_HEALTH,
            BatteryUpdateType.BATTERY_NOT_PRESENT})
    public @interface BatteryUpdateType {
        int MANUAL = 0;
        int BATTERY_LEVEL = 1;
        int BATTERY_SAVER = 2;
        int BATTERY_STATUS = 3;
        int BATTERY_HEALTH = 4;
        int BATTERY_NOT_PRESENT = 5;
    }

    @VisibleForTesting
    String mBatteryLevel;
    @VisibleForTesting
    String mBatteryStatus;
    @VisibleForTesting
    int mBatteryHealth;
    private OnBatteryChangedListener mBatteryListener;
    private Context mContext;

    public BatteryBroadcastReceiver(Context context) {
        mContext = context;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        updateBatteryStatus(intent, false /* forceUpdate */);
    }

    public void setBatteryChangedListener(OnBatteryChangedListener lsn) {
        mBatteryListener = lsn;
    }

    public void register() {
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);

        final Intent intent = mContext.registerReceiver(this, intentFilter);
        updateBatteryStatus(intent, true /* forceUpdate */);
    }

    public void unRegister() {
        mContext.unregisterReceiver(this);
    }

    private void updateBatteryStatus(Intent intent, boolean forceUpdate) {
        if (intent != null && mBatteryListener != null) {
            if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
                final String batteryLevel = Utils.getBatteryPercentage(intent);
                final String batteryStatus = Utils.getBatteryStatus(mContext, intent);
                final int batteryHealth = intent.getIntExtra(
                        BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_UNKNOWN);
                if (!Utils.isBatteryPresent(intent)) {
                    Log.w(TAG, "Problem reading the battery meter.");
                    mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_NOT_PRESENT);
                } else if (forceUpdate) {
                    mBatteryListener.onBatteryChanged(BatteryUpdateType.MANUAL);
                } else if (batteryHealth != mBatteryHealth) {
                    mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_HEALTH);
                } else if(!batteryLevel.equals(mBatteryLevel)) {
                    mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_LEVEL);
                } else if (!batteryStatus.equals(mBatteryStatus)) {
                    mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_STATUS);
                }
                mBatteryLevel = batteryLevel;
                mBatteryStatus = batteryStatus;
                mBatteryHealth = batteryHealth;
            } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(intent.getAction())) {
                mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_SAVER);
            }
        }
        BatteryFixSlice.updateBatteryTipAvailabilityCache(mContext);
    }
}