/**
 * Copyright (C) 2016 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.server.vr;

import android.annotation.NonNull;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.content.PackageMonitor;
import com.android.server.vr.SettingsObserver.SettingChangeListener;

import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
 * Detects changes in packages, settings, and current users that may affect whether components
 * implementing a given service can be run.
 *
 * @hide
 */
public class EnabledComponentsObserver implements SettingChangeListener {

    private static final String TAG = EnabledComponentsObserver.class.getSimpleName();
    private static final String ENABLED_SERVICES_SEPARATOR = ":";

    public static final int NO_ERROR = 0;
    public static final int DISABLED = -1;
    public static final int NOT_INSTALLED = -2;

    private final Object mLock;
    private final Context mContext;
    private final String mSettingName;
    private final String mServiceName;
    private final String mServicePermission;
    private final SparseArray<ArraySet<ComponentName>> mInstalledSet = new SparseArray<>();
    private final SparseArray<ArraySet<ComponentName>> mEnabledSet = new SparseArray<>();
    private final Set<EnabledComponentChangeListener> mEnabledComponentListeners = new ArraySet<>();

    /**
     * Implement this to receive callbacks when relevant changes to the allowed components occur.
     */
    public interface EnabledComponentChangeListener {

        /**
         * Called when a change in the allowed components occurs.
         */
        void onEnabledComponentChanged();
    }

    private EnabledComponentsObserver(@NonNull Context context, @NonNull String settingName,
            @NonNull String servicePermission, @NonNull String serviceName, @NonNull Object lock,
            @NonNull Collection<EnabledComponentChangeListener> listeners) {
        mLock = lock;
        mContext = context;
        mSettingName = settingName;
        mServiceName = serviceName;
        mServicePermission = servicePermission;
        mEnabledComponentListeners.addAll(listeners);
    }

    /**
     * Create a EnabledComponentObserver instance.
     *
     * @param context the context to query for changes.
     * @param handler a handler to receive lifecycle events from system services on.
     * @param settingName the name of a setting to monitor for a list of enabled components.
     * @param looper a {@link Looper} to use for receiving package callbacks.
     * @param servicePermission the permission required by the components to be bound.
     * @param serviceName the intent action implemented by the tracked components.
     * @param lock a lock object used to guard instance state in all callbacks and method calls.
     * @return an EnableComponentObserver instance.
     */
    public static EnabledComponentsObserver build(@NonNull Context context,
            @NonNull Handler handler, @NonNull String settingName, @NonNull Looper looper,
            @NonNull String servicePermission, @NonNull String serviceName,
            @NonNull final Object lock,
            @NonNull Collection<EnabledComponentChangeListener> listeners) {

        SettingsObserver s = SettingsObserver.build(context, handler, settingName);

        final EnabledComponentsObserver o = new EnabledComponentsObserver(context, settingName,
                servicePermission, serviceName, lock, listeners);

        PackageMonitor packageMonitor = new PackageMonitor() {
            @Override
            public void onSomePackagesChanged() {
                o.onPackagesChanged();

            }

            @Override
            public void onPackageDisappeared(String packageName, int reason) {
                o.onPackagesChanged();

            }

            @Override
            public void onPackageModified(String packageName) {
                o.onPackagesChanged();

            }

            @Override
            public boolean onHandleForceStop(Intent intent, String[] packages, int uid,
                    boolean doit) {
                o.onPackagesChanged();

                return super.onHandleForceStop(intent, packages, uid, doit);
            }
        };

        packageMonitor.register(context, looper, UserHandle.ALL, true);

        s.addListener(o);

        return o;

    }

    public void onPackagesChanged() {
        rebuildAll();
    }

    @Override
    public void onSettingChanged() {
        rebuildAll();
    }

    @Override
    public void onSettingRestored(String prevValue, String newValue, int userId) {
        rebuildAll();
    }

    public void onUsersChanged() {
        rebuildAll();
    }

    /**
     * Rebuild the sets of allowed components for each current user profile.
     */
    public void rebuildAll() {
        synchronized (mLock) {
            mInstalledSet.clear();
            mEnabledSet.clear();
            final int[] userIds = getCurrentProfileIds();
            for (int i : userIds) {
                ArraySet<ComponentName> implementingPackages = loadComponentNamesForUser(i);
                ArraySet<ComponentName> packagesFromSettings =
                        loadComponentNamesFromSetting(mSettingName, i);
                packagesFromSettings.retainAll(implementingPackages);

                mInstalledSet.put(i, implementingPackages);
                mEnabledSet.put(i, packagesFromSettings);

            }
        }
        sendSettingChanged();
    }

    /**
     * Check whether a given component is present and enabled for the given user.
     *
     * @param component the component to check.
     * @param userId the user ID for the component to check.
     * @return {@code true} if present and enabled.
     */
    public int isValid(ComponentName component, int userId) {
        synchronized (mLock) {
            ArraySet<ComponentName> installedComponents = mInstalledSet.get(userId);
            if (installedComponents == null || !installedComponents.contains(component)) {
                return NOT_INSTALLED;
            }
            ArraySet<ComponentName> validComponents = mEnabledSet.get(userId);
            if (validComponents == null || !validComponents.contains(component)) {
                return DISABLED;
            }
            return NO_ERROR;
        }
    }

    /**
     * Return all VrListenerService components installed for this user.
     *
     * @param userId ID of the user to check.
     * @return a set of {@link ComponentName}s.
     */
    public ArraySet<ComponentName> getInstalled(int userId) {
        synchronized (mLock) {
            ArraySet<ComponentName> ret = mInstalledSet.get(userId);
            if (ret == null) {
                return new ArraySet<ComponentName>();
            }
            return ret;
        }
    }

    /**
     * Return all VrListenerService components enabled for this user.
     *
     * @param userId ID of the user to check.
     * @return a set of {@link ComponentName}s.
     */
    public ArraySet<ComponentName> getEnabled(int userId) {
        synchronized (mLock) {
            ArraySet<ComponentName> ret = mEnabledSet.get(userId);
            if (ret == null) {
                return new ArraySet<ComponentName>();
            }
            return ret;

        }
    }

    private int[] getCurrentProfileIds() {
        UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        if (userManager == null) {
            return null;
        }
        return userManager.getEnabledProfileIds(ActivityManager.getCurrentUser());
    }

    public static ArraySet<ComponentName> loadComponentNames(PackageManager pm, int userId,
            String serviceName, String permissionName) {

        ArraySet<ComponentName> installed = new ArraySet<>();
        Intent queryIntent = new Intent(serviceName);
        List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
                queryIntent,
                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA |
                                    PackageManager.MATCH_DIRECT_BOOT_AWARE |
                                    PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                userId);
        if (installedServices != null) {
            for (int i = 0, count = installedServices.size(); i < count; i++) {
                ResolveInfo resolveInfo = installedServices.get(i);
                ServiceInfo info = resolveInfo.serviceInfo;

                ComponentName component = new ComponentName(info.packageName, info.name);
                if (!permissionName.equals(info.permission)) {
                    Slog.w(TAG, "Skipping service " + info.packageName + "/" + info.name
                            + ": it does not require the permission "
                            + permissionName);
                    continue;
                }
                installed.add(component);
            }
        }
        return installed;
    }

    private ArraySet<ComponentName> loadComponentNamesForUser(int userId) {
        return loadComponentNames(mContext.getPackageManager(), userId, mServiceName,
                mServicePermission);
    }

    private ArraySet<ComponentName> loadComponentNamesFromSetting(String settingName,
            int userId) {
        final ContentResolver cr = mContext.getContentResolver();
        String settingValue = Settings.Secure.getStringForUser(
                cr,
                settingName,
                userId);
        if (TextUtils.isEmpty(settingValue))
            return new ArraySet<>();
        String[] restored = settingValue.split(ENABLED_SERVICES_SEPARATOR);
        ArraySet<ComponentName> result = new ArraySet<>(restored.length);
        for (int i = 0; i < restored.length; i++) {
            ComponentName value = ComponentName.unflattenFromString(restored[i]);
            if (null != value) {
                result.add(value);
            }
        }
        return result;
    }

    private void sendSettingChanged() {
        for (EnabledComponentChangeListener l : mEnabledComponentListeners) {
            l.onEnabledComponentChanged();
        }
    }

}
