/*
 * Copyright (C) 2012 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;

import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.Log;
import android.view.LayoutInflater;
import android.widget.CheckBox;

import androidx.appcompat.app.AlertDialog;

import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;

/**
 * This activity is displayed when an app launches the BIND_APPWIDGET intent. This allows apps
 * that don't have the BIND_APPWIDGET permission to bind specific widgets.
 */
public class AllowBindAppWidgetActivity extends AlertActivity implements
        DialogInterface.OnClickListener {

    private CheckBox mAlwaysUse;
    private int mAppWidgetId;
    private Bundle mBindOptions;
    private UserHandle mProfile;
    private ComponentName mComponentName;
    private String mCallingPackage;
    private AppWidgetManager mAppWidgetManager;

    // Indicates whether this activity was closed because of a click
    private boolean mClicked;

    public void onClick(DialogInterface dialog, int which) {
        mClicked = true;
        if (which == AlertDialog.BUTTON_POSITIVE) {
            if (mAppWidgetId != -1 && mComponentName != null && mCallingPackage != null) {
                try {
                    final boolean bound = mAppWidgetManager.bindAppWidgetIdIfAllowed(mAppWidgetId,
                            mProfile, mComponentName, mBindOptions);
                    if (bound) {
                        Intent result = new Intent();
                        result.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
                        setResult(RESULT_OK, result);
                    }
                } catch (Exception e) {
                    Log.v("BIND_APPWIDGET", "Error binding widget with id "
                            + mAppWidgetId + " and component " + mComponentName);
                }

                final boolean alwaysAllowBind = mAlwaysUse.isChecked();
                if (alwaysAllowBind != mAppWidgetManager.hasBindAppWidgetPermission(
                        mCallingPackage)) {
                    mAppWidgetManager.setBindAppWidgetPermission(mCallingPackage,
                            alwaysAllowBind);
                }
            }
        }
        finish();
    }

    @Override
    protected void onPause() {
        if (!mClicked) { // RESULT_CANCELED
            finish();
        }
        super.onPause();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addPrivateFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
        setResult(RESULT_CANCELED); // By default, set the result to cancelled
        Intent intent = getIntent();
        CharSequence label = "";
        if (intent != null) {
            try {
                mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
                mProfile = intent.getParcelableExtra(
                        AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE);
                if (mProfile == null) {
                    mProfile = android.os.Process.myUserHandle();
                }
                mComponentName =
                        intent.getParcelableExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER);
                mBindOptions =
                        intent.getParcelableExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS);
                mCallingPackage = getCallingPackage();
                PackageManager pm = getPackageManager();
                ApplicationInfo ai = pm.getApplicationInfo(mCallingPackage, 0);
                label = pm.getApplicationLabel(ai);
            } catch (Exception e) {
                mAppWidgetId = -1;
                mComponentName = null;
                mCallingPackage = null;
                Log.v("BIND_APPWIDGET", "Error getting parameters");
                finish();
                return;
            }
        }
        mAppWidgetManager = AppWidgetManager.getInstance(this);
        final String widgetLabel = getWidgetLabel();
        AlertController.AlertParams ap = mAlertParams;
        ap.mTitle = getString(R.string.allow_bind_app_widget_activity_allow_bind_title);
        ap.mMessage = getString(R.string.allow_bind_app_widget_activity_allow_bind, label,
                widgetLabel);
        ap.mPositiveButtonText = getString(R.string.create);
        ap.mNegativeButtonText = getString(android.R.string.cancel);
        ap.mPositiveButtonListener = this;
        ap.mNegativeButtonListener = this;
        LayoutInflater inflater =
                (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
        mAlwaysUse = (CheckBox) ap.mView.findViewById(com.android.internal.R.id.alwaysUse);
        mAlwaysUse.setText(
                getString(R.string.allow_bind_app_widget_activity_always_allow_bind, label));

        mAlwaysUse.setPadding(mAlwaysUse.getPaddingLeft(),
                mAlwaysUse.getPaddingTop(),
                mAlwaysUse.getPaddingRight(),
                (int) (mAlwaysUse.getPaddingBottom() +
                        getResources().getDimension(
                                R.dimen.bind_app_widget_dialog_checkbox_bottom_padding)));

        mAlwaysUse.setChecked(mAppWidgetManager.hasBindAppWidgetPermission(mCallingPackage,
                mProfile.getIdentifier()));

        setupAlert();
    }

    private String getWidgetLabel() {
        String label = "";
        for (AppWidgetProviderInfo providerInfo : mAppWidgetManager.getInstalledProviders()) {
            if (providerInfo.provider.equals(mComponentName)) {
                label = providerInfo.loadLabel(getPackageManager());
                break;
            }
        }
        return label;
    }
}
