/*
 * Copyright (C) 2015 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.wear;

import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DENY_AND_DONT_ASK_AGAIN_BUTTON;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.TextAppearanceSpan;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Space;

import androidx.wear.ble.view.AcceptDenyDialog;
import androidx.wear.ble.view.WearableDialogHelper;

import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler;

/**
 * Watch-specific view handler for the grant permissions activity.
 */
public final class GrantPermissionsWearViewHandler implements GrantPermissionsViewHandler,
        DialogInterface.OnClickListener {
    private static final String TAG = "GrantPermsWatchViewH";

    private static final String WATCH_HANDLER_BUNDLE = "watch_handler_bundle";
    private static final String DIALOG_BUNDLE = "dialog_bundle";
    private static final String GROUP_NAME = "group_name";
    private static final String SHOW_DO_NOT_ASK = "show_do_not_ask";
    private static final String ICON = "icon";
    private static final String MESSAGE = "message";
    private static final String CURRENT_PAGE_TEXT = "current_page_text";

    private final Context mContext;

    private ResultListener mResultListener;

    private Dialog mDialog;

    private String mGroupName;
    private boolean mShowDoNotAsk;

    private CharSequence mMessage;
    private String mCurrentPageText;
    private Icon mIcon;

    public GrantPermissionsWearViewHandler(Context context) {
        mContext = context;
    }

    @Override
    public GrantPermissionsWearViewHandler setResultListener(ResultListener listener) {
        mResultListener = listener;
        return this;
    }

    @Override
    public View createView() {
        return new Space(mContext);
    }

    @Override
    public void updateWindowAttributes(WindowManager.LayoutParams outLayoutParams) {
        outLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
        outLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
        outLayoutParams.format = PixelFormat.OPAQUE;
        outLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
        outLayoutParams.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
    }

    @Override
    public void updateUi(String groupName, int groupCount, int groupIndex, Icon icon,
            CharSequence message, CharSequence detailMessage, boolean[] buttonVisibilities) {
        // TODO: Handle detailMessage

        boolean showDoNotAsk = buttonVisibilities[DENY_AND_DONT_ASK_AGAIN_BUTTON];

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "updateUi() - groupName: " + groupName
                            + ", groupCount: " + groupCount
                            + ", groupIndex: " + groupIndex
                            + ", icon: " + icon
                            + ", message: " + message
                            + ", showDoNotAsk: " + showDoNotAsk);
        }

        mGroupName = groupName;
        mShowDoNotAsk = showDoNotAsk;
        mMessage = message;
        mIcon = icon;
        mCurrentPageText = groupCount > 1
                ? mContext.getString(R.string.current_permission_template,
                        groupIndex + 1, groupCount)
                : null;
        showDialog(null);
    }

    private void showDialog(Bundle savedInstanceState) {
        TypedArray a = mContext.obtainStyledAttributes(
                new int[] { android.R.attr.textColorPrimary });
        int color = a.getColor(0, mContext.getColor(android.R.color.white));
        a.recycle();
        Drawable drawable = mIcon == null ? null : mIcon.setTint(color).loadDrawable(mContext);

        SpannableStringBuilder ssb = new SpannableStringBuilder();
        if (!TextUtils.isEmpty(mCurrentPageText)) {
            ssb.append(mCurrentPageText, new TextAppearanceSpan(mContext, R.style.BreadcrumbText),
                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            ssb.append('\n');
        }
        if (!TextUtils.isEmpty(mMessage)) {
            ssb.append(mMessage, new TextAppearanceSpan(mContext, R.style.TitleText),
                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }

        if (mDialog != null) {
            mDialog.dismiss();
            mDialog = null;
        }

        if (mShowDoNotAsk) {
            AlertDialog alertDialog = new WearableDialogHelper.DialogBuilder(mContext)
                    .setPositiveIcon(R.drawable.confirm_button)
                    .setNeutralIcon(R.drawable.cancel_button)
                    .setNegativeIcon(R.drawable.deny_button)
                    .setTitle(ssb)
                    .setIcon(drawable)
                    .setPositiveButton(R.string.grant_dialog_button_allow, this)
                    .setNeutralButton(R.string.grant_dialog_button_deny, this)
                    .setNegativeButton(R.string.grant_dialog_button_deny_dont_ask_again, this)
                    .show();
            alertDialog.getButton(DialogInterface.BUTTON_POSITIVE)
                    .setId(R.id.permission_allow_button);
            alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL)
                    .setId(R.id.permission_deny_button);
            alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE)
                    .setId(R.id.permission_deny_dont_ask_again_button);

            mDialog = alertDialog;
        } else {
            AcceptDenyDialog acceptDenyDialog = new AcceptDenyDialog(mContext);
            acceptDenyDialog.setTitle(ssb);
            acceptDenyDialog.setIcon(drawable);
            acceptDenyDialog.setPositiveButton(this);
            acceptDenyDialog.setNegativeButton(this);
            acceptDenyDialog.show();
            acceptDenyDialog.getButton(DialogInterface.BUTTON_POSITIVE)
                    .setId(R.id.permission_allow_button);
            acceptDenyDialog.getButton(DialogInterface.BUTTON_NEGATIVE)
                    .setId(R.id.permission_deny_button);

            mDialog = acceptDenyDialog;
        }
        mDialog.setCancelable(false);

        if (savedInstanceState != null) {
            mDialog.onRestoreInstanceState(savedInstanceState);
        }
    }

    @Override
    public void saveInstanceState(Bundle outState) {
        Bundle b = new Bundle();
        b.putByte(SHOW_DO_NOT_ASK, (byte) (mShowDoNotAsk ? 1 : 0));
        b.putString(GROUP_NAME, mGroupName);
        b.putBundle(DIALOG_BUNDLE, mDialog.onSaveInstanceState());

        outState.putBundle(WATCH_HANDLER_BUNDLE, b);
    }

    @Override
    public void loadInstanceState(Bundle savedInstanceState) {
        Bundle b = savedInstanceState.getBundle(WATCH_HANDLER_BUNDLE);
        mShowDoNotAsk = b.getByte(SHOW_DO_NOT_ASK) == 1;
        mGroupName = b.getString(GROUP_NAME);
        showDialog(b.getBundle(DIALOG_BUNDLE));
    }

    @Override
    public void onBackPressed() {
        notifyListener(DENIED);
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        switch (which) {
            case DialogInterface.BUTTON_POSITIVE:
                notifyListener(GRANTED_ALWAYS);
                break;
            case DialogInterface.BUTTON_NEUTRAL:
                notifyListener(DENIED);
                break;
            case DialogInterface.BUTTON_NEGATIVE:
                /* In AlertDialog, the negative button is also a don't ask again button. */
                if (dialog instanceof AlertDialog) {
                    notifyListener(DENIED_DO_NOT_ASK_AGAIN);
                } else {
                    notifyListener(DENIED);
                }
                break;
        }
    }

    private void notifyListener(@Result int result) {
        if (mResultListener != null) {
            mResultListener.onPermissionGrantResult(mGroupName, result);
        }
    }
}
