/*
 * Copyright (C) 2018 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.permissioncontroller.permission.ui.handheld;

import static android.health.connect.HealthPermissions.HEALTH_PERMISSION_GROUP;

import static com.android.permissioncontroller.Constants.EXTRA_SESSION_ID;
import static com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_CALLER_NAME;
import static com.android.permissioncontroller.permission.ui.handheld.AppPermissionFragment.GRANT_CATEGORY;
import static com.android.permissioncontroller.permission.ui.handheld.AppPermissionFragment.PERSISTENT_DEVICE_ID;
import static com.android.permissioncontroller.permission.utils.KotlinUtilsKt.navigateSafe;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.navigation.Navigation;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;

import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.model.AppPermissionGroup;
import com.android.permissioncontroller.permission.ui.LocationProviderInterceptDialog;
import com.android.permissioncontroller.permission.utils.LocationUtils;
import com.android.permissioncontroller.permission.utils.Utils;

import java.util.List;

/**
 * A preference that links to the screen where a permission can be toggled.
 */
public class PermissionControlPreference extends Preference {
    private final @NonNull Context mContext;
    private @Nullable Drawable mWidgetIcon;
    private @Nullable String mWidgetIconContentDescription;
    private @Nullable View.OnClickListener mWidgetIconOnClickListener;
    private @Nullable String mGranted;
    private boolean mUseSmallerIcon;
    private boolean mEllipsizeEnd;
    private @Nullable List<Integer> mTitleIcons;
    private @Nullable List<Integer> mSummaryIcons;
    private @NonNull String mPackageName;
    private @NonNull String mPermGroupName;
    private @NonNull String mCaller;
    private @NonNull long mSessionId;
    private boolean mHasNavGraph;
    private @NonNull UserHandle mUser;
    private @Nullable String mPersistentDeviceId;

    public PermissionControlPreference(@NonNull Context context,
            @NonNull AppPermissionGroup group, @NonNull String caller) {
        this(context, group, caller, 0);
    }

    public PermissionControlPreference(@NonNull Context context,
            @NonNull AppPermissionGroup group, @NonNull String caller, long sessionId) {
        this(context, group.getApp().packageName, group.getName(), group.getUser(), caller,
                sessionId, null, false);
    }

    public PermissionControlPreference(@NonNull Context context,
            @NonNull String packageName, @NonNull String permGroupName, @NonNull UserHandle user,
            @NonNull String caller, long sessionId, String granted, boolean hasNavGraph) {
        super(context);
        mContext = context;
        mWidgetIcon = null;
        mUseSmallerIcon = false;
        mEllipsizeEnd = false;
        mTitleIcons = null;
        mSummaryIcons = null;
        mPackageName = packageName;
        mCaller = caller;
        mPermGroupName = permGroupName;
        mSessionId = sessionId;
        mUser = user;
        mGranted = granted;
        mHasNavGraph = hasNavGraph;
    }

    /**
     * Sets this preference's right icon.
     *
     * Note that this must be called before preference layout to take effect.
     *
     * @param widgetIcon the icon to use.
     */
    public void setRightIcon(@NonNull Drawable widgetIcon) {
        mWidgetIcon = widgetIcon;
        setWidgetLayoutResource(R.layout.image_view);
    }

    /**
     * Sets this preference's right icon with an onClickListener.
     *
     * Note that this must be called before preference layout to take effect.
     *
     * @param widgetIcon the icon to use.
     * @param listener the onClickListener attached to the icon.
     */
    public void setRightIcon(@NonNull Drawable widgetIcon,
            @NonNull String widgetIconContentDescription, @NonNull View.OnClickListener listener) {
        mWidgetIcon = widgetIcon;
        mWidgetIconContentDescription = widgetIconContentDescription;
        setWidgetLayoutResource(R.layout.image_view_with_divider);
        mWidgetIconOnClickListener = listener;
    }

    /**
     * Sets this preference's left icon to be smaller than normal.
     *
     * Note that this must be called before preference layout to take effect.
     */
    public void useSmallerIcon() {
        mUseSmallerIcon = true;
    }

    /**
     * Sets this preference's title to use an ellipsis at the end.
     *
     * Note that this must be called before preference layout to take effect.
     */
    public void setEllipsizeEnd() {
        mEllipsizeEnd = true;
    }

    /**
     * Sets this preference's summary based on the group it represents, if applicable.
     *
     * @param group the permission group this preference represents.
     */
    public void setGroupSummary(@NonNull AppPermissionGroup group) {
        if (group.hasPermissionWithBackgroundMode() && group.areRuntimePermissionsGranted()) {
            AppPermissionGroup backgroundGroup = group.getBackgroundPermissions();
            if (backgroundGroup == null || !backgroundGroup.areRuntimePermissionsGranted()) {
                setSummary(R.string.permission_subtitle_only_in_foreground);
                return;
            }
        }
        setSummary("");
    }

    /**
     * Sets this preference to show the given icons to the left of its title.
     *
     * @param titleIcons the icons to show.
     */
    public void setTitleIcons(@NonNull List<Integer> titleIcons) {
        mTitleIcons = titleIcons;
        setLayoutResource(R.layout.preference_usage);
    }

    @Override
    public void onBindViewHolder(PreferenceViewHolder holder) {
        if (mUseSmallerIcon) {
            ImageView icon = ((ImageView) holder.findViewById(android.R.id.icon));
            icon.setMaxWidth(
                    mContext.getResources().getDimensionPixelSize(
                            com.android.settingslib.widget.theme.R.dimen.secondary_app_icon_size));
            icon.setMaxHeight(
                    mContext.getResources().getDimensionPixelSize(
                            com.android.settingslib.widget.theme.R.dimen.secondary_app_icon_size));
        }

        super.onBindViewHolder(holder);

        if (mWidgetIcon != null) {
            View widgetFrame = holder.findViewById(android.R.id.widget_frame);
            ImageView widgetIcon = widgetFrame.findViewById(R.id.icon);
            widgetIcon.setImageDrawable(mWidgetIcon);
            widgetIcon.setContentDescription(mWidgetIconContentDescription);

            if (mWidgetIconOnClickListener != null) {
                widgetFrame.findViewById(R.id.icon).setOnClickListener(mWidgetIconOnClickListener);
                View preferenceRootView = holder.itemView;
                preferenceRootView.setPaddingRelative(
                        preferenceRootView.getPaddingStart(), preferenceRootView.getPaddingTop(),
                        0, preferenceRootView.getPaddingBottom());
            }
        }

        if (mEllipsizeEnd) {
            TextView title = (TextView) holder.findViewById(android.R.id.title);
            title.setMaxLines(1);
            title.setEllipsize(TextUtils.TruncateAt.END);
        }

        setIcons(holder, mSummaryIcons, R.id.summary_widget_frame);
        setIcons(holder, mTitleIcons, R.id.title_widget_frame);

        setOnPreferenceClickListener(pref -> {
            if (LocationUtils.isLocationGroupAndProvider(
                    mContext, mPermGroupName, mPackageName)) {
                Intent intent = new Intent(mContext, LocationProviderInterceptDialog.class);
                intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mPackageName);
                mContext.startActivityAsUser(intent, mUser);
            } else if (LocationUtils.isLocationGroupAndControllerExtraPackage(
                    mContext, mPermGroupName, mPackageName)) {
                // Redirect to location controller extra package settings.
                LocationUtils.startLocationControllerExtraPackageSettings(mContext, mUser);
            } else if (mHasNavGraph) {
                if (mPermGroupName.equals(Manifest.permission_group.NOTIFICATIONS)) {
                    Utils.navigateToAppNotificationSettings(mContext, mPackageName, mUser);
                    return true;
                }
                if (Utils.isHealthPermissionUiEnabled()
                        && mPermGroupName.equals(HEALTH_PERMISSION_GROUP)) {
                    Utils.navigateToAppHealthConnectSettings(mContext, mPackageName, mUser);
                    return true;
                }
                Bundle args = new Bundle();
                args.putString(Intent.EXTRA_PACKAGE_NAME, mPackageName);
                args.putString(Intent.EXTRA_PERMISSION_GROUP_NAME, mPermGroupName);
                args.putParcelable(Intent.EXTRA_USER, mUser);
                args.putString(EXTRA_CALLER_NAME, mCaller);
                args.putLong(EXTRA_SESSION_ID, mSessionId);
                args.putString(GRANT_CATEGORY, mGranted);
                args.putString(PERSISTENT_DEVICE_ID, mPersistentDeviceId);
                navigateSafe(Navigation.findNavController(holder.itemView), R.id.perm_groups_to_app,
                        args);
            } else {
                // TODO ntmyren, yianyliu: Remove once Auto has been adapted to new permission model
                // see b/150229448
                Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSION);
                intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mPackageName);
                intent.putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, mPermGroupName);
                intent.putExtra(Intent.EXTRA_USER, mUser);
                intent.putExtra(EXTRA_CALLER_NAME, mCaller);
                intent.putExtra(EXTRA_SESSION_ID, mSessionId);
                mContext.startActivity(intent);
            }
            return true;
        });
    }

    public void setPersistentDeviceId(String persistentDeviceId) {
        this.mPersistentDeviceId = persistentDeviceId;
    }

    private void setIcons(PreferenceViewHolder holder, @Nullable List<Integer> icons, int frameId) {
        ViewGroup frame = (ViewGroup) holder.findViewById(frameId);
        if (icons != null && !icons.isEmpty()) {
            frame.setVisibility(View.VISIBLE);
            frame.removeAllViews();
            LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class);
            int numIcons = icons.size();
            for (int i = 0; i < numIcons; i++) {
                ViewGroup group = (ViewGroup) inflater.inflate(R.layout.title_summary_image_view,
                        null);
                ImageView imageView = group.requireViewById(R.id.icon);
                imageView.setImageResource(icons.get(i));
                frame.addView(group);
            }
        } else if (frame != null) {
            frame.setVisibility(View.GONE);
        }
    }
}
