/*
 * Copyright (C) 2018 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.util.ArrayMap;
import android.util.ArraySet;

import java.util.Arrays;

/**
 * Struct to track relevant packages and notifications for a userid's foreground services.
 */
class ForegroundServicesUserState {
    // shelf life of foreground services before they go bad
    private static final long FG_SERVICE_GRACE_MILLIS = 5000;

    private String[] mRunning = null;
    private long mServiceStartTime = 0;
    // package -> sufficiently important posted notification keys
    private ArrayMap<String, ArraySet<String>> mImportantNotifications = new ArrayMap<>(1);
    // package -> standard layout posted notification keys
    private ArrayMap<String, ArraySet<String>> mStandardLayoutNotifications = new ArrayMap<>(1);

    // package -> app ops
    private ArrayMap<String, ArraySet<Integer>> mAppOps = new ArrayMap<>(1);

    public void setRunningServices(String[] pkgs, long serviceStartTime) {
        mRunning = pkgs != null ? Arrays.copyOf(pkgs, pkgs.length) : null;
        mServiceStartTime = serviceStartTime;
    }

    public void addOp(String pkg, int op) {
        if (mAppOps.get(pkg) == null) {
            mAppOps.put(pkg, new ArraySet<>(3));
        }
        mAppOps.get(pkg).add(op);
    }

    public boolean removeOp(String pkg, int op) {
        final boolean found;
        final ArraySet<Integer> keys = mAppOps.get(pkg);
        if (keys == null) {
            found = false;
        } else {
            found = keys.remove(op);
            if (keys.size() == 0) {
                mAppOps.remove(pkg);
            }
        }
        return found;
    }

    public void addImportantNotification(String pkg, String key) {
        addNotification(mImportantNotifications, pkg, key);
    }

    public boolean removeImportantNotification(String pkg, String key) {
        return removeNotification(mImportantNotifications, pkg, key);
    }

    public void addStandardLayoutNotification(String pkg, String key) {
        addNotification(mStandardLayoutNotifications, pkg, key);
    }

    public boolean removeStandardLayoutNotification(String pkg, String key) {
        return removeNotification(mStandardLayoutNotifications, pkg, key);
    }

    public boolean removeNotification(String pkg, String key) {
        boolean removed = false;
        removed |= removeImportantNotification(pkg, key);
        removed |= removeStandardLayoutNotification(pkg, key);
        return removed;
    }

    public void addNotification(ArrayMap<String, ArraySet<String>> map, String pkg,
            String key) {
        if (map.get(pkg) == null) {
            map.put(pkg, new ArraySet<>());
        }
        map.get(pkg).add(key);
    }

    public boolean removeNotification(ArrayMap<String, ArraySet<String>> map,
            String pkg, String key) {
        final boolean found;
        final ArraySet<String> keys = map.get(pkg);
        if (keys == null) {
            found = false;
        } else {
            found = keys.remove(key);
            if (keys.size() == 0) {
                map.remove(pkg);
            }
        }
        return found;
    }

    public boolean isDisclosureNeeded() {
        if (mRunning != null
                && System.currentTimeMillis() - mServiceStartTime
                >= FG_SERVICE_GRACE_MILLIS) {

            for (String pkg : mRunning) {
                final ArraySet<String> set = mImportantNotifications.get(pkg);
                if (set == null || set.size() == 0) {
                    return true;
                }
            }
        }
        return false;
    }

    public ArraySet<Integer> getFeatures(String pkg) {
        return mAppOps.get(pkg);
    }

    public String getStandardLayoutKey(String pkg) {
        final ArraySet<String> set = mStandardLayoutNotifications.get(pkg);
        if (set == null || set.size() == 0) {
            return null;
        }
        return set.valueAt(0);
    }

    @Override
    public String toString() {
        return "UserServices{"
                + "mRunning=" + Arrays.toString(mRunning)
                + ", mServiceStartTime=" + mServiceStartTime
                + ", mImportantNotifications=" + mImportantNotifications
                + ", mStandardLayoutNotifications=" + mStandardLayoutNotifications
                + '}';
    }
}
