// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package io.v.android.impl.google.discovery.plugins.ble;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattServer;
import android.bluetooth.BluetoothGattServerCallback;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanRecord;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.pm.PackageManager;
import android.support.v4.content.ContextCompat;
import android.util.Log;

import com.google.common.collect.ImmutableList;

import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.joda.time.Duration;

import io.v.android.v23.V;
import io.v.v23.context.VContext;
import io.v.v23.discovery.AdId;

import io.v.x.ref.lib.discovery.AdInfo;

import io.v.impl.google.lib.discovery.UUIDUtil;
import io.v.impl.google.lib.discovery.Plugin;

/**
 * The discovery plugin interface for BLE.
 */
public class BlePlugin implements Plugin {
    private static final String TAG = "BlePlugin";

    // We are using a constant for the MTU because Android and paypal/gatt don't get along
    // when the paypal gatt client sends a setMTU message.  The Android server seems to send
    // a malformed L2CAP message.
    private static final int MTU = 23;

    // Default device cache expiration timeout.
    private static final Duration defaultCacheDuration = Duration.standardSeconds(90);

    // Random generator for stamp.
    private final SecureRandom random = new SecureRandom();

    private final Context androidContext;

    // Set of Ble objects that will be interacted with to perform operations.
    private BluetoothLeAdvertiser bluetoothLeAdvertiser;
    private BluetoothLeScanner bluetoothLeScanner;
    private BluetoothGattServer bluetoothGattServer;

    private Map<AdId, BluetoothGattService> advertisements;
    private AdvertiseCallback advertiseCallback;

    private Set<Plugin.ScanHandler> scanners;
    private Set<String> pendingConnections;
    private DeviceCache deviceCache;
    private ScanCallback scanCallback;

    private boolean hasPermission(String perm) {
        return ContextCompat.checkSelfPermission(androidContext, perm)
                == PackageManager.PERMISSION_GRANTED;
    }

    public BlePlugin(VContext ctx, String host) throws Exception {
        androidContext = V.getAndroidContext(ctx);
        if (androidContext == null) {
            throw new IllegalStateException("androidContext not available");
        }
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
            throw new IllegalStateException("BluetoothAdapter not available");
        }
        if (!hasPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
                && !hasPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
            throw new IllegalStateException("No permission on BluetoothAdapter");
        }

        bluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
        bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
        BluetoothManager manager =
                (BluetoothManager) androidContext.getSystemService(Context.BLUETOOTH_SERVICE);
        bluetoothGattServer =
                manager.openGattServer(
                        androidContext,
                        new BluetoothGattServerCallback() {
                            @Override
                            public void onConnectionStateChange(
                                    BluetoothDevice device, int status, int newState) {
                                super.onConnectionStateChange(device, status, newState);
                            }

                            @Override
                            public void onCharacteristicReadRequest(
                                    BluetoothDevice device,
                                    int requestId,
                                    int offset,
                                    BluetoothGattCharacteristic characteristic) {
                                super.onCharacteristicReadRequest(
                                        device, requestId, offset, characteristic);
                                byte[] total = characteristic.getValue();
                                byte[] res = {};
                                // Only send MTU - 1 bytes. The first byte of all packets is the op code.
                                if (offset < total.length) {
                                    int finalByte = offset + MTU - 1;
                                    if (finalByte > total.length) {
                                        finalByte = total.length;
                                    }
                                    res = Arrays.copyOfRange(total, offset, finalByte);
                                    bluetoothGattServer.sendResponse(
                                            device, requestId, BluetoothGatt.GATT_SUCCESS, 0, res);
                                } else {
                                    // This should probably be an error, but a bug in the paypal/gatt code causes an
                                    // infinite loop if this returns an error rather than the empty value.
                                    bluetoothGattServer.sendResponse(
                                            device, requestId, BluetoothGatt.GATT_SUCCESS, 0, res);
                                }
                            }
                        });

        advertisements = new HashMap<>();
        scanners = new HashSet<>();
        pendingConnections = new HashSet<>();
        deviceCache = new DeviceCache(defaultCacheDuration);
    }

    public void startAdvertising(AdInfo adInfo) throws Exception {
        BluetoothGattService service =
                new BluetoothGattService(
                        UUIDUtil.serviceUUID(adInfo.getAd().getInterfaceName()),
                        BluetoothGattService.SERVICE_TYPE_PRIMARY);
        for (Map.Entry<UUID, byte[]> entry : ConvertUtil.toGattAttrs(adInfo).entrySet()) {
            BluetoothGattCharacteristic c =
                    new BluetoothGattCharacteristic(
                            entry.getKey(),
                            BluetoothGattCharacteristic.PROPERTY_READ,
                            BluetoothGattCharacteristic.PERMISSION_READ);
            c.setValue(entry.getValue());
            service.addCharacteristic(c);
        }

        synchronized (advertisements) {
            advertisements.put(adInfo.getAd().getId(), service);
            bluetoothGattServer.addService(service);
            updateAdvertising();
        }
    }

    public void stopAdvertising(AdInfo adInfo) {
        synchronized (advertisements) {
            BluetoothGattService service = advertisements.remove(adInfo.getAd().getId());
            if (service != null) {
                bluetoothGattServer.removeService(service);
                updateAdvertising();
            }
        }
    }

    public void close() {
        bluetoothGattServer.close();
    }

    private long genStamp() {
        // We use 8-byte stamp to reflect the current services of the current device.
        //
        // TODO(bjornick): 8-byte random number might not be good enough for
        // global uniqueness. We might want to consider a better way to generate
        // stamp like using a unique device id with sequence number.
        return new BigInteger(64, random).longValue();
    }

    private void updateAdvertising() {
        if (advertiseCallback != null) {
            bluetoothLeAdvertiser.stopAdvertising(advertiseCallback);
            advertiseCallback = null;
        }
        if (advertisements.size() == 0) {
            return;
        }

        AdvertiseData.Builder builder = new AdvertiseData.Builder();
        ByteBuffer buf = ByteBuffer.allocate(9);
        buf.put((byte) 8);
        buf.putLong(genStamp());
        builder.addManufacturerData(1001, buf.array());
        AdvertiseSettings.Builder settingsBuilder = new AdvertiseSettings.Builder();
        settingsBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY);
        settingsBuilder.setConnectable(true);
        advertiseCallback =
                new AdvertiseCallback() {
                    @Override
                    public void onStartSuccess(AdvertiseSettings settingsInEffect) {
                        Log.d(TAG, "started " + settingsInEffect);
                    }

                    @Override
                    public void onStartFailure(int errorCode) {
                        Log.e(TAG, "failed to start advertising " + errorCode);
                    }
                };
        bluetoothLeAdvertiser.startAdvertising(
                settingsBuilder.build(), builder.build(), advertiseCallback);
    }

    public void startScan(String interfaceName, Plugin.ScanHandler handler) throws Exception {
        synchronized (scanners) {
            if (!scanners.add(handler)) {
                throw new IllegalArgumentException("handler already registered");
            }
            deviceCache.addScanner(interfaceName, handler);
            updateScan();
        }
    }

    public void stopScan(Plugin.ScanHandler handler) {
        synchronized (scanners) {
            if (!scanners.remove(handler)) {
                return;
            }
            deviceCache.removeScanner(handler);
            updateScan();
        }
    }

    private void updateScan() {
        // TODO(jhahn): Verify whether we need to stop scanning while connect to remote GATT servers.
        if (scanners.isEmpty()) {
            if (pendingConnections.isEmpty()) {
                bluetoothLeScanner.stopScan(scanCallback);
                scanCallback = null;
            }
            return;
        }
        if (scanCallback != null) {
            return;
        }

        final List<ScanFilter> scanFilters =
                ImmutableList.of(
                        new ScanFilter.Builder()
                                .setManufacturerData(1001, new byte[0], new byte[0])
                                .build());
        final ScanSettings scanSettings =
                new ScanSettings.Builder()
                        .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
                        .setScanMode(ScanSettings.SCAN_MODE_BALANCED)
                        .build();
        scanCallback =
                new ScanCallback() {
                    @Override
                    public void onScanResult(int callbackType, ScanResult result) {
                        ScanRecord record = result.getScanRecord();
                        // Use 1001 to denote that this is a Vanadium device.  We picked an id that is
                        // currently not in use.
                        byte[] data = record.getManufacturerSpecificData(1001);
                        ByteBuffer buffer = ByteBuffer.wrap(data);
                        final long stamp = buffer.getLong();
                        final String deviceId = result.getDevice().getAddress();
                        if (deviceCache.haveSeenStamp(stamp, deviceId)) {
                            return;
                        }

                        BluetoothGattReader.Handler handler =
                                new BluetoothGattReader.Handler() {
                                    @Override
                                    public void handle(Map<UUID, Map<UUID, byte[]>> services) {
                                        if (services != null) {
                                            List<AdInfo> adInfos = new ArrayList<>();
                                            for (Map.Entry<UUID, Map<UUID, byte[]>> entry :
                                                    services.entrySet()) {
                                                try {
                                                    AdInfo adInfo =
                                                            ConvertUtil.toAdInfo(entry.getValue());
                                                    adInfos.add(adInfo);
                                                } catch (IOException e) {
                                                    Log.e(
                                                            TAG,
                                                            "failed to convert advertisement" + e);
                                                }
                                            }
                                            deviceCache.saveDevice(stamp, deviceId, adInfos);
                                        }
                                        synchronized (scanners) {
                                            pendingConnections.remove(deviceId);
                                            if (pendingConnections.isEmpty()) {
                                                if (scanners.isEmpty()) {
                                                    scanCallback = null;
                                                    return;
                                                }
                                                bluetoothLeScanner.startScan(
                                                        scanFilters, scanSettings, scanCallback);
                                            }
                                        }
                                    }
                                };
                        BluetoothGattReader cb = new BluetoothGattReader(handler);
                        synchronized (scanners) {
                            if (scanners.isEmpty()) {
                                return;
                            }
                            if (!pendingConnections.add(deviceId)) {
                                return;
                            }
                            if (pendingConnections.size() == 1) {
                                bluetoothLeScanner.stopScan(scanCallback);
                            }
                        }
                        Log.d(TAG, "connecting to " + result.getDevice());
                        result.getDevice().connectGatt(androidContext, false, cb);
                    }

                    @Override
                    public void onBatchScanResults(List<ScanResult> results) {}

                    @Override
                    public void onScanFailed(int errorCode) {}
                };
        bluetoothLeScanner.startScan(scanFilters, scanSettings, scanCallback);
    }
}
