/*
 * 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.intelligence.suggestions.model;

import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Bundle;
import android.service.settings.suggestions.Suggestion;
import androidx.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.util.Log;

import com.android.settings.intelligence.suggestions.eligibility.AccountEligibilityChecker;
import com.android.settings.intelligence.suggestions.eligibility.AutomotiveEligibilityChecker;
import com.android.settings.intelligence.suggestions.eligibility.ConnectivityEligibilityChecker;
import com.android.settings.intelligence.suggestions.eligibility.DismissedChecker;
import com.android.settings.intelligence.suggestions.eligibility.FeatureEligibilityChecker;
import com.android.settings.intelligence.suggestions.eligibility.ProviderEligibilityChecker;

import java.util.List;

/**
 * A wrapper to {@link android.content.pm.ResolveInfo} that matches Suggestion signature.
 * <p/>
 * This class contains necessary metadata to eventually be
 * processed into a {@link android.service.settings.suggestions.Suggestion}.
 */
public class CandidateSuggestion {

    private static final String TAG = "CandidateSuggestion";

    /**
     * Name of the meta-data item that should be set in the AndroidManifest.xml
     * to specify the title text that should be displayed for the preference.
     */
    @VisibleForTesting
    public static final String META_DATA_PREFERENCE_TITLE = "com.android.settings.title";

    /**
     * Name of the meta-data item that should be set in the AndroidManifest.xml
     * to specify the summary text that should be displayed for the preference.
     */
    @VisibleForTesting
    public static final String META_DATA_PREFERENCE_SUMMARY = "com.android.settings.summary";

    /**
     * Name of the meta-data item that should be set in the AndroidManifest.xml
     * to specify the content provider providing the summary text that should be displayed for the
     * preference.
     *
     * Summary provided by the content provider overrides any static summary.
     */
    @VisibleForTesting
    public static final String META_DATA_PREFERENCE_SUMMARY_URI =
            "com.android.settings.summary_uri";

    /**
     * Name of the meta-data item that should be set in the AndroidManifest.xml
     * to specify the icon that should be displayed for the preference.
     */
    @VisibleForTesting
    public static final String META_DATA_PREFERENCE_ICON = "com.android.settings.icon";

    /**
     * Hint for type of suggestion UI to be displayed.
     */
    @VisibleForTesting
    public static final String META_DATA_PREFERENCE_CUSTOM_VIEW =
            "com.android.settings.custom_view";

    private final String mId;
    private final Context mContext;
    private final ResolveInfo mResolveInfo;
    private final ComponentName mComponent;
    private final Intent mIntent;
    private final boolean mIsEligible;
    private final boolean mIgnoreAppearRule;

    public CandidateSuggestion(Context context, ResolveInfo resolveInfo,
            boolean ignoreAppearRule) {
        mContext = context;
        mIgnoreAppearRule = ignoreAppearRule;
        mResolveInfo = resolveInfo;
        mIntent = new Intent().setClassName(
                resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name);
        mComponent = mIntent.getComponent();
        mId = generateId();
        mIsEligible = initIsEligible();
    }

    public String getId() {
        return mId;
    }

    public ComponentName getComponent() {
        return mComponent;
    }

    /**
     * Whether or not this candidate is eligible for display.
     * <p/>
     * Note: eligible doesn't mean it will be displayed.
     */
    public boolean isEligible() {
        return mIsEligible;
    }

    public Suggestion toSuggestion() {
        if (!mIsEligible) {
            return null;
        }
        final Suggestion.Builder builder = new Suggestion.Builder(mId);
        updateBuilder(builder);
        return builder.build();
    }

    /**
     * Checks device condition against suggestion requirement. Returns true if the suggestion is
     * eligible.
     * <p/>
     * Note: eligible doesn't mean it will be displayed.
     */
    private boolean initIsEligible() {
        if (!ProviderEligibilityChecker.isEligible(mContext, mId, mResolveInfo)) {
            return false;
        }
        if (!ConnectivityEligibilityChecker.isEligible(mContext, mId, mResolveInfo)) {
            return false;
        }
        if (!FeatureEligibilityChecker.isEligible(mContext, mId, mResolveInfo)) {
            return false;
        }
        if (!AccountEligibilityChecker.isEligible(mContext, mId, mResolveInfo)) {
            return false;
        }
        if (!DismissedChecker.isEligible(mContext, mId, mResolveInfo, mIgnoreAppearRule)) {
            return false;
        }
        if (!AutomotiveEligibilityChecker.isEligible(mContext, mId, mResolveInfo)) {
            return false;
        }
        return true;
    }

    private void updateBuilder(Suggestion.Builder builder) {
        final PackageManager pm = mContext.getPackageManager();
        final String packageName = mComponent.getPackageName();

        int iconRes = 0;
        int flags = 0;
        CharSequence title = null;
        CharSequence summary = null;
        Icon icon = null;

        // Get the activity's meta-data
        try {
            final Resources res = pm.getResourcesForApplication(packageName);
            final Bundle metaData = mResolveInfo.activityInfo.metaData;

            if (res != null && metaData != null) {
                // First get override data
                final Bundle overrideData = getOverrideData(metaData);
                // Get icon
                if (metaData.containsKey(META_DATA_PREFERENCE_ICON)) {
                    iconRes = metaData.getInt(META_DATA_PREFERENCE_ICON);
                } else {
                    iconRes = mResolveInfo.activityInfo.icon;
                }
                if (iconRes != 0) {
                    icon = Icon.createWithResource(
                            mResolveInfo.activityInfo.packageName, iconRes);
                }
                // Get title
                title = getStringFromBundle(overrideData, META_DATA_PREFERENCE_TITLE);
                if (TextUtils.isEmpty(title) && metaData.containsKey(META_DATA_PREFERENCE_TITLE)) {
                    if (metaData.get(META_DATA_PREFERENCE_TITLE) instanceof Integer) {
                        title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE));
                    } else {
                        title = metaData.getString(META_DATA_PREFERENCE_TITLE);
                    }
                }
                // Get summary
                summary = getStringFromBundle(overrideData, META_DATA_PREFERENCE_SUMMARY);
                if (TextUtils.isEmpty(summary)
                        && metaData.containsKey(META_DATA_PREFERENCE_SUMMARY)) {
                    if (metaData.get(META_DATA_PREFERENCE_SUMMARY) instanceof Integer) {
                        summary = res.getString(metaData.getInt(META_DATA_PREFERENCE_SUMMARY));
                    } else {
                        summary = metaData.getString(META_DATA_PREFERENCE_SUMMARY);
                    }
                }
                // Detect remote view
                flags = metaData.containsKey(META_DATA_PREFERENCE_CUSTOM_VIEW)
                        ? Suggestion.FLAG_HAS_BUTTON : 0;
            }
        } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
            Log.w(TAG, "Couldn't find info", e);
        }

        // Set the preference title to the activity's label if no
        // meta-data is found
        if (TextUtils.isEmpty(title)) {
            title = mResolveInfo.activityInfo.loadLabel(pm);
        }
        builder.setTitle(title)
                .setSummary(summary)
                .setFlags(flags)
                .setIcon(icon)
                .setPendingIntent(PendingIntent
                        .getActivity(mContext, 0 /* requestCode */, mIntent, 0 /* flags */));
    }

    /**
     * Extracts a string from bundle.
     */
    private CharSequence getStringFromBundle(Bundle bundle, String key) {
        if (bundle == null || TextUtils.isEmpty(key)) {
            return null;
        }
        return bundle.getString(key);
    }

    private Bundle getOverrideData(Bundle metadata) {
        if (metadata == null || !metadata.containsKey(META_DATA_PREFERENCE_SUMMARY_URI)) {
            Log.d(TAG, "Metadata null or has no info about summary_uri");
            return null;
        }

        final String uriString = metadata.getString(META_DATA_PREFERENCE_SUMMARY_URI);
        final Bundle bundle = getBundleFromUri(uriString);
        return bundle;
    }

    /**
     * Calls method through ContentProvider and expects a bundle in return.
     */
    private Bundle getBundleFromUri(String uriString) {
        final Uri uri = Uri.parse(uriString);

        final String method = getMethodFromUri(uri);
        if (TextUtils.isEmpty(method)) {
            return null;
        }
        try {
            return mContext.getContentResolver().call(uri, method, null /* args */,
                    null /* bundle */);
        } catch (IllegalArgumentException e){
            Log.d(TAG, "Unknown summary_uri", e);
            return null;
        }
    }

    /**
     * Returns the first path segment of the uri if it exists as the method, otherwise null.
     */
    private String getMethodFromUri(Uri uri) {
        if (uri == null) {
            return null;
        }
        final List<String> pathSegments = uri.getPathSegments();
        if ((pathSegments == null) || pathSegments.isEmpty()) {
            return null;
        }
        return pathSegments.get(0);
    }

    private String generateId() {
        return mComponent.flattenToString();
    }
}
