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

import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_CONTROLLER;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_ICON;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_SUMMARY;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_TITLE;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_UNAVAILABLE_SLICE_SUBTITLE;

import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.net.Uri;
import android.os.Bundle;
import android.provider.SearchIndexableResource;
import android.provider.SettingsSlicesContract;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
import android.view.accessibility.AccessibilityManager;

import androidx.annotation.VisibleForTesting;

import com.android.settings.R;
import com.android.settings.accessibility.AccessibilitySettings;
import com.android.settings.accessibility.AccessibilitySlicePreferenceController;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceXmlParserUtils;
import com.android.settings.core.PreferenceXmlParserUtils.MetadataFlag;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.search.Indexable.SearchIndexProvider;
import com.android.settingslib.search.SearchIndexableData;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Converts all Slice sources into {@link SliceData}.
 * This includes:
 * - All {@link DashboardFragment DashboardFragments} indexed by settings search
 * - Accessibility services
 */
class SliceDataConverter {

    private static final String TAG = "SliceDataConverter";

    private static final String NODE_NAME_PREFERENCE_SCREEN = "PreferenceScreen";

    private final MetricsFeatureProvider mMetricsFeatureProvider;
    private Context mContext;

    public SliceDataConverter(Context context) {
        mContext = context;
        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
    }

    /**
     * @return a list of {@link SliceData} to be indexed and later referenced as a Slice.
     *
     * The collection works as follows:
     * - Collects a list of Fragments from
     * {@link FeatureFactory#getSearchFeatureProvider()}.
     * - From each fragment, grab a {@link SearchIndexProvider}.
     * - For each provider, collect XML resource layout and a list of
     * {@link com.android.settings.core.BasePreferenceController}.
     */
    public List<SliceData> getSliceData() {
        List<SliceData> sliceData = new ArrayList<>();

        final Collection<SearchIndexableData> bundles = FeatureFactory.getFactory(mContext)
                .getSearchFeatureProvider().getSearchIndexableResources().getProviderValues();

        for (SearchIndexableData bundle : bundles) {
            final String fragmentName = bundle.getTargetClass().getName();

            final SearchIndexProvider provider = bundle.getSearchIndexProvider();

            // CodeInspection test guards against the null check. Keep check in case of bad actors.
            if (provider == null) {
                Log.e(TAG, fragmentName + " dose not implement Search Index Provider");
                continue;
            }

            final List<SliceData> providerSliceData = getSliceDataFromProvider(provider,
                    fragmentName);
            sliceData.addAll(providerSliceData);
        }

        final List<SliceData> a11ySliceData = getAccessibilitySliceData();
        sliceData.addAll(a11ySliceData);
        return sliceData;
    }

    private List<SliceData> getSliceDataFromProvider(SearchIndexProvider provider,
            String fragmentName) {
        final List<SliceData> sliceData = new ArrayList<>();

        final List<SearchIndexableResource> resList =
                provider.getXmlResourcesToIndex(mContext, true /* enabled */);

        if (resList == null) {
            return sliceData;
        }

        // TODO (b/67996923) get a list of permanent NIKs and skip the invalid keys.

        for (SearchIndexableResource resource : resList) {
            int xmlResId = resource.xmlResId;
            if (xmlResId == 0) {
                Log.e(TAG, fragmentName + " provides invalid XML (0) in search provider.");
                continue;
            }

            List<SliceData> xmlSliceData = getSliceDataFromXML(xmlResId, fragmentName);
            sliceData.addAll(xmlSliceData);
        }

        return sliceData;
    }

    private List<SliceData> getSliceDataFromXML(int xmlResId, String fragmentName) {
        XmlResourceParser parser = null;

        final List<SliceData> xmlSliceData = new ArrayList<>();
        String controllerClassName = "";

        try {
            parser = mContext.getResources().getXml(xmlResId);

            int type;
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                    && type != XmlPullParser.START_TAG) {
                // Parse next until start tag is found
            }

            String nodeName = parser.getName();
            if (!NODE_NAME_PREFERENCE_SCREEN.equals(nodeName)) {
                throw new RuntimeException(
                        "XML document must start with <PreferenceScreen> tag; found"
                                + nodeName + " at " + parser.getPositionDescription());
            }

            final AttributeSet attrs = Xml.asAttributeSet(parser);
            final String screenTitle = PreferenceXmlParserUtils.getDataTitle(mContext, attrs);

            // TODO (b/67996923) Investigate if we need headers for Slices, since they never
            // correspond to an actual setting.

            final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(mContext,
                    xmlResId,
                    MetadataFlag.FLAG_NEED_KEY
                            | MetadataFlag.FLAG_NEED_PREF_CONTROLLER
                            | MetadataFlag.FLAG_NEED_PREF_TYPE
                            | MetadataFlag.FLAG_NEED_PREF_TITLE
                            | MetadataFlag.FLAG_NEED_PREF_ICON
                            | MetadataFlag.FLAG_NEED_PREF_SUMMARY
                            | MetadataFlag.FLAG_UNAVAILABLE_SLICE_SUBTITLE);

            for (Bundle bundle : metadata) {
                // TODO (b/67996923) Non-controller Slices should become intent-only slices.
                // Note that without a controller, dynamic summaries are impossible.
                controllerClassName = bundle.getString(METADATA_CONTROLLER);
                if (TextUtils.isEmpty(controllerClassName)) {
                    continue;
                }

                final String key = bundle.getString(METADATA_KEY);
                final BasePreferenceController controller = SliceBuilderUtils
                        .getPreferenceController(mContext, controllerClassName, key);
                // Only add pre-approved Slices available on the device.
                if (!controller.isSliceable() || !controller.isAvailable()) {
                    continue;
                }
                final String title = bundle.getString(METADATA_TITLE);
                final String summary = bundle.getString(METADATA_SUMMARY);
                final int iconResId = bundle.getInt(METADATA_ICON);

                final int sliceType = controller.getSliceType();
                final String unavailableSliceSubtitle = bundle.getString(
                        METADATA_UNAVAILABLE_SLICE_SUBTITLE);
                final boolean isPublicSlice = controller.isPublicSlice();

                final SliceData xmlSlice = new SliceData.Builder()
                        .setKey(key)
                        .setUri(controller.getSliceUri())
                        .setTitle(title)
                        .setSummary(summary)
                        .setIcon(iconResId)
                        .setScreenTitle(screenTitle)
                        .setPreferenceControllerClassName(controllerClassName)
                        .setFragmentName(fragmentName)
                        .setSliceType(sliceType)
                        .setUnavailableSliceSubtitle(unavailableSliceSubtitle)
                        .setIsPublicSlice(isPublicSlice)
                        .build();

                xmlSliceData.add(xmlSlice);
            }
        } catch (SliceData.InvalidSliceDataException e) {
            Log.w(TAG, "Invalid data when building SliceData for " + fragmentName, e);
            mMetricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
                    SettingsEnums.ACTION_VERIFY_SLICE_ERROR_INVALID_DATA,
                    SettingsEnums.PAGE_UNKNOWN,
                    controllerClassName,
                    1);
        } catch (XmlPullParserException | IOException | Resources.NotFoundException e) {
            Log.w(TAG, "Error parsing PreferenceScreen: ", e);
            mMetricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
                    SettingsEnums.ACTION_VERIFY_SLICE_PARSING_ERROR,
                    SettingsEnums.PAGE_UNKNOWN,
                    fragmentName,
                    1);
        } catch (Exception e) {
            Log.w(TAG, "Get slice data from XML failed ", e);
            mMetricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
                    SettingsEnums.ACTION_VERIFY_SLICE_OTHER_EXCEPTION,
                    SettingsEnums.PAGE_UNKNOWN,
                    fragmentName + "_" + controllerClassName,
                    1);
        } finally {
            if (parser != null) parser.close();
        }
        return xmlSliceData;
    }

    private List<SliceData> getAccessibilitySliceData() {
        final List<SliceData> sliceData = new ArrayList<>();

        final String accessibilityControllerClassName =
                AccessibilitySlicePreferenceController.class.getName();
        final String fragmentClassName = AccessibilitySettings.class.getName();
        final CharSequence screenTitle = mContext.getText(R.string.accessibility_settings);

        final SliceData.Builder sliceDataBuilder = new SliceData.Builder()
                .setFragmentName(fragmentClassName)
                .setScreenTitle(screenTitle)
                .setPreferenceControllerClassName(accessibilityControllerClassName);

        final Set<String> a11yServiceNames = new HashSet<>();
        Collections.addAll(a11yServiceNames, mContext.getResources()
                .getStringArray(R.array.config_settings_slices_accessibility_components));
        final List<AccessibilityServiceInfo> installedServices = getAccessibilityServiceInfoList();
        final PackageManager packageManager = mContext.getPackageManager();

        for (AccessibilityServiceInfo a11yServiceInfo : installedServices) {
            final ResolveInfo resolveInfo = a11yServiceInfo.getResolveInfo();
            final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
            final String packageName = serviceInfo.packageName;
            final ComponentName componentName = new ComponentName(packageName, serviceInfo.name);
            final String flattenedName = componentName.flattenToString();

            if (!a11yServiceNames.contains(flattenedName)) {
                continue;
            }

            final String title = resolveInfo.loadLabel(packageManager).toString();
            int iconResource = resolveInfo.getIconResource();
            if (iconResource == 0) {
                iconResource = R.drawable.ic_accessibility_generic;
            }

            sliceDataBuilder.setKey(flattenedName)
                    .setTitle(title)
                    .setUri(new Uri.Builder()
                            .scheme(ContentResolver.SCHEME_CONTENT)
                            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
                            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
                            .appendPath(flattenedName)
                            .build())
                    .setIcon(iconResource)
                    .setSliceType(SliceData.SliceType.SWITCH);
            try {
                sliceData.add(sliceDataBuilder.build());
            } catch (SliceData.InvalidSliceDataException e) {
                Log.w(TAG, "Invalid data when building a11y SliceData for " + flattenedName, e);
            }
        }

        return sliceData;
    }

    @VisibleForTesting
    List<AccessibilityServiceInfo> getAccessibilityServiceInfoList() {
        final AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(
                mContext);
        return accessibilityManager.getInstalledAccessibilityServiceList();
    }
}