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

import static com.android.compatibility.common.util.ShellIdentityUtils.invokeWithShellPermissions;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
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.os.Handler;
import android.util.Log;
import android.widget.ListView;


import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;

import java.util.ArrayList;
import java.util.List;

public class BleClientTestBaseActivity extends PassFailButtons.Activity {
    public static final String TAG = "BleClientTestBase";

    private static final boolean STEP_EXECUTION = false;

    private static final int PASS_FLAG_CONNECT = 0x1;
    private static final int PASS_FLAG_DISCOVER = 0x2;
    private static final int PASS_FLAG_READ_CHARACTERISTIC = 0x4;
    private static final int PASS_FLAG_WRITE_CHARACTERISTIC = 0x8;
    private static final int PASS_FLAG_RELIABLE_WRITE = 0x10;
    private static final int PASS_FLAG_NOTIFY_CHARACTERISTIC = 0x20;
    private static final int PASS_FLAG_READ_DESCRIPTOR = 0x40;
    private static final int PASS_FLAG_WRITE_DESCRIPTOR = 0x80;
    private static final int PASS_FLAG_READ_RSSI = 0x100;
    private static final int PASS_FLAG_DISCONNECT = 0x200;
    private static final int PASS_FLAG_READ_CHARACTERISTIC_NO_PERMISSION = 0x400;
    private static final int PASS_FLAG_WRITE_CHARACTERISTIC_NO_PERMISSION = 0x800;
    private static final int PASS_FLAG_READ_DESCRIPTOR_NO_PERMISSION = 0x1000;
    private static final int PASS_FLAG_WRITE_DESCRIPTOR_NO_PERMISSION = 0x2000;
    private static final int PASS_FLAG_MTU_CHANGE_23BYTES = 0x4000;
    private static final int PASS_FLAG_INDICATE_CHARACTERISTIC = 0x8000;
    private static final int PASS_FLAG_MTU_CHANGE_512BYTES = 0x10000;
    private static final int PASS_FLAG_RELIABLE_WRITE_BAD_RESP = 0x20000;
    private static final int PASS_FLAG_ON_SERVICE_CHANGED = 0x40000;
    private static final int PASS_FLAG_READ_PHY = 0x80000;
    private static final int PASS_FLAG_ALL = 0xFFFFF;

    private final int BLE_CLIENT_CONNECT = 0;
    private final int BLE_BLE_DISCOVER_SERVICE = 1;
    private final int BLE_READ_CHARACTERISTIC = 2;
    private final int BLE_WRITE_CHARACTERISTIC = 3;
    private final int BLE_REQUEST_MTU_23BYTES = 4;
    private final int BLE_REQUEST_MTU_512BYTES = 5;
    private final int BLE_READ_CHARACTERISTIC_NO_PERMISSION = 6;
    private final int BLE_WRITE_CHARACTERISTIC_NO_PERMISSION = 7;
    private final int BLE_RELIABLE_WRITE = 8;
    private final int BLE_RELIABLE_WRITE_BAD_RESP = 9;
    private final int BLE_NOTIFY_CHARACTERISTIC = 9;    //10;
    private final int BLE_INDICATE_CHARACTERISTIC = 10;  //11;
    private final int BLE_READ_DESCRIPTOR = 11; //12;
    private final int BLE_WRITE_DESCRIPTOR = 12;    //13;
    private final int BLE_READ_DESCRIPTOR_NO_PERMISSION = 13;   //14;
    private final int BLE_WRITE_DESCRIPTOR_NO_PERMISSION = 14;  //15;
    private final int BLE_READ_RSSI = 15;   //16;
    private final int BLE_READ_PHY = 15;   //16; //17;
    private final int BLE_ON_SERVICE_CHANGED = 16; //17; //18;
    private final int BLE_CLIENT_DISCONNECT = 17;  //18; //19;

    private TestAdapter mTestAdapter;
    private long mPassed;
    private Dialog mDialog;
    private Handler mHandler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.ble_server_start);
        setPassFailButtonClickListeners();
        getPassButton().setEnabled(false);

        mTestAdapter = new TestAdapter(this, setupTestList());
        ListView listView = (ListView) findViewById(R.id.ble_server_tests);
        listView.setAdapter(mTestAdapter);

        mPassed = 0;
        mHandler = new Handler();
    }

    @Override
    public void onStart() {
        super.onStart();

        IntentFilter filter = new IntentFilter();
        filter.addAction(BleClientService.BLE_BLUETOOTH_CONNECTED);
        filter.addAction(BleClientService.BLE_BLUETOOTH_DISCONNECTED);
        filter.addAction(BleClientService.BLE_SERVICES_DISCOVERED);
        filter.addAction(BleClientService.BLE_MTU_CHANGED_23BYTES);
        filter.addAction(BleClientService.BLE_MTU_CHANGED_512BYTES);
        filter.addAction(BleClientService.BLE_CHARACTERISTIC_READ);
        filter.addAction(BleClientService.BLE_CHARACTERISTIC_WRITE);
        filter.addAction(BleClientService.BLE_CHARACTERISTIC_CHANGED);
        filter.addAction(BleClientService.BLE_DESCRIPTOR_READ);
        filter.addAction(BleClientService.BLE_DESCRIPTOR_WRITE);
        filter.addAction(BleClientService.BLE_RELIABLE_WRITE_COMPLETED);
        filter.addAction(BleClientService.BLE_RELIABLE_WRITE_BAD_RESP_COMPLETED);
        filter.addAction(BleClientService.BLE_READ_REMOTE_RSSI);
        filter.addAction(BleClientService.BLE_PHY_READ);
        filter.addAction(BleClientService.BLE_ON_SERVICE_CHANGED);
        filter.addAction(BleClientService.BLE_CHARACTERISTIC_READ_NOPERMISSION);
        filter.addAction(BleClientService.BLE_CHARACTERISTIC_WRITE_NOPERMISSION);
        filter.addAction(BleClientService.BLE_DESCRIPTOR_READ_NOPERMISSION);
        filter.addAction(BleClientService.BLE_DESCRIPTOR_WRITE_NOPERMISSION);
        filter.addAction(BleClientService.BLE_CHARACTERISTIC_INDICATED);
        filter.addAction(BleClientService.BLE_BLUETOOTH_DISABLED);
        filter.addAction(BleClientService.BLE_BLUETOOTH_MISMATCH_SECURE);
        filter.addAction(BleClientService.BLE_BLUETOOTH_MISMATCH_INSECURE);
        filter.addAction(BleClientService.BLE_CLIENT_ERROR);

        registerReceiver(mBroadcast, filter);
    }

    @Override
    public void onPause() {
        super.onPause();
        closeDialog();
    }

    @Override
    public void onStop() {
        super.onStop();
        unregisterReceiver(mBroadcast);
    }

    private synchronized void closeDialog() {
        if (mDialog != null) {
            mDialog.dismiss();
            mDialog = null;
        }
    }

    private synchronized void showProgressDialog() {
        closeDialog();

        ProgressDialog dialog = new ProgressDialog(this);
        dialog.setTitle(R.string.ble_test_running);
        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        dialog.setMessage(getString(R.string.ble_test_running_message));
        dialog.setCanceledOnTouchOutside(false);
        mDialog = dialog;
        mDialog.show();
    }

    private List<Integer> setupTestList() {
        ArrayList<Integer> testList = new ArrayList<Integer>();
        testList.add(R.string.ble_client_connect_name);
        testList.add(R.string.ble_discover_service_name);
        testList.add(R.string.ble_read_characteristic_name);
        testList.add(R.string.ble_write_characteristic_name);
        testList.add(R.string.ble_mtu_23_name);
        testList.add(R.string.ble_mtu_512_name);
        testList.add(R.string.ble_read_characteristic_nopermission_name);
        testList.add(R.string.ble_write_characteristic_nopermission_name);
        testList.add(R.string.ble_reliable_write_name);
//        testList.add(R.string.ble_reliable_write_bad_resp_name);
        testList.add(R.string.ble_notify_characteristic_name);
        testList.add(R.string.ble_indicate_characteristic_name);
        testList.add(R.string.ble_read_descriptor_name);
        testList.add(R.string.ble_write_descriptor_name);
        testList.add(R.string.ble_read_descriptor_nopermission_name);
        testList.add(R.string.ble_write_descriptor_nopermission_name);
// TODO: too flaky b/34951749
//        testList.add(R.string.ble_read_rssi_name);
        testList.add(R.string.ble_read_phy_name);
        testList.add(R.string.ble_on_service_changed);
        testList.add(R.string.ble_client_disconnect_name);

        return testList;
    }

    private void showErrorDialog(int titleId, int messageId, boolean finish) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this)
                .setTitle(titleId)
                .setMessage(messageId);
        if (finish) {
            builder.setOnCancelListener(new Dialog.OnCancelListener() {
                @Override
                public void onCancel(DialogInterface dialog) {
                    finish();
                }
            });
        }
        builder.create().show();
    }

    public boolean shouldRebootBluetoothAfterTest() {
        return false;
    }

    private BroadcastReceiver mBroadcast = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            boolean showProgressDialog = false;
            closeDialog();

            String action = intent.getAction();
            String newAction = null;
            String actionName = null;
            long previousPassed = mPassed;
            final Intent startIntent = new Intent(BleClientTestBaseActivity.this, BleClientService.class);
            if (action != null) {
                Log.d(TAG, "Processing " + action);
            }
            switch (action) {
            case BleClientService.BLE_BLUETOOTH_DISABLED:
                showErrorDialog(R.string.ble_bluetooth_disable_title, R.string.ble_bluetooth_disable_message, true);
                break;
            case BleClientService.BLE_BLUETOOTH_CONNECTED:
                actionName = getString(R.string.ble_client_connect_name);
                mTestAdapter.setTestPass(BLE_CLIENT_CONNECT);
                mPassed |= PASS_FLAG_CONNECT;
                // execute service discovery test
                newAction = BleClientService.BLE_CLIENT_ACTION_BLE_DISCOVER_SERVICE;
                break;
            case BleClientService.BLE_SERVICES_DISCOVERED:
                actionName = getString(R.string.ble_discover_service_name);
                mTestAdapter.setTestPass(BLE_BLE_DISCOVER_SERVICE);
                mPassed |= PASS_FLAG_DISCOVER;
                // execute MTU requesting test (23bytes)
                newAction = BleClientService.BLE_CLIENT_ACTION_READ_CHARACTERISTIC;
                break;
            case BleClientService.BLE_MTU_CHANGED_23BYTES:
                actionName = getString(R.string.ble_mtu_23_name);
                mTestAdapter.setTestPass(BLE_REQUEST_MTU_23BYTES);
                mPassed |= PASS_FLAG_MTU_CHANGE_23BYTES;
                // execute MTU requesting test (512bytes)
                newAction = BleClientService.BLE_CLIENT_ACTION_REQUEST_MTU_512;
                showProgressDialog = true;
                break;
            case BleClientService.BLE_MTU_CHANGED_512BYTES:
                actionName = getString(R.string.ble_mtu_512_name);
                mTestAdapter.setTestPass(BLE_REQUEST_MTU_512BYTES);
                mPassed |= PASS_FLAG_MTU_CHANGE_512BYTES;
                // execute characteristic reading test
                newAction = BleClientService.BLE_CLIENT_ACTION_READ_CHARACTERISTIC_NO_PERMISSION;
                break;
            case BleClientService.BLE_CHARACTERISTIC_READ:
                actionName = getString(R.string.ble_read_characteristic_name);
                mTestAdapter.setTestPass(BLE_READ_CHARACTERISTIC);
                mPassed |= PASS_FLAG_READ_CHARACTERISTIC;
                // execute characteristic writing test
                newAction = BleClientService.BLE_CLIENT_ACTION_WRITE_CHARACTERISTIC;
                break;
            case BleClientService.BLE_CHARACTERISTIC_WRITE:
                actionName = getString(R.string.ble_write_characteristic_name);
                mTestAdapter.setTestPass(BLE_WRITE_CHARACTERISTIC);
                mPassed |= PASS_FLAG_WRITE_CHARACTERISTIC;
                newAction = BleClientService.BLE_CLIENT_ACTION_REQUEST_MTU_23;
                showProgressDialog = true;
                break;
            case BleClientService.BLE_CHARACTERISTIC_READ_NOPERMISSION:
                actionName = getString(R.string.ble_read_characteristic_nopermission_name);
                mTestAdapter.setTestPass(BLE_READ_CHARACTERISTIC_NO_PERMISSION);
                mPassed |= PASS_FLAG_READ_CHARACTERISTIC_NO_PERMISSION;
                // execute unpermitted characteristic writing test
                newAction = BleClientService.BLE_CLIENT_ACTION_WRITE_CHARACTERISTIC_NO_PERMISSION;
                break;
            case BleClientService.BLE_CHARACTERISTIC_WRITE_NOPERMISSION:
                actionName = getString(R.string.ble_write_characteristic_nopermission_name);
                mTestAdapter.setTestPass(BLE_WRITE_CHARACTERISTIC_NO_PERMISSION);
                mPassed |= PASS_FLAG_WRITE_CHARACTERISTIC_NO_PERMISSION;
                // execute reliable write test
                newAction = BleClientService.BLE_CLIENT_ACTION_RELIABLE_WRITE;
                showProgressDialog = true;
                break;
            case BleClientService.BLE_RELIABLE_WRITE_COMPLETED:
                actionName = getString(R.string.ble_reliable_write_name);
                mTestAdapter.setTestPass(BLE_RELIABLE_WRITE);
                mPassed |= PASS_FLAG_RELIABLE_WRITE;
//                newAction = BleClientService.BLE_CLIENT_ACTION_RELIABLE_WRITE_BAD_RESP;

                // skip Reliable write (bad response) test
                mPassed |= PASS_FLAG_RELIABLE_WRITE_BAD_RESP;
                Log.d(TAG, "Skip PASS_FLAG_RELIABLE_WRITE_BAD_RESP.");
                newAction = BleClientService.BLE_CLIENT_ACTION_NOTIFY_CHARACTERISTIC;
                showProgressDialog = true;
                break;
            case BleClientService.BLE_RELIABLE_WRITE_BAD_RESP_COMPLETED: {
                actionName = getString(R.string.ble_reliable_write_bad_resp_name);
                if(!intent.hasExtra(BleClientService.EXTRA_ERROR_MESSAGE)) {
                    mPassed |= PASS_FLAG_RELIABLE_WRITE_BAD_RESP;
                    mTestAdapter.setTestPass(BLE_RELIABLE_WRITE_BAD_RESP);
                }
                // execute notification test
                newAction = BleClientService.BLE_CLIENT_ACTION_NOTIFY_CHARACTERISTIC;
                showProgressDialog = true;
            }
                break;
            case BleClientService.BLE_CHARACTERISTIC_CHANGED:
                actionName = getString(R.string.ble_notify_characteristic_name);
                mTestAdapter.setTestPass(BLE_NOTIFY_CHARACTERISTIC);
                mPassed |= PASS_FLAG_NOTIFY_CHARACTERISTIC;
                // execute indication test
                newAction = BleClientService.BLE_CLIENT_ACTION_INDICATE_CHARACTERISTIC;
                showProgressDialog = true;
                break;
            case BleClientService.BLE_CHARACTERISTIC_INDICATED:
                actionName = getString(R.string.ble_indicate_characteristic_name);
                mTestAdapter.setTestPass(BLE_INDICATE_CHARACTERISTIC);
                mPassed |= PASS_FLAG_INDICATE_CHARACTERISTIC;
                // execute descriptor reading test
                newAction = BleClientService.BLE_CLIENT_ACTION_READ_DESCRIPTOR;
                break;
            case BleClientService.BLE_DESCRIPTOR_READ:
                actionName = getString(R.string.ble_read_descriptor_name);
                mTestAdapter.setTestPass(BLE_READ_DESCRIPTOR);
                mPassed |= PASS_FLAG_READ_DESCRIPTOR;
                // execute descriptor writing test
                newAction = BleClientService.BLE_CLIENT_ACTION_WRITE_DESCRIPTOR;
                break;
            case BleClientService.BLE_DESCRIPTOR_WRITE:
                actionName = getString(R.string.ble_write_descriptor_name);
                mTestAdapter.setTestPass(BLE_WRITE_DESCRIPTOR);
                mPassed |= PASS_FLAG_WRITE_DESCRIPTOR;
                // execute unpermitted descriptor reading test
                newAction = BleClientService.BLE_CLIENT_ACTION_READ_DESCRIPTOR_NO_PERMISSION;
                break;
            case BleClientService.BLE_DESCRIPTOR_READ_NOPERMISSION:
                actionName = getString(R.string.ble_read_descriptor_nopermission_name);
                mTestAdapter.setTestPass(BLE_READ_DESCRIPTOR_NO_PERMISSION);
                mPassed |= PASS_FLAG_READ_DESCRIPTOR_NO_PERMISSION;
                // execute unpermitted descriptor writing test
                newAction = BleClientService.BLE_CLIENT_ACTION_WRITE_DESCRIPTOR_NO_PERMISSION;
                break;
            case BleClientService.BLE_DESCRIPTOR_WRITE_NOPERMISSION:
                actionName = getString(R.string.ble_write_descriptor_nopermission_name);
                mTestAdapter.setTestPass(BLE_WRITE_DESCRIPTOR_NO_PERMISSION);
                mPassed |= PASS_FLAG_WRITE_DESCRIPTOR_NO_PERMISSION;
// TODO: too flaky b/34951749
                // execute RSSI requesting test
                // newAction = BleClientService.BLE_CLIENT_ACTION_READ_RSSI;
                mPassed |= PASS_FLAG_READ_RSSI;
                Log.d(TAG, "Skip PASS_FLAG_READ_RSSI.");
                newAction = BleClientService.BLE_CLIENT_ACTION_READ_PHY;
                break;
            case BleClientService.BLE_READ_REMOTE_RSSI:
                actionName = getString(R.string.ble_read_rssi_name);
                mTestAdapter.setTestPass(BLE_READ_RSSI);
                mPassed |= PASS_FLAG_READ_RSSI;
                newAction = BleClientService.BLE_CLIENT_ACTION_READ_PHY;
                break;
            case BleClientService.BLE_PHY_READ:
                actionName = getString(R.string.ble_read_phy_name);
                mTestAdapter.setTestPass(BLE_READ_PHY);
                mPassed |= PASS_FLAG_READ_PHY;
                newAction = BleClientService.BLE_CLIENT_ACTION_TRIGGER_SERVICE_CHANGED;
                break;
            case BleClientService.BLE_ON_SERVICE_CHANGED:
                actionName = getString(R.string.ble_on_service_changed);
                mTestAdapter.setTestPass(BLE_ON_SERVICE_CHANGED);
                mPassed |= PASS_FLAG_ON_SERVICE_CHANGED;
                newAction = BleClientService.BLE_CLIENT_ACTION_CLIENT_DISCONNECT;
                break;
            case BleClientService.BLE_BLUETOOTH_DISCONNECTED:
                mTestAdapter.setTestPass(BLE_CLIENT_DISCONNECT);
                mPassed |= PASS_FLAG_DISCONNECT;
                // all test done
                newAction = null;
                break;
            case BleClientService.BLE_BLUETOOTH_MISMATCH_SECURE:
                showErrorDialog(R.string.ble_bluetooth_mismatch_title, R.string.ble_bluetooth_mismatch_secure_message, true);
                break;
            case BleClientService.BLE_BLUETOOTH_MISMATCH_INSECURE:
                showErrorDialog(R.string.ble_bluetooth_mismatch_title, R.string.ble_bluetooth_mismatch_insecure_message, true);
                break;
            }

            if (previousPassed != mPassed) {
                String logMessage = String.format("Passed Flags has changed from 0x%08X to 0x%08X. Delta=0x%08X",
                                                  previousPassed, mPassed, mPassed ^ previousPassed);
                Log.d(TAG, logMessage);
            }

            mTestAdapter.notifyDataSetChanged();

            if (newAction != null) {
                Log.d(TAG, "Starting " + newAction);
                startIntent.setAction(newAction);
                if (STEP_EXECUTION) {
                    closeDialog();
                    final boolean showProgressDialogValue = showProgressDialog;
                    mDialog = new AlertDialog.Builder(BleClientTestBaseActivity.this)
                            .setTitle(actionName)
                            .setMessage(R.string.ble_test_finished)
                            .setCancelable(false)
                            .setPositiveButton(R.string.ble_test_next,
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            closeDialog();
                                            if (showProgressDialogValue) {
                                                showProgressDialog();
                                            }
                                            startService(startIntent);
                                        }
                                    })
                            .show();
                } else {
                    if (showProgressDialog) {
                        showProgressDialog();
                    }
                    startService(startIntent);
                }
            } else {
                closeDialog();
            }

            if (mPassed == PASS_FLAG_ALL) {
                Log.d(TAG, "All Tests Passed.");
                if (shouldRebootBluetoothAfterTest()) {
                    mBtPowerSwitcher.executeSwitching();
                } else {
                    getPassButton().setEnabled(true);
                }
            }
        }
    };

    private static final long BT_ON_DELAY = 10000;
    private final BluetoothPowerSwitcher mBtPowerSwitcher = new BluetoothPowerSwitcher();
    private class BluetoothPowerSwitcher extends BroadcastReceiver {

        private boolean mIsSwitching = false;
        private BluetoothAdapter mAdapter;

        public void executeSwitching() {
            if (mAdapter == null) {
                BluetoothManager btMgr = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
                mAdapter = btMgr.getAdapter();
            }

            if (!mIsSwitching) {
                IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
                registerReceiver(this, filter);
                mIsSwitching = true;
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mAdapter.disable();
                    }
                }, 1000);
                showProgressDialog();
            }
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
                if (state == BluetoothAdapter.STATE_OFF) {
                    mHandler.postDelayed(() ->
                            invokeWithShellPermissions(() -> mAdapter.enable()), BT_ON_DELAY);
                } else if (state == BluetoothAdapter.STATE_ON) {
                    mIsSwitching = false;
                    unregisterReceiver(this);
                    getPassButton().setEnabled(true);
                    closeDialog();
                }
            }
        }
    }

}
