/*
 * Copyright (C) 2019 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.setupwizardlib.summary;

import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Collects the actions provided by partners and compiles them into a list of {@link SummaryAction}
 * items.
 */
public class PartnerSummaryActionsCollector {

    private static final String TAG = "PartnerSummaryActionsCollector";

    private static final String CONTENT_PROVIDER_INTENT_ACTION =
            "com.google.android.car.setupwizard.SETUP_ACTIONS_STATE_PROVIDER";

    // Methods for fetching info from the content provider.
    private static final String METHOD_GET_ACTION_COMPLETION_STATE = "get_action_completion_state";
    private static final String METHOD_GET_ACTION_SUMMARY_STATE = "get_action_summary_state";
    private static final String METHOD_GET_DEFERRED_ACTION_STATE =
            "get_deferred_action_state";
    private static final String METHOD_GET_SUMMARY_ACTIONS = "get_summary_actions";

    // Constants for fetching information from the bundles passed back by the content provider.
    private static final String EXTRA_SUMMARY_ACTIONS_LIST = "summary_actions_list";
    private static final String EXTRA_IS_ACTION_COMPLETED = "is_action_completed";

    // Constants for information contained within the summary action bundle.
    private static final String EXTRA_SUMMARY_ACTION_HAS_DEPENDENCY =
            "summary_action_has_dependency";
    private static final String EXTRA_SUMMARY_ACTION_DEPENDENCY_DESCRIPTION =
            "summary_action_dependency_description";
    private static final String EXTRA_SUMMARY_ACTION_TITLE = "summary_action_title";
    private static final String EXTRA_SUMMARY_ACTION_DESCRIPTION = "summary_action_description";
    private static final String EXTRA_SUMMARY_ACTION_REQUIRES_NETWORK =
            "summary_action_requires_network";
    private static final String EXTRA_SUMMARY_ACTION_WIZARD_SCRIPT = "summary_action_wizard_script";
    private static final String EXTRA_SUMMARY_ACTION_PRIORITY = "summary_action_priority";
    private static final String EXTRA_SUMMARY_ICON_RESOURCE_NAME =
            "summary_action_icon_resource_name";
    private static final String EXTRA_SUMMARY_COMPLETED_DESCRIPTION =
            "summary_action_completed_description";
    private static final String EXTRA_SUMMARY_ACTION_DEFERRED_NOTIFICATION_DESCRIPTION =
            "summary_action_deferred_notification_description";

    // Extra used as a key for the action id passed in to query summary action state.
    private static final String EXTRA_ACTION_ID = "action_id";
    private static PartnerSummaryActionsCollector partnerSummaryActionsCollector;
    private final Context context;
    private Uri mContentProviderUri;

    /** private constructor, should use getter. */
    private PartnerSummaryActionsCollector(Context context) {
        this.context = context;
        ResolveInfo resolveInfo = getSummaryContentProviderResolveInfo(context.getPackageManager());

        if (resolveInfo == null) {
            Log.e(TAG, "Could not find partner content provider, ignoring partner summary items.");
            return;
        }

        mContentProviderUri = getSummaryContentProviderUri(resolveInfo);

        if (mContentProviderUri == null) {
            Log.e(TAG, "Could not fetch content provider URI, ignoring partner summary items.");
        }
    }

    /** Gets the current instance of the {@link PartnerSummaryActionsCollector}. */
    public static PartnerSummaryActionsCollector get(Context context) {
        if (partnerSummaryActionsCollector == null) {
            partnerSummaryActionsCollector = new PartnerSummaryActionsCollector(context);
        }
        return partnerSummaryActionsCollector;
    }

    /**
     * Creates a summary action using the passed in completion state and summary state {@link
     * Bundle}.
     * This will pull out all relevant state such as title, description, dependencies, and anything
     * else that defines a summary item. Returns null if the bundle does not have all the required
     * state or is null.
     */
    @Nullable
    private static SummaryAction buildSummaryAction(
            boolean completed, Bundle summaryStateBundle) {
        if (summaryStateBundle == null) {
            return null;
        }

        String title = summaryStateBundle.getString(EXTRA_SUMMARY_ACTION_TITLE);
        if (title == null) {
            Log.e(TAG, "No title provided in summaryStateBundle: " + summaryStateBundle);
            return null;
        }

        String scriptUri = summaryStateBundle.getString(EXTRA_SUMMARY_ACTION_WIZARD_SCRIPT);
        if (scriptUri == null) {
            Log.e(TAG, "No wizard script provided in summaryStateBundle: " + summaryStateBundle);
            return null;
        }

        String description = summaryStateBundle.getString(EXTRA_SUMMARY_ACTION_DESCRIPTION, "");
        boolean requiresNetwork =
                summaryStateBundle.getBoolean(EXTRA_SUMMARY_ACTION_REQUIRES_NETWORK, false);
        boolean hasUnfinishedDependency =
                summaryStateBundle.getBoolean(EXTRA_SUMMARY_ACTION_HAS_DEPENDENCY, false);
        String unfinishedDependencyDescription = null;
        if (hasUnfinishedDependency) {
            unfinishedDependencyDescription =
                    summaryStateBundle.getString(EXTRA_SUMMARY_ACTION_DEPENDENCY_DESCRIPTION);
        }
        // Fetch priority, default 0 so that if no priority is provided they will be placed above
        // the Google items which are located in 100-200.
        int priority = summaryStateBundle.getInt(EXTRA_SUMMARY_ACTION_PRIORITY, 0);
        String iconResourceName = null;
        if (summaryStateBundle.containsKey(EXTRA_SUMMARY_ICON_RESOURCE_NAME)) {
            iconResourceName = summaryStateBundle.getString(EXTRA_SUMMARY_ICON_RESOURCE_NAME, "");
        }

        String completedDescription =
                summaryStateBundle.getString(EXTRA_SUMMARY_COMPLETED_DESCRIPTION, description);
        return new SummaryAction(
                title,
                description,
                requiresNetwork,
                completed,
                priority,
                scriptUri,
                hasUnfinishedDependency,
                unfinishedDependencyDescription,
                iconResourceName,
                completedDescription);
    }

    /**
     * Creates a {@link DeferredAction} based on the passed in completion state and deferred action
     * state bundle. Will return null if there is no notification description or a null bundle.
     */
    private static DeferredAction buildDeferredAction(boolean completed,
            Bundle deferredActionState) {
        if (deferredActionState == null) {
            Log.e(TAG, "Cannot build deferred action with null deferredActionState");
            return null;
        }

        String deferredNotificationDescription = deferredActionState.getString(
                EXTRA_SUMMARY_ACTION_DEFERRED_NOTIFICATION_DESCRIPTION);
        if (deferredNotificationDescription == null) {
            Log.v(TAG, "Cannot build deferred action with no notification description");
            return null;
        }

        int priority = deferredActionState.getInt(EXTRA_SUMMARY_ACTION_PRIORITY, 0);
        return new DeferredAction(deferredNotificationDescription, completed, priority);
    }

    private static ResolveInfo getSummaryContentProviderResolveInfo(PackageManager packageManager) {
        Intent contentProviderQueryIntent = new Intent(CONTENT_PROVIDER_INTENT_ACTION);
        List<ResolveInfo> queryResults =
                packageManager.queryIntentContentProviders(contentProviderQueryIntent, 0);
        Log.v(TAG, "Query results size before pruning for system packages: " + queryResults.size());
        queryResults =
                queryResults.stream()
                        .filter(
                                resolveInfo ->
                                        resolveInfo.providerInfo != null
                                                && resolveInfo.providerInfo.applicationInfo != null
                                                && (resolveInfo.providerInfo.applicationInfo.flags
                                                & ApplicationInfo.FLAG_SYSTEM)
                                                != 0)
                        .collect(Collectors.toList());
        if (queryResults.size() > 1 || queryResults.isEmpty()) {
            Log.v(
                    TAG,
                    "Found "
                            + queryResults.size()
                            + " content providers, there should be exactly 1 to show partner "
                            + "actions. Ignoring"
                            + " all partner actions.");
            return null;
        }
        return queryResults.get(0);
    }

    private static Uri getSummaryContentProviderUri(ResolveInfo resolveInfo) {
        if (resolveInfo.providerInfo == null || TextUtils.isEmpty(
                resolveInfo.providerInfo.authority)) {
            Log.e(TAG, "Incorrectly configured partner content provider");
            return null;
        }
        return new Uri.Builder()
                .scheme(ContentResolver.SCHEME_CONTENT)
                .authority(resolveInfo.providerInfo.authority)
                .build();
    }

    /**
     * Gets the list of provided partner summary actions. Will return an empty list if none are
     * found or there is an error loading them.
     */
    public List<SummaryAction> getPartnerSummaryActions() {
        if (mContentProviderUri == null) {
            Log.e(TAG, "No content provider URI found, summary actions ignored");
            return new ArrayList<>();
        }
        ArrayList<String> partnerSummaryActions;
        try {
            partnerSummaryActions = getPartnerSummaryActionsFromContentProvider(
                    mContentProviderUri);
        } catch (NullPointerException | IllegalArgumentException e) {
            Log.e(TAG, "Unable to find or successfully query content provider, ignoring action", e);
            return new ArrayList<>();
        }

        if (partnerSummaryActions == null || partnerSummaryActions.isEmpty()) {
            Log.v(TAG, "No actions were fetched for partners");
            return new ArrayList<>();
        }

        List<SummaryAction> summaryActionList = new ArrayList<>();
        for (String actionId : partnerSummaryActions) {
            Log.v(TAG, "Attempting to generate summary action for id: " + actionId);
            try {
                boolean completed =
                        getActionCompletionStateFromContentProvider(actionId, mContentProviderUri);
                Bundle summaryActionBundle =
                        getActionSummaryStateFromContentProvider(actionId, mContentProviderUri);
                SummaryAction summaryAction = buildSummaryAction(completed, summaryActionBundle);
                if (summaryAction != null) {
                    summaryActionList.add(summaryAction);
                }
            } catch (NullPointerException | IllegalArgumentException e) {
                Log.e(
                        TAG,
                        "Unable to load the completion or config state for summary action: "
                                + actionId,
                        e);
            }
        }
        return summaryActionList;
    }

    /** Returns the set of partner deferred actions provided by the partner content provider. */
    public List<DeferredAction> getPartnerDeferredActions() {
        if (mContentProviderUri == null) {
            Log.e(TAG, "No content provider URI found, deferred actions ignored");
            return new ArrayList<>();
        }

        ArrayList<String> partnerSummaryActions;
        try {
            partnerSummaryActions = getPartnerSummaryActionsFromContentProvider(
                    mContentProviderUri);
        } catch (NullPointerException | IllegalArgumentException e) {
            Log.e(TAG, "Unable to find or successfully query content provider, ignoring action", e);
            return new ArrayList<>();
        }

        if (partnerSummaryActions == null || partnerSummaryActions.isEmpty()) {
            Log.v(TAG, "No actions were fetched for partners");
            return new ArrayList<>();
        }

        List<DeferredAction> deferredActions = new ArrayList<>();
        for (String actionId : partnerSummaryActions) {
            Log.v(TAG, "Attempting to generate deferred action for id: " + actionId);
            try {
                boolean completed =
                        getActionCompletionStateFromContentProvider(actionId, mContentProviderUri);
                Bundle deferredActionBundle =
                        getDeferredActionStateFromContentProvider(actionId, mContentProviderUri);
                if (deferredActionBundle == null) {
                    Log.v(TAG, "No valid deferredActionBundle for action: " + actionId);
                    continue;
                }
                DeferredAction deferredAction = buildDeferredAction(completed,
                        deferredActionBundle);
                if (deferredAction != null) {
                    deferredActions.add(deferredAction);
                }
            } catch (NullPointerException e) {
                Log.e(
                        TAG,
                        "Unable to load the completion or config state for deferred action: "
                                + actionId,
                        e);
            }
        }
        return deferredActions;
    }

    /**
     * Gets the list of actionId's for the partner summary actions form the passed in content
     * provider
     * {@link Uri}.
     *
     * @throws NullPointerException     if the method is null on the content provider.
     * @throws IllegalArgumentException if uri is not known or the request method is not supported
     *                                  properly.
     */
    private ArrayList<String> getPartnerSummaryActionsFromContentProvider(Uri contentProviderUri) {
        Bundle result = context.getContentResolver().call(
                contentProviderUri,
                METHOD_GET_SUMMARY_ACTIONS,
                /* arg= */ null,
                /* extras= */ null);
        if (result == null || result.getStringArrayList(EXTRA_SUMMARY_ACTIONS_LIST) == null) {
            Log.e(
                    TAG,
                    "No summary actions returned from content resolve call, can't fetch partner "
                            + "actions.");
            throw new IllegalArgumentException(
                    "Uri: " + contentProviderUri + " did not return a list of actionId's.");
        }
        return result.getStringArrayList(EXTRA_SUMMARY_ACTIONS_LIST);
    }

    /**
     * Gets the completion state for the specific actionId passed in using the passed in content
     * provider {@link Uri}.
     *
     * @throws NullPointerException     if the method is null on the content provider.
     * @throws IllegalArgumentException if uri is not known or the request method is not supported
     *                                  properly.
     */
    private boolean getActionCompletionStateFromContentProvider(
            String actionId, Uri contentProviderUri) {
        Bundle completionStateArgs = new Bundle();
        completionStateArgs.putString(EXTRA_ACTION_ID, actionId);
        Bundle result = context.getContentResolver().call(
                contentProviderUri,
                METHOD_GET_ACTION_COMPLETION_STATE,
                /* arg= */ null,
                completionStateArgs);
        if (result == null || !result.containsKey(EXTRA_IS_ACTION_COMPLETED)) {
            throw new IllegalArgumentException(
                    "No action with id " + actionId + " found in content provider");
        }
        return result.getBoolean(EXTRA_IS_ACTION_COMPLETED, true);
    }

    private Bundle getActionSummaryStateFromContentProvider(String actionId,
            Uri contentProviderUri) {
        Bundle summaryStateArgs = new Bundle();
        summaryStateArgs.putString(EXTRA_ACTION_ID, actionId);
        Bundle result = context.getContentResolver().call(
                contentProviderUri,
                METHOD_GET_ACTION_SUMMARY_STATE,
                /* arg= */ null,
                summaryStateArgs);
        if (result == null) {
            throw new IllegalArgumentException(
                    "No action summary found in content provider for " + actionId);
        }
        return result;
    }

    private Bundle getDeferredActionStateFromContentProvider(String actionId,
            Uri contentProviderUri) {
        Bundle deferredStateArgs = new Bundle();
        deferredStateArgs.putString(EXTRA_ACTION_ID, actionId);
        Bundle result;
        try {
            result = context.getContentResolver().call(
                    contentProviderUri,
                    METHOD_GET_DEFERRED_ACTION_STATE,
                    /* arg= */ null,
                    deferredStateArgs);
        } catch (UnsupportedOperationException e) {
            Log.v(TAG, "Deferred notification query not supported by partner content provider");
            return null;
        }
        return result;
    }
}
