/*
 * 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.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.Intent;
import android.text.Editable;
import android.util.Log;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;

import androidx.annotation.VisibleForTesting;

import com.android.settings.R;
import com.android.settings.bluetooth.BluetoothPairingDialogFragment.BluetoothPairingDialogListener;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfile;

import java.util.Locale;

/**
 * A controller used by {@link BluetoothPairingDialog} to manage connection state while we try to
 * pair with a bluetooth device. It includes methods that allow the
 * {@link BluetoothPairingDialogFragment} to interrogate the current state as well.
 */
public class BluetoothPairingController implements OnCheckedChangeListener,
        BluetoothPairingDialogListener {

    private static final String TAG = "BTPairingController";

    // Different types of dialogs we can map to
    public static final int INVALID_DIALOG_TYPE = -1;
    public static final int USER_ENTRY_DIALOG = 0;
    public static final int CONFIRMATION_DIALOG = 1;
    public static final int DISPLAY_PASSKEY_DIALOG = 2;

    private static final int BLUETOOTH_PIN_MAX_LENGTH = 16;
    private static final int BLUETOOTH_PASSKEY_MAX_LENGTH = 6;

    // Bluetooth dependencies for the connection we are trying to establish
    private LocalBluetoothManager mBluetoothManager;
    private BluetoothDevice mDevice;
    @VisibleForTesting
    int mType;
    private String mUserInput;
    private String mPasskeyFormatted;
    private int mPasskey;
    private int mInitiator;
    private String mDeviceName;
    private LocalBluetoothProfile mPbapClientProfile;
    private boolean mPbapAllowed;

    /**
     * Creates an instance of a BluetoothPairingController.
     *
     * @param intent - must contain {@link BluetoothDevice#EXTRA_PAIRING_VARIANT}, {@link
     * BluetoothDevice#EXTRA_PAIRING_KEY}, and {@link BluetoothDevice#EXTRA_DEVICE}. Missing extra
     * will lead to undefined behavior.
     */
    public BluetoothPairingController(Intent intent, Context context) {
        mBluetoothManager = Utils.getLocalBtManager(context);
        mDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

        String message = "";
        if (mBluetoothManager == null) {
            throw new IllegalStateException("Could not obtain LocalBluetoothManager");
        } else if (mDevice == null) {
            throw new IllegalStateException("Could not find BluetoothDevice");
        }

        mType = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR);
        mPasskey = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_KEY, BluetoothDevice.ERROR);
        mInitiator =
                intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_INITIATOR, BluetoothDevice.ERROR);
        mDeviceName = mBluetoothManager.getCachedDeviceManager().getName(mDevice);
        mPbapClientProfile = mBluetoothManager.getProfileManager().getPbapClientProfile();
        mPasskeyFormatted = formatKey(mPasskey);
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (isChecked) {
            mPbapAllowed = true;
        } else {
            mPbapAllowed = false;
        }
    }

    @Override
    public void onDialogPositiveClick(BluetoothPairingDialogFragment dialog) {
        if (mPbapAllowed) {
            mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED);
        } else {
            mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED);
        }

        if (getDialogType() == USER_ENTRY_DIALOG) {
            onPair(mUserInput);
        } else {
            onPair(null);
        }
    }

    @Override
    public void onDialogNegativeClick(BluetoothPairingDialogFragment dialog) {
        mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED);
        onCancel();
    }

    /**
     * A method for querying which bluetooth pairing dialog fragment variant this device requires.
     *
     * @return - The dialog view variant needed for this device.
     */
    public int getDialogType() {
        switch (mType) {
            case BluetoothDevice.PAIRING_VARIANT_PIN:
            case BluetoothDevice.PAIRING_VARIANT_PIN_16_DIGITS:
            case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
                return USER_ENTRY_DIALOG;

            case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:
            case BluetoothDevice.PAIRING_VARIANT_CONSENT:
            case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:
                return CONFIRMATION_DIALOG;

            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY:
            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN:
                return DISPLAY_PASSKEY_DIALOG;

            default:
                return INVALID_DIALOG_TYPE;
        }
    }

    /**
     * @return - A string containing the name provided by the device.
     */
    public String getDeviceName() {
        return mDeviceName;
    }

    /**
     * A method for querying if the bluetooth device has a profile already set up on this device.
     *
     * @return - A boolean indicating if the device has previous knowledge of a profile for this
     * device.
     */
    public boolean isProfileReady() {
        return mPbapClientProfile != null && mPbapClientProfile.isProfileReady();
    }

    /**
     * A method for querying if the bluetooth device has access to contacts on the device.
     *
     * @return - A boolean indicating if the bluetooth device has permission to access the device
     * contacts
     */
    public boolean getContactSharingState() {
        switch (mDevice.getPhonebookAccessPermission()) {
            case BluetoothDevice.ACCESS_ALLOWED:
                return true;
            case BluetoothDevice.ACCESS_REJECTED:
                return false;
            default:
                if (mDevice.getBluetoothClass().getDeviceClass()
                        == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE) {
                    return BluetoothDevice.EXTRA_PAIRING_INITIATOR_FOREGROUND == mInitiator;
                }
                return false;
        }
    }

    /**
     * Update Phone book permission
     *
     */
     public void  setContactSharingState() {
         final int permission = mDevice.getPhonebookAccessPermission();
         if (permission == BluetoothDevice.ACCESS_ALLOWED
                 || (permission == BluetoothDevice.ACCESS_UNKNOWN && mDevice.getBluetoothClass().
                        getDeviceClass() == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE)) {
             onCheckedChanged(null, true);
         } else {
             onCheckedChanged(null, false);
         }

     }

    /**
     * A method for querying if the provided editable is a valid passkey/pin format for this device.
     *
     * @param s - The passkey/pin
     * @return - A boolean indicating if the passkey/pin is of the correct format.
     */
    public boolean isPasskeyValid(Editable s) {
        boolean requires16Digits = mType == BluetoothDevice.PAIRING_VARIANT_PIN_16_DIGITS;
        return s.length() >= 16 && requires16Digits || s.length() > 0 && !requires16Digits;
    }

    /**
     * A method for querying what message should be shown to the user as additional text in the
     * dialog for this device. Returns -1 to indicate a device type that does not use this message.
     *
     * @return - The message ID to show the user.
     */
    public int getDeviceVariantMessageId() {
        switch (mType) {
            case BluetoothDevice.PAIRING_VARIANT_PIN_16_DIGITS:
            case BluetoothDevice.PAIRING_VARIANT_PIN:
                return R.string.bluetooth_enter_pin_other_device;

            case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
                return R.string.bluetooth_enter_passkey_other_device;

            default:
                return INVALID_DIALOG_TYPE;
        }
    }

    /**
     * A method for querying what message hint should be shown to the user as additional text in the
     * dialog for this device. Returns -1 to indicate a device type that does not use this message.
     *
     * @return - The message ID to show the user.
     */
    public int getDeviceVariantMessageHintId() {
        switch (mType) {
            case BluetoothDevice.PAIRING_VARIANT_PIN_16_DIGITS:
                return R.string.bluetooth_pin_values_hint_16_digits;

            case BluetoothDevice.PAIRING_VARIANT_PIN:
            case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
                return R.string.bluetooth_pin_values_hint;

            default:
                return INVALID_DIALOG_TYPE;
        }
    }

    /**
     * A method for querying the maximum passkey/pin length for this device.
     *
     * @return - An int indicating the maximum length
     */
    public int getDeviceMaxPasskeyLength() {
        switch (mType) {
            case BluetoothDevice.PAIRING_VARIANT_PIN_16_DIGITS:
            case BluetoothDevice.PAIRING_VARIANT_PIN:
                return BLUETOOTH_PIN_MAX_LENGTH;

            case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
                return BLUETOOTH_PASSKEY_MAX_LENGTH;

            default:
                return 0;
        }

    }

    /**
     * A method for querying if the device uses an alphanumeric passkey.
     *
     * @return - a boolean indicating if the passkey can be alphanumeric.
     */
    public boolean pairingCodeIsAlphanumeric() {
        switch (mType) {
            case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
                return false;

            default:
                return true;
        }
    }

    /**
     * A method used by the dialogfragment to notify the controller that the dialog has been
     * displayed for bluetooth device types that just care about it being displayed.
     */
    protected void notifyDialogDisplayed() {
        // send an OK to the framework, indicating that the dialog has been displayed.
        if (mType == BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY) {
            mDevice.setPairingConfirmation(true);
        } else if (mType == BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN) {
            mDevice.setPin(mPasskeyFormatted);
        }
    }

    /**
     * A method for querying if this bluetooth device type has a key it would like displayed
     * to the user.
     *
     * @return - A boolean indicating if a key exists which should be displayed to the user.
     */
    public boolean isDisplayPairingKeyVariant() {
        switch (mType) {
            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY:
            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN:
            case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:
                return true;
            default:
                return false;
        }
    }

    /**
     * A method for querying if this bluetooth device type has other content it would like displayed
     * to the user.
     *
     * @return - A boolean indicating if content exists which should be displayed to the user.
     */
    public boolean hasPairingContent() {
        switch (mType) {
            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY:
            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN:
            case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:
                return true;

            default:
                return false;
        }
    }

    /**
     * A method for obtaining any additional content this bluetooth device has for displaying to the
     * user.
     *
     * @return - A string containing the additional content, null if none exists.
     * @see {@link BluetoothPairingController#hasPairingContent()}
     */
    public String getPairingContent() {
        if (hasPairingContent()) {
            return mPasskeyFormatted;
        } else {
            return null;
        }
    }

    /**
     * A method that exists to allow the fragment to update the controller with input the user has
     * provided in the fragment.
     *
     * @param input - A string containing the user input.
     */
    protected void updateUserInput(String input) {
        mUserInput = input;
    }

    /**
     * Returns the provided passkey in a format that this device expects. Only works for numeric
     * passkeys/pins.
     *
     * @param passkey - An integer containing the passkey to format.
     * @return - A string containing the formatted passkey/pin
     */
    private String formatKey(int passkey) {
        switch (mType) {
            case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:
            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY:
                return String.format(Locale.US, "%06d", passkey);

            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN:
                return String.format("%04d", passkey);

            default:
                return null;
        }
    }

    /**
     * handles the necessary communication with the bluetooth device to establish a successful
     * pairing
     *
     * @param passkey - The passkey we will attempt to pair to the device with.
     */
    private void onPair(String passkey) {
        Log.d(TAG, "Pairing dialog accepted");
        switch (mType) {
            case BluetoothDevice.PAIRING_VARIANT_PIN:
            case BluetoothDevice.PAIRING_VARIANT_PIN_16_DIGITS:
                mDevice.setPin(passkey);
                break;


            case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:
            case BluetoothDevice.PAIRING_VARIANT_CONSENT:
                mDevice.setPairingConfirmation(true);
                break;

            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY:
            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN:
            case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:
            case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
                // Do nothing.
                break;

            default:
                Log.e(TAG, "Incorrect pairing type received");
        }
    }

    /**
     * A method for properly ending communication with the bluetooth device. Will be called by the
     * {@link BluetoothPairingDialogFragment} when it is dismissed.
     */
    public void onCancel() {
        Log.d(TAG, "Pairing dialog canceled");
        mDevice.cancelPairing();
    }

    /**
     * A method for checking if this device is equal to another device.
     *
     * @param device - The other device being compared to this device.
     * @return - A boolean indicating if the devices were equal.
     */
    public boolean deviceEquals(BluetoothDevice device) {
        return mDevice == device;
    }
}
