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

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputFilter;
import android.text.InputFilter.LengthFilter;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;

/**
 * A dialogFragment used by {@link BluetoothPairingDialog} to create an appropriately styled dialog
 * for the bluetooth device.
 */
public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment implements
        TextWatcher, OnClickListener {

    private static final String TAG = "BTPairingDialogFragment";

    private AlertDialog.Builder mBuilder;
    private AlertDialog mDialog;
    private BluetoothPairingController mPairingController;
    private BluetoothPairingDialog mPairingDialogActivity;
    private EditText mPairingView;
    /**
     * The interface we expect a listener to implement. Typically this should be done by
     * the controller.
     */
    public interface BluetoothPairingDialogListener {

        void onDialogNegativeClick(BluetoothPairingDialogFragment dialog);

        void onDialogPositiveClick(BluetoothPairingDialogFragment dialog);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        if (!isPairingControllerSet()) {
            throw new IllegalStateException(
                "Must call setPairingController() before showing dialog");
        }
        if (!isPairingDialogActivitySet()) {
            throw new IllegalStateException(
                "Must call setPairingDialogActivity() before showing dialog");
        }
        mBuilder = new AlertDialog.Builder(getActivity());
        mDialog = setupDialog();
        mDialog.setCanceledOnTouchOutside(false);
        return mDialog;
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }

    @Override
    public void afterTextChanged(Editable s) {
        // enable the positive button when we detect potentially valid input
        Button positiveButton = mDialog.getButton(DialogInterface.BUTTON_POSITIVE);
        if (positiveButton != null) {
            positiveButton.setEnabled(mPairingController.isPasskeyValid(s));
        }
        // notify the controller about user input
        mPairingController.updateUserInput(s.toString());
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        if (which == DialogInterface.BUTTON_POSITIVE) {
            mPairingController.onDialogPositiveClick(this);
        } else if (which == DialogInterface.BUTTON_NEGATIVE) {
            mPairingController.onDialogNegativeClick(this);
        }
        mPairingDialogActivity.dismiss();
    }

    @Override
    public int getMetricsCategory() {
        return MetricsEvent.BLUETOOTH_DIALOG_FRAGMENT;
    }

    /**
     * Used in testing to get a reference to the dialog.
     * @return - The fragments current dialog
     */
    protected AlertDialog getmDialog() {
        return mDialog;
    }

    /**
     * Sets the controller that the fragment should use. this method MUST be called
     * before you try to show the dialog or an error will be thrown. An implementation
     * of a pairing controller can be found at {@link BluetoothPairingController}. A
     * controller may not be substituted once it is assigned. Forcibly switching a
     * controller for a new one will lead to undefined behavior.
     */
    void setPairingController(BluetoothPairingController pairingController) {
        if (isPairingControllerSet()) {
            throw new IllegalStateException("The controller can only be set once. "
                    + "Forcibly replacing it will lead to undefined behavior");
        }
        mPairingController = pairingController;
    }

    /**
     * Checks whether mPairingController is set
     * @return True when mPairingController is set, False otherwise
     */
    boolean isPairingControllerSet() {
        return mPairingController != null;
    }

    /**
     * Sets the BluetoothPairingDialog activity that started this fragment
     * @param pairingDialogActivity The pairing dialog activty that started this fragment
     */
    void setPairingDialogActivity(BluetoothPairingDialog pairingDialogActivity) {
        if (isPairingDialogActivitySet()) {
            throw new IllegalStateException("The pairing dialog activity can only be set once");
        }
        mPairingDialogActivity = pairingDialogActivity;
    }

    /**
     * Checks whether mPairingDialogActivity is set
     * @return True when mPairingDialogActivity is set, False otherwise
     */
    boolean isPairingDialogActivitySet() {
        return mPairingDialogActivity != null;
    }

    /**
     * Creates the appropriate type of dialog and returns it.
     */
    private AlertDialog setupDialog() {
        AlertDialog dialog;
        switch (mPairingController.getDialogType()) {
            case BluetoothPairingController.USER_ENTRY_DIALOG:
                dialog = createUserEntryDialog();
                break;
            case BluetoothPairingController.CONFIRMATION_DIALOG:
                dialog = createConsentDialog();
                break;
            case BluetoothPairingController.DISPLAY_PASSKEY_DIALOG:
                dialog = createDisplayPasskeyOrPinDialog();
                break;
            default:
                dialog = null;
                Log.e(TAG, "Incorrect pairing type received, not showing any dialog");
        }
        return dialog;
    }

    /**
     * Helper method to return the text of the pin entry field - this exists primarily to help us
     * simulate having existing text when the dialog is recreated, for example after a screen
     * rotation.
     */
    @VisibleForTesting
    CharSequence getPairingViewText() {
        if (mPairingView != null) {
            return mPairingView.getText();
        }
        return null;
    }

    /**
     * Returns a dialog with UI elements that allow a user to provide input.
     */
    private AlertDialog createUserEntryDialog() {
        mBuilder.setTitle(getString(R.string.bluetooth_pairing_request,
                mPairingController.getDeviceName()));
        mBuilder.setView(createPinEntryView());
        mBuilder.setPositiveButton(getString(android.R.string.ok), this);
        mBuilder.setNegativeButton(getString(android.R.string.cancel), this);
        AlertDialog dialog = mBuilder.create();
        dialog.setOnShowListener(d -> {
            if (TextUtils.isEmpty(getPairingViewText())) {
                mDialog.getButton(Dialog.BUTTON_POSITIVE).setEnabled(false);
            }
            if (mPairingView != null && mPairingView.requestFocus()) {
                InputMethodManager imm = (InputMethodManager)
                        getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                if (imm != null) {
                    imm.showSoftInput(mPairingView, InputMethodManager.SHOW_IMPLICIT);
                }
            }
        });
        return dialog;
    }

    /**
     * Creates the custom view with UI elements for user input.
     */
    private View createPinEntryView() {
        View view = getActivity().getLayoutInflater().inflate(R.layout.bluetooth_pin_entry, null);
        TextView messageViewCaptionHint = (TextView) view.findViewById(R.id.pin_values_hint);
        TextView messageView2 = (TextView) view.findViewById(R.id.message_below_pin);
        CheckBox alphanumericPin = (CheckBox) view.findViewById(R.id.alphanumeric_pin);
        CheckBox contactSharing = (CheckBox) view.findViewById(
                R.id.phonebook_sharing_message_entry_pin);
        contactSharing.setText(getString(R.string.bluetooth_pairing_shares_phonebook,
                mPairingController.getDeviceName()));
        EditText pairingView = (EditText) view.findViewById(R.id.text);

        contactSharing.setVisibility(mPairingController.isProfileReady()
                ? View.GONE : View.VISIBLE);
        mPairingController.setContactSharingState();
        contactSharing.setOnCheckedChangeListener(mPairingController);
        contactSharing.setChecked(mPairingController.getContactSharingState());

        mPairingView = pairingView;

        pairingView.setInputType(InputType.TYPE_CLASS_NUMBER);
        pairingView.addTextChangedListener(this);
        alphanumericPin.setOnCheckedChangeListener((buttonView, isChecked) -> {
            // change input type for soft keyboard to numeric or alphanumeric
            if (isChecked) {
                mPairingView.setInputType(InputType.TYPE_CLASS_TEXT);
            } else {
                mPairingView.setInputType(InputType.TYPE_CLASS_NUMBER);
            }
        });

        int messageId = mPairingController.getDeviceVariantMessageId();
        int messageIdHint = mPairingController.getDeviceVariantMessageHintId();
        int maxLength = mPairingController.getDeviceMaxPasskeyLength();
        alphanumericPin.setVisibility(mPairingController.pairingCodeIsAlphanumeric()
                ? View.VISIBLE : View.GONE);
        if (messageId != BluetoothPairingController.INVALID_DIALOG_TYPE) {
            messageView2.setText(messageId);
        } else {
            messageView2.setVisibility(View.GONE);
        }
        if (messageIdHint != BluetoothPairingController.INVALID_DIALOG_TYPE) {
            messageViewCaptionHint.setText(messageIdHint);
        } else {
            messageViewCaptionHint.setVisibility(View.GONE);
        }
        pairingView.setFilters(new InputFilter[]{
                new LengthFilter(maxLength)});

        return view;
    }

    /**
     * Creates a dialog with UI elements that allow the user to confirm a pairing request.
     */
    private AlertDialog createConfirmationDialog() {
        mBuilder.setTitle(getString(R.string.bluetooth_pairing_request,
                mPairingController.getDeviceName()));
        mBuilder.setView(createView());
        mBuilder.setPositiveButton(getString(R.string.bluetooth_pairing_accept), this);
        mBuilder.setNegativeButton(getString(R.string.bluetooth_pairing_decline), this);
        AlertDialog dialog = mBuilder.create();
        return dialog;
    }

    /**
     * Creates a dialog with UI elements that allow the user to consent to a pairing request.
     */
    private AlertDialog createConsentDialog() {
        return createConfirmationDialog();
    }

    /**
     * Creates a dialog that informs users of a pairing request and shows them the passkey/pin
     * of the device.
     */
    private AlertDialog createDisplayPasskeyOrPinDialog() {
        mBuilder.setTitle(getString(R.string.bluetooth_pairing_request,
                mPairingController.getDeviceName()));
        mBuilder.setView(createView());
        mBuilder.setNegativeButton(getString(android.R.string.cancel), this);
        AlertDialog dialog = mBuilder.create();

        // Tell the controller the dialog has been created.
        mPairingController.notifyDialogDisplayed();

        return dialog;
    }

    /**
     * Creates a custom view for dialogs which need to show users additional information but do
     * not require user input.
     */
    private View createView() {
        View view = getActivity().getLayoutInflater().inflate(R.layout.bluetooth_pin_confirm, null);
        TextView pairingViewCaption = (TextView) view.findViewById(R.id.pairing_caption);
        TextView pairingViewContent = (TextView) view.findViewById(R.id.pairing_subhead);
        TextView messagePairing = (TextView) view.findViewById(R.id.pairing_code_message);
        CheckBox contactSharing = (CheckBox) view.findViewById(
                R.id.phonebook_sharing_message_confirm_pin);
        contactSharing.setText(getString(R.string.bluetooth_pairing_shares_phonebook,
                mPairingController.getDeviceName()));

        contactSharing.setVisibility(
                mPairingController.isProfileReady() ? View.GONE : View.VISIBLE);
        mPairingController.setContactSharingState();
        contactSharing.setChecked(mPairingController.getContactSharingState());
        contactSharing.setOnCheckedChangeListener(mPairingController);

        messagePairing.setVisibility(mPairingController.isDisplayPairingKeyVariant()
                ? View.VISIBLE : View.GONE);
        if (mPairingController.hasPairingContent()) {
            pairingViewCaption.setVisibility(View.VISIBLE);
            pairingViewContent.setVisibility(View.VISIBLE);
            pairingViewContent.setText(mPairingController.getPairingContent());
        }
        return view;
    }

}
