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

import static com.android.settingslib.drawer.SwitchesProvider.METHOD_GET_DYNAMIC_SUMMARY;
import static com.android.settingslib.drawer.SwitchesProvider.METHOD_GET_DYNAMIC_TITLE;
import static com.android.settingslib.drawer.SwitchesProvider.METHOD_GET_PROVIDER_ICON;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY_URI;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE_URI;

import android.car.drivingstate.CarUxRestrictions;
import android.content.ContentResolver;
import android.content.Context;
import android.content.IContentProvider;
import android.content.Intent;
import android.database.ContentObserver;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Pair;

import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;

import com.android.car.settings.R;
import com.android.settingslib.drawer.TileUtils;
import com.android.settingslib.utils.ThreadUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Injects preferences from other system applications at a placeholder location. The placeholder
 * should be a {@link PreferenceGroup} which sets the controller attribute to the fully qualified
 * name of this class. The preference should contain an intent which will be passed to
 * {@link ExtraSettingsLoader#loadPreferences(Intent)}.
 *
 * {@link com.android.settingslib.drawer.TileUtils#EXTRA_SETTINGS_ACTION} is automatically added
 * for backwards compatibility. Please make sure to use
 * {@link com.android.settingslib.drawer.TileUtils#IA_SETTINGS_ACTION} instead.
 *
 * <p>For example:
 * <pre>{@code
 * <PreferenceCategory
 *     android:key="@string/pk_system_extra_settings"
 *     android:title="@string/system_extra_settings_title"
 *     settings:controller="com.android.settings.common.ExtraSettingsPreferenceController">
 *     <intent android:action="com.android.settings.action.IA_SETTINGS">
 *         <extra android:name="com.android.settings.category"
 *                android:value="com.android.settings.category.system"/>
 *     </intent>
 * </PreferenceCategory>
 * }</pre>
 *
 * @see ExtraSettingsLoader
 */
// TODO: investigate using SettingsLib Tiles.
public class ExtraSettingsPreferenceController extends PreferenceController<PreferenceGroup> {
    private static final Logger LOG = new Logger(ExtraSettingsPreferenceController.class);

    @VisibleForTesting
    static final String META_DATA_DISTRACTION_OPTIMIZED = "distractionOptimized";

    private Context mContext;
    private ContentResolver mContentResolver;
    private ExtraSettingsLoader mExtraSettingsLoader;
    private boolean mSettingsLoaded;
    @VisibleForTesting
    List<DynamicDataObserver> mObservers = new ArrayList<>();

    public ExtraSettingsPreferenceController(Context context, String preferenceKey,
            FragmentController fragmentController, CarUxRestrictions restrictionInfo) {
        super(context, preferenceKey, fragmentController, restrictionInfo);
        mContext = context;
        mContentResolver = context.getContentResolver();
        mExtraSettingsLoader = new ExtraSettingsLoader(context);
    }

    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
    public void setExtraSettingsLoader(ExtraSettingsLoader extraSettingsLoader) {
        mExtraSettingsLoader = extraSettingsLoader;
    }

    @Override
    protected Class<PreferenceGroup> getPreferenceType() {
        return PreferenceGroup.class;
    }

    @Override
    protected void onApplyUxRestrictions(CarUxRestrictions uxRestrictions) {
        // If preference intents into an activity that's not distraction optimized, disable the
        // preference. This will override the UXRE flags config_ignore_ux_restrictions and
        // config_always_ignore_ux_restrictions because navigating to these non distraction
        // optimized activities will cause the blocking activity to come up, which dead ends the
        // user.
        for (int i = 0; i < getPreference().getPreferenceCount(); i++) {
            boolean restricted = false;
            Preference preference = getPreference().getPreference(i);
            if (uxRestrictions.isRequiresDistractionOptimization()
                    && !preference.getExtras().getBoolean(META_DATA_DISTRACTION_OPTIMIZED)
                    && getAvailabilityStatus() != AVAILABLE_FOR_VIEWING) {
                restricted = true;
            }
            preference.setEnabled(getAvailabilityStatus() != AVAILABLE_FOR_VIEWING);
            restrictPreference(preference, restricted);
        }
    }

    @Override
    protected void updateState(PreferenceGroup preference) {
        Map<Preference, Bundle> preferenceBundleMap = mExtraSettingsLoader.loadPreferences(
                preference.getIntent());
        if (!mSettingsLoaded) {
            addExtraSettings(preferenceBundleMap);
            mSettingsLoaded = true;
        }
        preference.setVisible(preference.getPreferenceCount() > 0);
    }

    @Override
    protected void onStartInternal() {
        mObservers.forEach(observer -> {
            observer.register(mContentResolver, /* register= */ true);
        });
    }

    @Override
    protected void onStopInternal() {
        mObservers.forEach(observer -> {
            observer.register(mContentResolver, /* register= */ false);
        });
    }

    /**
     * Adds the extra settings from the system based on the intent that is passed in the preference
     * group. All the preferences that resolve these intents will be added in the preference group.
     *
     * @param preferenceBundleMap a map of {@link Preference} and {@link Bundle} representing
     * settings injected from system apps and their metadata.
     */
    protected void addExtraSettings(Map<Preference, Bundle> preferenceBundleMap) {
        for (Preference setting : preferenceBundleMap.keySet()) {
            Bundle metaData = preferenceBundleMap.get(setting);
            boolean distractionOptimized = false;
            if (metaData.containsKey(META_DATA_DISTRACTION_OPTIMIZED)) {
                distractionOptimized =
                        metaData.getBoolean(META_DATA_DISTRACTION_OPTIMIZED);
            }
            setting.getExtras().putBoolean(META_DATA_DISTRACTION_OPTIMIZED, distractionOptimized);
            getDynamicData(setting, metaData);
            getPreference().addPreference(setting);
        }
    }

    /**
     * Retrieve dynamic injected preference data and create observers for updates.
     */
    protected void getDynamicData(Preference preference, Bundle metaData) {
        if (metaData.containsKey(META_DATA_PREFERENCE_TITLE_URI)) {
            // Set a placeholder title before starting to fetch real title to prevent vertical
            // preference shift.
            preference.setTitle(R.string.empty_placeholder);
            Uri uri = ExtraSettingsUtil.getCompleteUri(metaData, META_DATA_PREFERENCE_TITLE_URI,
                    METHOD_GET_DYNAMIC_TITLE);
            refreshTitle(uri, preference);
            mObservers.add(
                    new DynamicDataObserver(METHOD_GET_DYNAMIC_TITLE, uri, metaData, preference));
        }
        if (metaData.containsKey(META_DATA_PREFERENCE_SUMMARY_URI)) {
            // Set a placeholder summary before starting to fetch real summary to prevent vertical
            // preference shift.
            preference.setSummary(R.string.empty_placeholder);
            Uri uri = ExtraSettingsUtil.getCompleteUri(metaData, META_DATA_PREFERENCE_SUMMARY_URI,
                    METHOD_GET_DYNAMIC_SUMMARY);
            refreshSummary(uri, preference);
            mObservers.add(
                    new DynamicDataObserver(METHOD_GET_DYNAMIC_SUMMARY, uri, metaData, preference));
        }
        if (metaData.containsKey(META_DATA_PREFERENCE_ICON_URI)) {
            // Set a placeholder icon before starting to fetch real icon to prevent horizontal
            // preference shift.
            preference.setIcon(R.drawable.ic_placeholder);
            Uri uri = ExtraSettingsUtil.getCompleteUri(metaData, META_DATA_PREFERENCE_ICON_URI,
                    METHOD_GET_PROVIDER_ICON);
            refreshIcon(uri, metaData, preference);
            mObservers.add(
                    new DynamicDataObserver(METHOD_GET_PROVIDER_ICON, uri, metaData, preference));
        }
    }

    @VisibleForTesting
    void executeBackgroundTask(Runnable r) {
        ThreadUtils.postOnBackgroundThread(r);
    }

    @VisibleForTesting
    void executeUiTask(Runnable r) {
        ThreadUtils.postOnMainThread(r);
    }

    private void refreshTitle(Uri uri, Preference preference) {
        executeBackgroundTask(() -> {
            Map<String, IContentProvider> providerMap = new ArrayMap<>();
            String titleFromUri = TileUtils.getTextFromUri(
                    mContext, uri, providerMap, META_DATA_PREFERENCE_TITLE);
            if (!TextUtils.equals(titleFromUri, preference.getTitle())) {
                executeUiTask(() -> preference.setTitle(titleFromUri));
            }
        });
    }

    private void refreshSummary(Uri uri, Preference preference) {
        executeBackgroundTask(() -> {
            Map<String, IContentProvider> providerMap = new ArrayMap<>();
            String summaryFromUri = TileUtils.getTextFromUri(
                    mContext, uri, providerMap, META_DATA_PREFERENCE_SUMMARY);
            if (!TextUtils.equals(summaryFromUri, preference.getSummary())) {
                executeUiTask(() -> preference.setSummary(summaryFromUri));
            }
        });
    }

    private void refreshIcon(Uri uri, Bundle metaData, Preference preference) {
        executeBackgroundTask(() -> {
            Intent intent = preference.getIntent();
            String packageName = null;
            if (!TextUtils.isEmpty(intent.getPackage())) {
                packageName = intent.getPackage();
            } else if (intent.getComponent() != null) {
                packageName = intent.getComponent().getPackageName();
            }
            Map<String, IContentProvider> providerMap = new ArrayMap<>();
            Pair<String, Integer> iconInfo = TileUtils.getIconFromUri(
                    mContext, packageName, uri, providerMap);
            Drawable icon;
            if (iconInfo != null) {
                icon = ExtraSettingsUtil.createIcon(mContext, metaData, iconInfo.first,
                        iconInfo.second);
            } else {
                LOG.w("Failed to get icon from uri " + uri);
                icon = ExtraSettingsUtil.createIcon(mContext, metaData, packageName, 0);
            }
            if (icon != null) {
                executeUiTask(() -> {
                    preference.setIcon(icon);
                });
            }
        });
    }

    /**
     * Observer for updating injected dynamic data.
     */
    private class DynamicDataObserver extends ContentObserver {
        private final String mMethod;
        private final Uri mUri;
        private final Bundle mMetaData;
        private final Preference mPreference;

        DynamicDataObserver(String method, Uri uri, Bundle metaData, Preference preference) {
            super(new Handler(Looper.getMainLooper()));
            mMethod = method;
            mUri = uri;
            mMetaData = metaData;
            mPreference = preference;
        }

        /** Registers or unregisters this observer to the given content resolver. */
        void register(ContentResolver cr, boolean register) {
            if (register) {
                cr.registerContentObserver(mUri, /* notifyForDescendants= */ false,
                        /* observer= */ this);
            } else {
                cr.unregisterContentObserver(this);
            }
        }

        @Override
        public void onChange(boolean selfChange) {
            switch (mMethod) {
                case METHOD_GET_DYNAMIC_TITLE:
                    refreshTitle(mUri, mPreference);
                    break;
                case METHOD_GET_DYNAMIC_SUMMARY:
                    refreshSummary(mUri, mPreference);
                    break;
                case METHOD_GET_PROVIDER_ICON:
                    refreshIcon(mUri, mMetaData, mPreference);
                    break;
            }
        }
    }
}
