/*
 * 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.applications.defaultapps;

import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import androidx.preference.Preference;
import android.text.TextUtils;
import android.util.IconDrawableFactory;
import android.util.Log;

import com.android.settingslib.applications.DefaultAppInfo;

import java.util.List;

public class DefaultBrowserPreferenceController extends DefaultAppPreferenceController {

    private static final String TAG = "BrowserPrefCtrl";

    static final Intent BROWSE_PROBE = new Intent()
            .setAction(Intent.ACTION_VIEW)
            .addCategory(Intent.CATEGORY_BROWSABLE)
            .setData(Uri.parse("http:"));

    public DefaultBrowserPreferenceController(Context context) {
        super(context);
    }

    @Override
    public boolean isAvailable() {
        final List<ResolveInfo> candidates = getCandidates();
        return candidates != null && !candidates.isEmpty();
    }

    @Override
    public String getPreferenceKey() {
        return "default_browser";
    }

    @Override
    public void updateState(Preference preference) {
        super.updateState(preference);
        final CharSequence defaultAppLabel = getDefaultAppLabel();
        if (!TextUtils.isEmpty(defaultAppLabel)) {
            preference.setSummary(defaultAppLabel);
        }
    }

    @Override
    protected DefaultAppInfo getDefaultAppInfo() {
        try {
            final String packageName = mPackageManager.getDefaultBrowserPackageNameAsUser(mUserId);
            Log.d(TAG, "Get default browser package: " + packageName);
            return new DefaultAppInfo(mContext, mPackageManager,
                    mPackageManager.getPackageManager().getApplicationInfo(packageName, 0));
        } catch (PackageManager.NameNotFoundException e) {
            return null;
        }
    }

    @Override
    public CharSequence getDefaultAppLabel() {
        if (!isAvailable()) {
            return null;
        }
        final DefaultAppInfo defaultApp = getDefaultAppInfo();
        final CharSequence defaultAppLabel = defaultApp != null ? defaultApp.loadLabel() : null;
        if (!TextUtils.isEmpty(defaultAppLabel)) {
            return defaultAppLabel;
        }
        return getOnlyAppLabel();
    }

    @Override
    public Drawable getDefaultAppIcon() {
        if (!isAvailable()) {
            return null;
        }
        final DefaultAppInfo defaultApp = getDefaultAppInfo();
        if (defaultApp != null) {
            return defaultApp.loadIcon();
        }
        return getOnlyAppIcon();
    }

    private List<ResolveInfo> getCandidates() {
        return mPackageManager.queryIntentActivitiesAsUser(BROWSE_PROBE, PackageManager.MATCH_ALL,
                mUserId);
    }

    private String getOnlyAppLabel() {
        // Resolve that intent and check that the handleAllWebDataURI boolean is set
        final List<ResolveInfo> list = getCandidates();
        if (list != null && list.size() == 1) {
            final ResolveInfo info = list.get(0);
            final String label = info.loadLabel(mPackageManager.getPackageManager()).toString();
            final ComponentInfo cn = info.getComponentInfo();
            final String packageName = cn == null ? null : cn.packageName;
            Log.d(TAG, "Getting label for the only browser app: " + packageName + label);
            return label;
        }
        return null;
    }

    private Drawable getOnlyAppIcon() {
        final List<ResolveInfo> list = getCandidates();
        if (list != null && list.size() == 1) {
            final ResolveInfo info = list.get(0);
            final ComponentInfo cn = info.getComponentInfo();
            final String packageName = cn == null ? null : cn.packageName;
            if (TextUtils.isEmpty(packageName)) {
                return null;
            }
            final ApplicationInfo appInfo;
            try {
                appInfo = mPackageManager.getPackageManager().getApplicationInfo(packageName, 0);
            } catch (PackageManager.NameNotFoundException e) {
                Log.w(TAG, "Error getting app info for " + packageName);
                return null;
            }
            Log.d(TAG, "Getting icon for the only browser app: " + packageName);
            final IconDrawableFactory iconFactory = IconDrawableFactory.newInstance(mContext);
            return iconFactory.getBadgedIcon(cn, appInfo, mUserId);
        }
        return null;
    }

    /**
     * Whether or not the pkg contains browser capability
     */
    public static boolean hasBrowserPreference(String pkg, Context context) {
        final Intent intent = new Intent(BROWSE_PROBE);
        intent.setPackage(pkg);
        final List<ResolveInfo> resolveInfos =
                context.getPackageManager().queryIntentActivities(intent, 0);
        return resolveInfos != null && resolveInfos.size() != 0;
    }

    /**
     * Whether or not the pkg is the default browser
     */
    public boolean isBrowserDefault(String pkg, int userId) {
        String defaultPackage = mPackageManager.getDefaultBrowserPackageNameAsUser(userId);
        if (defaultPackage != null) {
            return defaultPackage.equals(pkg);
        }

        final List<ResolveInfo> list = mPackageManager.queryIntentActivitiesAsUser(BROWSE_PROBE,
                PackageManager.MATCH_ALL, userId);
        // There is only 1 app, it must be the default browser.
        return list != null && list.size() == 1;
    }
}
