/*
 * Copyright (C) 2013 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 java.util.UUID;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGattServer;
import android.bluetooth.BluetoothGattServerCallback;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.ParcelUuid;
import android.util.Log;
import android.widget.Toast;

public class BleAdvertiserService extends Service {

    public static final boolean DEBUG = true;
    public static final String TAG = "BleAdvertiseService";

    public static final int COMMAND_START_ADVERTISE = 0;
    public static final int COMMAND_STOP_ADVERTISE = 1;
    public static final int COMMAND_START_POWER_LEVEL = 2;
    public static final int COMMAND_STOP_POWER_LEVEL = 3;
    public static final int COMMAND_START_SCANNABLE = 4;
    public static final int COMMAND_STOP_SCANNABLE = 5;
    public static final int COMMAND_START_UNSCANNABLE = 6;
    public static final int COMMAND_STOP_UNSCANNABLE = 7;

    public static final String BLE_ADV_NOT_SUPPORT =
            "com.android.cts.verifier.bluetooth.BLE_ADV_NOT_SUPPORT";
    public static final String BLE_START_ADVERTISE =
            "com.android.cts.verifier.bluetooth.BLE_START_ADVERTISE";
    public static final String BLE_STOP_ADVERTISE =
            "com.android.cts.verifier.bluetooth.BLE_STOP_ADVERTISE";
    public static final String BLE_START_POWER_LEVEL =
            "com.android.cts.verifier.bluetooth.BLE_START_POWER_LEVEL";
    public static final String BLE_STOP_POWER_LEVEL =
            "com.android.cts.verifier.bluetooth.BLE_STOP_POWER_LEVEL";
    public static final String BLE_START_SCANNABLE =
            "com.android.cts.verifier.bluetooth.BLE_START_SCANNABLE";
    public static final String BLE_START_UNSCANNABLE =
            "com.android.cts.verifier.bluetooth.BLE_START_UNSCANNABLE";
    public static final String BLE_STOP_SCANNABLE =
            "com.android.cts.verifier.bluetooth.BLE_STOP_SCANNABLE";
    public static final String BLE_STOP_UNSCANNABLE =
            "com.android.cts.verifier.bluetooth.BLE_STOP_UNSCANNABLE";

    public static final String EXTRA_COMMAND =
            "com.android.cts.verifier.bluetooth.EXTRA_COMMAND";

    protected static final UUID PRIVACY_MAC_UUID =
            UUID.fromString("00009999-0000-1000-8000-00805f9b34fb");
    protected static final UUID POWER_LEVEL_UUID =
            UUID.fromString("00008888-0000-1000-8000-00805f9b34fb");
    protected static final UUID SCAN_RESP_UUID =
            UUID.fromString("00007777-0000-1000-8000-00805f9b34fb");
    protected static final UUID SCANNABLE_UUID =
            UUID.fromString("00006666-0000-1000-8000-00805f9b34fb");
    protected static final UUID UNSCANNABLE_UUID =
            UUID.fromString("00005555-0000-1000-8000-00805f9b34fb");

    public static final byte MANUFACTURER_TEST_ID = (byte)0x07;
    public static final byte[] PRIVACY_MAC_DATA = new byte[]{3, 1, 4};
    public static final byte[] PRIVACY_RESPONSE = new byte[]{9, 2, 6};
    public static final byte[] POWER_LEVEL_DATA = new byte[]{1, 5, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0};  // 15 bytes
    public static final byte[] POWER_LEVEL_MASK = new byte[]{1, 1, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0};  // 15 bytes
    public static final int POWER_LEVEL_DATA_LENGTH = 15;
    public static final byte[] SCANNABLE_DATA = new byte[]{5, 3, 5};
    public static final byte[] UNSCANNABLE_DATA = new byte[]{8, 9, 7};

    private BluetoothManager mBluetoothManager;
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothLeAdvertiser mAdvertiser;
    private BluetoothGattServer mGattServer;
    private AdvertiseCallback mCallback;
    private Handler mHandler;

    private int[] mPowerLevel;
    private Map<Integer, AdvertiseCallback> mPowerCallback;
    private int mAdvertiserStatus;

    private AdvertiseCallback mScannableCallback;
    private AdvertiseCallback mUnscannableCallback;

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

        mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = mBluetoothManager.getAdapter();
        mAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
        mGattServer = mBluetoothManager.openGattServer(getApplicationContext(),
            new BluetoothGattServerCallback() {});
        mHandler = new Handler();
        mAdvertiserStatus = 0;

        mCallback = new BLEAdvertiseCallback();
        mScannableCallback = new BLEAdvertiseCallback();
        mUnscannableCallback = new BLEAdvertiseCallback();
        mPowerLevel = new int[]{
            AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW,
            AdvertiseSettings.ADVERTISE_TX_POWER_LOW,
            AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM,
            AdvertiseSettings.ADVERTISE_TX_POWER_HIGH};
        mPowerCallback = new HashMap<Integer, AdvertiseCallback>();
        for (int x : mPowerLevel) {
            mPowerCallback.put(x, new BLEAdvertiseCallback());
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null) handleIntent(intent);
        return START_NOT_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mAdvertiser != null) {
            stopAdvertiser();
        }
    }

    private void stopAdvertiser() {
        if (mAdvertiser == null) {
            mAdvertiserStatus = 0;
            return;
        }
        if ((mAdvertiserStatus & (1 << COMMAND_START_ADVERTISE)) > 0) {
            mAdvertiser.stopAdvertising(mCallback);
        }
        if ((mAdvertiserStatus & (1 << COMMAND_START_POWER_LEVEL)) > 0) {
            for (int t : mPowerLevel) {
                mAdvertiser.stopAdvertising(mPowerCallback.get(t));
            }
        }
        if ((mAdvertiserStatus & (1 << COMMAND_START_SCANNABLE)) > 0) {
            mAdvertiser.stopAdvertising(mScannableCallback);
        }
        if ((mAdvertiserStatus & (1 << COMMAND_START_UNSCANNABLE)) > 0) {
            mAdvertiser.stopAdvertising(mUnscannableCallback);
        }
        mAdvertiserStatus = 0;
    }

    private AdvertiseData generateAdvertiseData(UUID uuid, byte[] data) {
        return new AdvertiseData.Builder()
            .addManufacturerData(MANUFACTURER_TEST_ID, new byte[]{MANUFACTURER_TEST_ID, 0})
            .addServiceData(new ParcelUuid(uuid), data)
            .setIncludeTxPowerLevel(true)
            .build();
    }

    private AdvertiseSettings generateSetting(int power) {
        return new AdvertiseSettings.Builder()
            .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
            .setTxPowerLevel(power)
            .setConnectable(false)
            .build();
    }

    private void handleIntent(Intent intent) {
        if (mBluetoothAdapter != null && !mBluetoothAdapter.isMultipleAdvertisementSupported()) {
            showMessage("Multiple advertisement is not supported.");
            sendBroadcast(new Intent(BLE_ADV_NOT_SUPPORT));
            return;
        } else if (mAdvertiser == null) {
            showMessage("Cannot start advertising on this device.");
            return;
        }
        int command = intent.getIntExtra(EXTRA_COMMAND, -1);
        if (command >= 0) {
            stopAdvertiser();
            mAdvertiserStatus |= (1 << command);
        }

        switch (command) {
            case COMMAND_START_ADVERTISE:
                AdvertiseData data = generateAdvertiseData(PRIVACY_MAC_UUID, PRIVACY_MAC_DATA);
                AdvertiseData response = generateAdvertiseData(SCAN_RESP_UUID, PRIVACY_RESPONSE);
                AdvertiseSettings setting =
                        generateSetting(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM);

                mAdvertiser.startAdvertising(setting, data, response, mCallback);
                sendBroadcast(new Intent(BLE_START_ADVERTISE));
                break;
            case COMMAND_STOP_ADVERTISE:
                sendBroadcast(new Intent(BLE_STOP_ADVERTISE));
                break;
            case COMMAND_START_POWER_LEVEL:
                for (int t : mPowerLevel) {
                    // Service data:
                    //    field overhead = 2 bytes
                    //    uuid = 2 bytes
                    //    data = 15 bytes
                    // Manufacturer data:
                    //    field overhead = 2 bytes
                    //    Specific data length = 2 bytes
                    //    data length = 2 bytes
                    // Include power level:
                    //    field overhead = 2 bytes
                    //    1 byte
                    // Connectable flag: 3 bytes (0 byte for Android 5.1+)
                    // SUM = 31 bytes
                    byte[] dataBytes = new byte[POWER_LEVEL_DATA_LENGTH];
                    dataBytes[0] = 0x01;
                    dataBytes[1] = 0x05;
                    for (int i = 2; i < POWER_LEVEL_DATA_LENGTH; i++) {
                        dataBytes[i] = (byte)t;
                    }
                    AdvertiseData d = generateAdvertiseData(POWER_LEVEL_UUID, dataBytes);
                    AdvertiseSettings settings = generateSetting(t);
                    mAdvertiser.startAdvertising(settings, d, mPowerCallback.get(t));
                }
                sendBroadcast(new Intent(BLE_START_POWER_LEVEL));
                break;
            case COMMAND_STOP_POWER_LEVEL:
                sendBroadcast(new Intent(BLE_STOP_POWER_LEVEL));
                break;
            case COMMAND_START_SCANNABLE:
                data = generateAdvertiseData(SCANNABLE_UUID, SCANNABLE_DATA);
                setting = generateSetting(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM);

                mAdvertiser.startAdvertising(setting, data, mScannableCallback);
                sendBroadcast(new Intent(BLE_START_SCANNABLE));
                break;
            case COMMAND_START_UNSCANNABLE:
                data = generateAdvertiseData(UNSCANNABLE_UUID, UNSCANNABLE_DATA);
                setting = generateSetting(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM);

                mAdvertiser.startAdvertising(setting, data, mUnscannableCallback);
                sendBroadcast(new Intent(BLE_START_UNSCANNABLE));
                break;
            case COMMAND_STOP_SCANNABLE:
                sendBroadcast(new Intent(BLE_STOP_SCANNABLE));
                break;
            case COMMAND_STOP_UNSCANNABLE:
                sendBroadcast(new Intent(BLE_STOP_UNSCANNABLE));
                break;
            default:
                showMessage("Unrecognized command: " + command);
                break;
        }
    }

    private void showMessage(final String msg) {
        mHandler.post(new Runnable() {
            public void run() {
                Toast.makeText(BleAdvertiserService.this, msg, Toast.LENGTH_SHORT).show();
            }
        });
    }

    private class BLEAdvertiseCallback extends AdvertiseCallback {
        @Override
        public void onStartFailure(int errorCode) {
            Log.e(TAG, "fail. Error code: " + errorCode);
        }

        @Override
        public void onStartSuccess(AdvertiseSettings setting) {
            if (DEBUG) Log.d(TAG, "success.");
        }
    }
}
