/*
 * Copyright (C) 2009 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 com.android.settings.R;

import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;

/**
 * RequestPermissionActivity asks the user whether to enable discovery. This is
 * usually started by an application wanted to start bluetooth and or discovery
 */
public class RequestPermissionActivity extends Activity implements
        DialogInterface.OnClickListener {
    // Command line to test this
    // adb shell am start -a android.bluetooth.adapter.action.REQUEST_ENABLE
    // adb shell am start -a android.bluetooth.adapter.action.REQUEST_DISCOVERABLE

    private static final String TAG = "RequestPermissionActivity";

    private static final int MAX_DISCOVERABLE_TIMEOUT = 3600; // 1 hr

    // Non-error return code: BT is starting or has started successfully. Used
    // by this Activity and RequestPermissionHelperActivity
    /* package */ static final int RESULT_BT_STARTING_OR_STARTED = -1000;

    private static final int REQUEST_CODE_START_BT = 1;

    private LocalBluetoothAdapter mLocalAdapter;

    private int mTimeout = BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT;

    /*
     * True if bluetooth wasn't enabled and RequestPermissionHelperActivity was
     * started to ask the user and start bt.
     *
     * If/when that activity returns successfully, display please wait msg then
     * go away when bt has started and discovery mode has been enabled.
     */
    private boolean mNeededToEnableBluetooth;

    // True if requesting BT to be turned on
    // False if requesting BT to be turned on + discoverable mode
    private boolean mEnableOnly;

    private boolean mUserConfirmed;

    private AlertDialog mDialog;

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent == null) {
                return;
            }
            if (mNeededToEnableBluetooth
                    && BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothDevice.ERROR);
                if (state == BluetoothAdapter.STATE_ON) {
                    if (mUserConfirmed) {
                        proceedAndFinish();
                    }
                }
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Note: initializes mLocalAdapter and returns true on error
        if (parseIntent()) {
            finish();
            return;
        }

        int btState = mLocalAdapter.getState();

        switch (btState) {
            case BluetoothAdapter.STATE_OFF:
            case BluetoothAdapter.STATE_TURNING_OFF:
            case BluetoothAdapter.STATE_TURNING_ON:
                /*
                 * Strictly speaking STATE_TURNING_ON belong with STATE_ON;
                 * however, BT may not be ready when the user clicks yes and we
                 * would fail to turn on discovery mode. By kicking this to the
                 * RequestPermissionHelperActivity, this class will handle that
                 * case via the broadcast receiver.
                 */

                /*
                 * Start the helper activity to:
                 * 1) ask the user about enabling bt AND discovery
                 * 2) enable BT upon confirmation
                 */
                registerReceiver(mReceiver,
                        new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
                Intent intent = new Intent();
                intent.setClass(this, RequestPermissionHelperActivity.class);
                if (mEnableOnly) {
                    intent.setAction(RequestPermissionHelperActivity.ACTION_INTERNAL_REQUEST_BT_ON);
                } else {
                    intent.setAction(RequestPermissionHelperActivity.
                            ACTION_INTERNAL_REQUEST_BT_ON_AND_DISCOVERABLE);
                    intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, mTimeout);
                }
                startActivityForResult(intent, REQUEST_CODE_START_BT);
                mNeededToEnableBluetooth = true;
                break;
            case BluetoothAdapter.STATE_ON:
                if (mEnableOnly) {
                    // Nothing to do. Already enabled.
                    proceedAndFinish();
                } else {
                    // Ask the user about enabling discovery mode
                    createDialog();
                }
                break;
            default:
                Log.e(TAG, "Unknown adapter state: " + btState);
        }
    }

    private void createDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setIcon(android.R.drawable.ic_dialog_info);
        builder.setTitle(getString(R.string.bluetooth_permission_request));

        if (mNeededToEnableBluetooth) {
            // RequestPermissionHelperActivity has gotten confirmation from user
            // to turn on BT
            builder.setMessage(getString(R.string.bluetooth_turning_on));
            builder.setCancelable(false);
        } else {
            // Ask the user whether to turn on discovery mode or not
            // For lasting discoverable mode there is a different message
            if (mTimeout == BluetoothDiscoverableEnabler.DISCOVERABLE_TIMEOUT_NEVER) {
                builder.setMessage(
                        getString(R.string.bluetooth_ask_lasting_discovery));
            } else {
                builder.setMessage(
                        getString(R.string.bluetooth_ask_discovery, mTimeout));
            }
            builder.setPositiveButton(getString(R.string.yes), this);
            builder.setNegativeButton(getString(R.string.no), this);
        }

        mDialog = builder.create();
        mDialog.show();

        if (getResources().getBoolean(R.bool.auto_confirm_bluetooth_activation_dialog) == true) {
            // dismiss dialog immediately if settings say so
            onClick(null, DialogInterface.BUTTON_POSITIVE);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode != REQUEST_CODE_START_BT) {
            Log.e(TAG, "Unexpected onActivityResult " + requestCode + ' ' + resultCode);
            setResult(RESULT_CANCELED);
            finish();
            return;
        }
        if (resultCode != RESULT_BT_STARTING_OR_STARTED) {
            setResult(resultCode);
            finish();
            return;
        }

        // Back from RequestPermissionHelperActivity. User confirmed to enable
        // BT and discoverable mode.
        mUserConfirmed = true;

        if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON) {
            proceedAndFinish();
        } else {
            // If BT is not up yet, show "Turning on Bluetooth..."
            createDialog();
        }
    }

    public void onClick(DialogInterface dialog, int which) {
        switch (which) {
            case DialogInterface.BUTTON_POSITIVE:
                proceedAndFinish();
                break;

            case DialogInterface.BUTTON_NEGATIVE:
                setResult(RESULT_CANCELED);
                finish();
                break;
        }
    }

    private void proceedAndFinish() {
        int returnCode;

        if (mEnableOnly) {
            // BT enabled. Done
            returnCode = RESULT_OK;
        } else if (mLocalAdapter.setScanMode(
                BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, mTimeout)) {
            // If already in discoverable mode, this will extend the timeout.
            long endTime = System.currentTimeMillis() + (long) mTimeout * 1000;
            LocalBluetoothPreferences.persistDiscoverableEndTimestamp(
                    this, endTime);
            if (0 < mTimeout) {
               BluetoothDiscoverableTimeoutReceiver.setDiscoverableAlarm(this, endTime);
            }
            returnCode = mTimeout;
            // Activity.RESULT_FIRST_USER should be 1
            if (returnCode < RESULT_FIRST_USER) {
                returnCode = RESULT_FIRST_USER;
            }
        } else {
            returnCode = RESULT_CANCELED;
        }

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

        setResult(returnCode);
        finish();
    }

    /**
     * Parse the received Intent and initialize mLocalBluetoothAdapter.
     * @return true if an error occurred; false otherwise
     */
    private boolean parseIntent() {
        Intent intent = getIntent();
        if (intent != null && intent.getAction().equals(BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
            mEnableOnly = true;
        } else if (intent != null
                && intent.getAction().equals(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)) {
            mTimeout = intent.getIntExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,
                    BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT);

            Log.d(TAG, "Setting Bluetooth Discoverable Timeout = " + mTimeout);

            if (mTimeout < 0 || mTimeout > MAX_DISCOVERABLE_TIMEOUT) {
                mTimeout = BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT;
            }
        } else {
            Log.e(TAG, "Error: this activity may be started only with intent "
                    + BluetoothAdapter.ACTION_REQUEST_ENABLE + " or "
                    + BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
            setResult(RESULT_CANCELED);
            return true;
        }

        LocalBluetoothManager manager = LocalBluetoothManager.getInstance(this);
        if (manager == null) {
            Log.e(TAG, "Error: there's a problem starting Bluetooth");
            setResult(RESULT_CANCELED);
            return true;
        }
        mLocalAdapter = manager.getBluetoothAdapter();

        return false;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mNeededToEnableBluetooth) {
            unregisterReceiver(mReceiver);
        }
    }

    @Override
    public void onBackPressed() {
        setResult(RESULT_CANCELED);
        super.onBackPressed();
    }
}
