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

import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS;
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;

import android.app.admin.DevicePolicyManager;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import android.text.TextUtils;
import android.util.Log;

import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.RestrictedListPreference;
import com.android.settings.Utils;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;

import java.util.ArrayList;

public class LockScreenNotificationPreferenceController extends AbstractPreferenceController
        implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener,
        LifecycleObserver, OnResume, OnPause {

    private static final String TAG = "LockScreenNotifPref";

    private final String mSettingKey;
    private final String mWorkSettingCategoryKey;
    private final String mWorkSettingKey;

    private RestrictedListPreference mLockscreen;
    private RestrictedListPreference mLockscreenProfile;

    private final int mProfileUserId;
    private final boolean mSecure;
    private final boolean mSecureProfile;

    private SettingObserver mSettingObserver;
    private int mLockscreenSelectedValue;
    private int mLockscreenSelectedValueProfile;

    public LockScreenNotificationPreferenceController(Context context) {
        this(context, null, null, null);
    }

    public LockScreenNotificationPreferenceController(Context context,
            String settingKey, String workSettingCategoryKey, String workSettingKey) {
        super(context);
        mSettingKey = settingKey;
        mWorkSettingCategoryKey = workSettingCategoryKey;
        mWorkSettingKey = workSettingKey;

        mProfileUserId = Utils.getManagedProfileId(UserManager.get(context), UserHandle.myUserId());
        final LockPatternUtils utils = FeatureFactory.getFactory(context)
                .getSecurityFeatureProvider()
                .getLockPatternUtils(context);
        mSecure = utils.isSecure(UserHandle.myUserId());
        mSecureProfile = (mProfileUserId != UserHandle.USER_NULL) && utils.isSecure(mProfileUserId);
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        mLockscreen = (RestrictedListPreference) screen.findPreference(mSettingKey);
        if (mLockscreen == null) {
            Log.i(TAG, "Preference not found: " + mSettingKey);
            return;
        }
        if (mProfileUserId != UserHandle.USER_NULL) {
            mLockscreenProfile = (RestrictedListPreference) screen.findPreference(mWorkSettingKey);
            mLockscreenProfile.setRequiresActiveUnlockedProfile(true);
            mLockscreenProfile.setProfileUserId(mProfileUserId);
        } else {
            setVisible(screen, mWorkSettingKey, false /* visible */);
            setVisible(screen, mWorkSettingCategoryKey, false /* visible */);
        }
        mSettingObserver = new SettingObserver();
        initLockScreenNotificationPrefDisplay();
        initLockscreenNotificationPrefForProfile();
    }

    private void initLockScreenNotificationPrefDisplay() {
        ArrayList<CharSequence> entries = new ArrayList<>();
        ArrayList<CharSequence> values = new ArrayList<>();

        String summaryShowEntry =
                mContext.getString(R.string.lock_screen_notifications_summary_show);
        String summaryShowEntryValue =
                Integer.toString(R.string.lock_screen_notifications_summary_show);
        entries.add(summaryShowEntry);
        values.add(summaryShowEntryValue);
        setRestrictedIfNotificationFeaturesDisabled(summaryShowEntry, summaryShowEntryValue,
                KEYGUARD_DISABLE_SECURE_NOTIFICATIONS | KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);

        if (mSecure) {
            String summaryHideEntry =
                    mContext.getString(R.string.lock_screen_notifications_summary_hide);
            String summaryHideEntryValue =
                    Integer.toString(R.string.lock_screen_notifications_summary_hide);
            entries.add(summaryHideEntry);
            values.add(summaryHideEntryValue);
            setRestrictedIfNotificationFeaturesDisabled(summaryHideEntry, summaryHideEntryValue,
                    KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
        }

        entries.add(mContext.getString(R.string.lock_screen_notifications_summary_disable));
        values.add(Integer.toString(R.string.lock_screen_notifications_summary_disable));


        mLockscreen.setEntries(entries.toArray(new CharSequence[entries.size()]));
        mLockscreen.setEntryValues(values.toArray(new CharSequence[values.size()]));
        updateLockscreenNotifications();

        if (mLockscreen.getEntries().length > 1) {
            mLockscreen.setOnPreferenceChangeListener(this);
        } else {
            // There is one or less option for the user, disable the drop down.
            mLockscreen.setEnabled(false);
        }
    }

    private void initLockscreenNotificationPrefForProfile() {
        if (mLockscreenProfile == null) {
            Log.i(TAG, "Preference not found: " + mWorkSettingKey);
            return;
        }
        ArrayList<CharSequence> entries = new ArrayList<>();
        ArrayList<CharSequence> values = new ArrayList<>();

        String summaryShowEntry = mContext.getString(
                R.string.lock_screen_notifications_summary_show_profile);
        String summaryShowEntryValue = Integer.toString(
                R.string.lock_screen_notifications_summary_show_profile);
        entries.add(summaryShowEntry);
        values.add(summaryShowEntryValue);
        setRestrictedIfNotificationFeaturesDisabled(summaryShowEntry, summaryShowEntryValue,
                KEYGUARD_DISABLE_SECURE_NOTIFICATIONS | KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);

        if (mSecureProfile) {
            String summaryHideEntry = mContext.getString(
                    R.string.lock_screen_notifications_summary_hide_profile);
            String summaryHideEntryValue = Integer.toString(
                    R.string.lock_screen_notifications_summary_hide_profile);
            entries.add(summaryHideEntry);
            values.add(summaryHideEntryValue);
            setRestrictedIfNotificationFeaturesDisabled(summaryHideEntry, summaryHideEntryValue,
                    KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
        }

        mLockscreenProfile.setEntries(entries.toArray(new CharSequence[entries.size()]));
        mLockscreenProfile.setEntryValues(values.toArray(new CharSequence[values.size()]));
        updateLockscreenNotificationsForProfile();
        if (mLockscreenProfile.getEntries().length > 1) {
            mLockscreenProfile.setOnPreferenceChangeListener(this);
        } else {
            // There is one or less option for the user, disable the drop down.
            mLockscreenProfile.setEnabled(false);
        }
    }

    @Override
    public String getPreferenceKey() {
        return null;
    }

    @Override
    public boolean isAvailable() {
        return false;
    }

    @Override
    public void onResume() {
        if (mSettingObserver != null) {
            mSettingObserver.register(mContext.getContentResolver(), true /* register */);
        }
    }

    @Override
    public void onPause() {
        if (mSettingObserver != null) {
            mSettingObserver.register(mContext.getContentResolver(), false /* register */);
        }
    }

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        final String key = preference.getKey();
        if (TextUtils.equals(mWorkSettingKey, key)) {
            final int val = Integer.parseInt((String) newValue);
            if (val == mLockscreenSelectedValueProfile) {
                return false;
            }
            final boolean show = val == R.string.lock_screen_notifications_summary_show_profile;
            Settings.Secure.putIntForUser(mContext.getContentResolver(),
                    Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
                    show ? 1 : 0, mProfileUserId);
            mLockscreenSelectedValueProfile = val;
            return true;
        } else if (TextUtils.equals(mSettingKey, key)) {
            final int val = Integer.parseInt((String) newValue);
            if (val == mLockscreenSelectedValue) {
                return false;
            }
            final boolean enabled = val != R.string.lock_screen_notifications_summary_disable;
            final boolean show = val == R.string.lock_screen_notifications_summary_show;
            Settings.Secure.putInt(mContext.getContentResolver(),
                    Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, show ? 1 : 0);
            Settings.Secure.putInt(mContext.getContentResolver(),
                    Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, enabled ? 1 : 0);
            mLockscreenSelectedValue = val;
            return true;
        }
        return false;
    }

    private void setRestrictedIfNotificationFeaturesDisabled(CharSequence entry,
            CharSequence entryValue, int keyguardNotificationFeatures) {
        RestrictedLockUtils.EnforcedAdmin admin =
                RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
                        mContext, keyguardNotificationFeatures, UserHandle.myUserId());
        if (admin != null && mLockscreen != null) {
            RestrictedListPreference.RestrictedItem item =
                    new RestrictedListPreference.RestrictedItem(entry, entryValue, admin);
            mLockscreen.addRestrictedItem(item);
        }
        if (mProfileUserId != UserHandle.USER_NULL) {
            RestrictedLockUtils.EnforcedAdmin profileAdmin =
                    RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
                            mContext, keyguardNotificationFeatures, mProfileUserId);
            if (profileAdmin != null && mLockscreenProfile != null) {
                RestrictedListPreference.RestrictedItem item =
                        new RestrictedListPreference.RestrictedItem(
                                entry, entryValue, profileAdmin);
                mLockscreenProfile.addRestrictedItem(item);
            }
        }
    }

    public static int getSummaryResource(Context context) {
        final boolean enabled = getLockscreenNotificationsEnabled(context);
        final boolean secure = FeatureFactory.getFactory(context)
                .getSecurityFeatureProvider()
                .getLockPatternUtils(context)
                .isSecure(UserHandle.myUserId());
        final boolean allowPrivate = !secure
            || getAllowPrivateNotifications(context, UserHandle.myUserId());
        return !enabled ? R.string.lock_screen_notifications_summary_disable :
            allowPrivate ? R.string.lock_screen_notifications_summary_show :
                R.string.lock_screen_notifications_summary_hide;
    }

    private void updateLockscreenNotifications() {
        if (mLockscreen == null) {
            return;
        }
        mLockscreenSelectedValue = getSummaryResource(mContext);
        mLockscreen.setSummary("%s");
        mLockscreen.setValue(Integer.toString(mLockscreenSelectedValue));
    }

    private boolean adminAllowsUnredactedNotifications(int userId) {
        final int dpmFlags = mContext.getSystemService(DevicePolicyManager.class)
                .getKeyguardDisabledFeatures(null/* admin */, userId);
        return (dpmFlags & KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) == 0;
    }

    private void updateLockscreenNotificationsForProfile() {
        if (mProfileUserId == UserHandle.USER_NULL) {
            return;
        }
        if (mLockscreenProfile == null) {
            return;
        }
        final boolean allowPrivate = adminAllowsUnredactedNotifications(mProfileUserId) &&
                (!mSecureProfile || getAllowPrivateNotifications(mContext, mProfileUserId));
        mLockscreenProfile.setSummary("%s");
        mLockscreenSelectedValueProfile = allowPrivate
                        ? R.string.lock_screen_notifications_summary_show_profile
                        : R.string.lock_screen_notifications_summary_hide_profile;
        mLockscreenProfile.setValue(Integer.toString(mLockscreenSelectedValueProfile));
    }

    private static boolean getLockscreenNotificationsEnabled(Context context) {
        return Settings.Secure.getInt(context.getContentResolver(),
                Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0;
    }

    private static boolean getAllowPrivateNotifications(Context context, int userId) {
        return Settings.Secure.getIntForUser(context.getContentResolver(),
                Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userId) != 0;
    }

    class SettingObserver extends ContentObserver {

        private final Uri LOCK_SCREEN_PRIVATE_URI =
                Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
        private final Uri LOCK_SCREEN_SHOW_URI =
                Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS);

        public SettingObserver() {
            super(new Handler());
        }

        public void register(ContentResolver cr, boolean register) {
            if (register) {
                cr.registerContentObserver(LOCK_SCREEN_PRIVATE_URI, false, this);
                cr.registerContentObserver(LOCK_SCREEN_SHOW_URI, false, this);
            } else {
                cr.unregisterContentObserver(this);
            }
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            super.onChange(selfChange, uri);
            if (LOCK_SCREEN_PRIVATE_URI.equals(uri) || LOCK_SCREEN_SHOW_URI.equals(uri)) {
                updateLockscreenNotifications();
                if (mProfileUserId != UserHandle.USER_NULL) {
                    updateLockscreenNotificationsForProfile();
                }
            }
        }
    }
}
