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

import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.os.Handler;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.util.ArraySet;
import android.util.SparseArray;

import com.android.internal.messages.nano.SystemMessageProto;
import com.android.systemui.appops.AppOpsController;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.util.Assert;

import javax.inject.Inject;
import javax.inject.Singleton;

/**
 * Tracks state of foreground services and notifications related to foreground services per user.
 */
@Singleton
public class ForegroundServiceController {
    public static final int[] APP_OPS = new int[] {AppOpsManager.OP_CAMERA,
            AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
            AppOpsManager.OP_RECORD_AUDIO,
            AppOpsManager.OP_COARSE_LOCATION,
            AppOpsManager.OP_FINE_LOCATION};

    private final SparseArray<ForegroundServicesUserState> mUserServices = new SparseArray<>();
    private final Object mMutex = new Object();
    private final NotificationEntryManager mEntryManager;
    private final Handler mMainHandler;

    @Inject
    public ForegroundServiceController(NotificationEntryManager entryManager,
            AppOpsController appOpsController, @Main Handler mainHandler) {
        mEntryManager = entryManager;
        mMainHandler = mainHandler;
        appOpsController.addCallback(APP_OPS, (code, uid, packageName, active) -> {
            mMainHandler.post(() -> {
                onAppOpChanged(code, uid, packageName, active);
            });
        });
    }

    /**
     * @return true if this user has services missing notifications and therefore needs a
     * disclosure notification.
     */
    public boolean isDisclosureNeededForUser(int userId) {
        synchronized (mMutex) {
            final ForegroundServicesUserState services = mUserServices.get(userId);
            if (services == null) return false;
            return services.isDisclosureNeeded();
        }
    }

    /**
     * @return true if this user/pkg has a missing or custom layout notification and therefore needs
     * a disclosure notification for system alert windows.
     */
    public boolean isSystemAlertWarningNeeded(int userId, String pkg) {
        synchronized (mMutex) {
            final ForegroundServicesUserState services = mUserServices.get(userId);
            if (services == null) return false;
            return services.getStandardLayoutKey(pkg) == null;
        }
    }

    /**
     * Returns the key of the foreground service from this package using the standard template,
     * if one exists.
     */
    @Nullable
    public String getStandardLayoutKey(int userId, String pkg) {
        synchronized (mMutex) {
            final ForegroundServicesUserState services = mUserServices.get(userId);
            if (services == null) return null;
            return services.getStandardLayoutKey(pkg);
        }
    }

    /**
     * Gets active app ops for this user and package
     */
    @Nullable
    public ArraySet<Integer> getAppOps(int userId, String pkg) {
        synchronized (mMutex) {
            final ForegroundServicesUserState services = mUserServices.get(userId);
            if (services == null) {
                return null;
            }
            return services.getFeatures(pkg);
        }
    }

    /**
     * Records active app ops and updates the app op for the pending or visible notifications
     * with the given parameters.
     * App Ops are stored in FSC in addition to NotificationEntry in case they change before we
     * have a notification to tag.
     * @param appOpCode code for appOp to add/remove
     * @param uid of user the notification is sent to
     * @param packageName package that created the notification
     * @param active whether the appOpCode is active or not
     */
    void onAppOpChanged(int appOpCode, int uid, String packageName, boolean active) {
        Assert.isMainThread();

        int userId = UserHandle.getUserId(uid);
        // Record active app ops
        synchronized (mMutex) {
            ForegroundServicesUserState userServices = mUserServices.get(userId);
            if (userServices == null) {
                userServices = new ForegroundServicesUserState();
                mUserServices.put(userId, userServices);
            }
            if (active) {
                userServices.addOp(packageName, appOpCode);
            } else {
                userServices.removeOp(packageName, appOpCode);
            }
        }

        // TODO: (b/145659174) remove when moving to NewNotifPipeline. Replaced by
        //  ForegroundCoordinator
        // Update appOp if there's an associated pending or visible notification:
        final String foregroundKey = getStandardLayoutKey(userId, packageName);
        if (foregroundKey != null) {
            final NotificationEntry entry = mEntryManager.getPendingOrActiveNotif(foregroundKey);
            if (entry != null
                    && uid == entry.getSbn().getUid()
                    && packageName.equals(entry.getSbn().getPackageName())) {
                boolean changed;
                synchronized (entry.mActiveAppOps) {
                    if (active) {
                        changed = entry.mActiveAppOps.add(appOpCode);
                    } else {
                        changed = entry.mActiveAppOps.remove(appOpCode);
                    }
                }
                if (changed) {
                    mEntryManager.updateNotifications("appOpChanged pkg=" + packageName);
                }
            }
        }
    }

    /**
     * Looks up the {@link ForegroundServicesUserState} for the given {@code userId}, then performs
     * the given {@link UserStateUpdateCallback} on it.  If no state exists for the user ID, creates
     * a new one if {@code createIfNotFound} is true, then performs the update on the new state.
     * If {@code createIfNotFound} is false, no update is performed.
     *
     * @return false if no user state was found and none was created; true otherwise.
     */
    boolean updateUserState(int userId,
            UserStateUpdateCallback updateCallback,
            boolean createIfNotFound) {
        synchronized (mMutex) {
            ForegroundServicesUserState userState = mUserServices.get(userId);
            if (userState == null) {
                if (createIfNotFound) {
                    userState = new ForegroundServicesUserState();
                    mUserServices.put(userId, userState);
                } else {
                    return false;
                }
            }
            return updateCallback.updateUserState(userState);
        }
    }

    /**
     * @return true if {@code sbn} is the system-provided disclosure notification containing the
     * list of running foreground services.
     */
    public boolean isDisclosureNotification(StatusBarNotification sbn) {
        return sbn.getId() == SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES
                && sbn.getTag() == null
                && sbn.getPackageName().equals("android");
    }

    /**
     * @return true if sbn is one of the window manager "drawing over other apps" notifications
     */
    public boolean isSystemAlertNotification(StatusBarNotification sbn) {
        return sbn.getPackageName().equals("android")
                && sbn.getTag() != null
                && sbn.getTag().contains("AlertWindowNotification");
    }

    /**
     * Callback provided to {@link #updateUserState(int, UserStateUpdateCallback, boolean)}
     * to perform the update.
     */
    interface UserStateUpdateCallback {
        /**
         * Perform update operations on the provided {@code userState}.
         *
         * @return true if the update succeeded.
         */
        boolean updateUserState(ForegroundServicesUserState userState);

        /** Called if the state was not found and was not created. */
        default void userStateNotFound(int userId) {
        }
    }
}
