// Copyright 2015 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.libs.discovery.ble;

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.util.Log;

import org.joda.time.Duration;

import java.io.IOException;
import java.nio.ByteBuffer;
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.TreeMap;
import java.util.UUID;

import io.v.impl.google.lib.discovery.DeviceCache;
import io.v.impl.google.lib.discovery.UUIDUtil;
import io.v.impl.google.lib.discovery.VScanner;
import io.v.impl.google.lib.discovery.ble.BleAdvertisementConverter;
import io.v.v23.context.VContext;
import io.v.impl.google.lib.discovery.ScanHandler;
import io.v.x.ref.lib.discovery.Advertisement;

/**
 * BlePlugin implements the Discovery Plugin Interface for Bluetooth.
 */
public class 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;

    // Object used to lock advertisement objects.
    private final Object advertisementLock;
    // The id to assign to the next advertisment.
    private int nextAdv;
    // A map of advertisement ids to the advertisement that corresponds to them.
    private Map<Integer, BluetoothGattService> advertisements;
    // A map of advertisement ids to the thread waiting for cancellation of the context.
    private Map<Integer, Thread> advCancellationThreads;

    // Object used to lock scanner objects
    private final Object scannerLock;
    // A map of scanner ids to the thread waiting for cancellation of the context.
    private Map<Integer, Thread> scanCancellationThreads;
    private DeviceCache cachedDevices;
    // Used to track the set of devices we currently talking to.
    private Set<String> pendingCalls;

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

    // We need to hold onto the callbacks for scan an advertise because that is what is used
    // to stop the operation.
    private ScanCallback scanCallback;
    private AdvertiseCallback advertiseCallback;

    private boolean isScanning;

    private Context androidContext;


    // A thread to wait for the cancellation of a particular advertisement.  VContext.done().await()
    // is blocking so have to spin up a thread per outstanding advertisement.
    private class AdvertisementCancellationRunner implements Runnable{
        private VContext mCtx;

        private int mId;
        AdvertisementCancellationRunner(VContext ctx, int id) {
            mId = id;
            mCtx = ctx;
        }

        @Override
        public void run() {
            try {
                mCtx.done().await();
            } catch (InterruptedException e) {
                // Ignore interruptions.
            }
            BlePlugin.this.removeAdvertisement(mId);
        }
    }

    // Similar to AdvertisementCancellationRunner except for scanning.
    private class ScannerCancellationRunner implements Runnable{
        private VContext mCtx;

        private int mId;
        ScannerCancellationRunner(VContext ctx, int id) {
            mId = id;
            mCtx = ctx;
        }

        @Override
        public void run() {
            try {
                mCtx.done().await();
            } catch (InterruptedException e) {
                // Ignore interruptions.
            }
            BlePlugin.this.removeScanner(mId);
        }
    }

    public BlePlugin(Context androidContext) {
        advertisementLock = new Object();
        nextAdv = 0;
        advertisements = new TreeMap<>();
        advCancellationThreads = new HashMap<>();

        scannerLock = new Object();
        cachedDevices = new DeviceCache(new Duration(5 * 60000));
        scanCancellationThreads = new HashMap<>();
        isScanning = false;
        pendingCalls = new HashSet<>();

        bluetoothLeAdvertise = BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();
        bluetoothLeScanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();
        this.androidContext = androidContext;
        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 {
                    bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_FAILURE, 0,  res);
                }
            }
        });
    }


    // Converts a Vanadium Advertisement to a Bluetooth gatt service.
    private BluetoothGattService convertToService(Advertisement adv) throws IOException {
        Map<UUID, byte[]> attributes = BleAdvertisementConverter.vadvertismentToBleAttr(adv);
        BluetoothGattService service = new BluetoothGattService(
                UUIDUtil.UuidtUUID(adv.getServiceUuid()), BluetoothGattService.SERVICE_TYPE_PRIMARY);
        for (Map.Entry<UUID, byte[]> entry : attributes.entrySet()) {
            BluetoothGattCharacteristic ch = new BluetoothGattCharacteristic(entry.getKey(), 0,
                    BluetoothGattCharacteristic.PERMISSION_READ);
            ch.setValue(entry.getValue());
            service.addCharacteristic(ch);
        }
        return service;
    }

    public void addAdvertisement(VContext ctx, Advertisement advertisement) throws IOException {
        BluetoothGattService service = convertToService(advertisement);
        synchronized (advertisementLock) {
            int currentId = nextAdv++;
            advertisements.put(currentId, service);
            Thread t = new Thread(new AdvertisementCancellationRunner(ctx, currentId));
            t.start();
            advCancellationThreads.put(currentId, t);
            bluetoothGattServer.addService(service);
            readvertise();
        }
    }

    private void removeAdvertisement(int id) {
        synchronized (advertisements) {
            BluetoothGattService s = advertisements.get(id);
            if (s != null) {
                bluetoothGattServer.removeService(s);
            }
            advertisements.remove(id);
            advCancellationThreads.remove(id);
            readvertise();
        }
    }

    public void addScanner(VContext ctx, UUID serviceUUID,  ScanHandler handler) {
        VScanner scanner = new VScanner(serviceUUID, handler);
        int currentId = cachedDevices.addScanner(scanner);
        synchronized (scannerLock) {
            Thread t = new Thread(new ScannerCancellationRunner(ctx, currentId));
            t.start();
            scanCancellationThreads.put(currentId, t);
            updateScanning();
        }
    }

    private void removeScanner(int id) {
        cachedDevices.removeScanner(id);
        synchronized (scannerLock) {
            scanCancellationThreads.remove(id);
            updateScanning();
        }
    }

    private void updateScanning() {
        if (isScanning && scanCancellationThreads.size() == 0) {
            isScanning = false;
            bluetoothLeScanner.stopScan(scanCallback);
            return;
        }

        if (!isScanning && scanCancellationThreads.size() > 0) {
            isScanning = true;
            ScanFilter.Builder builder = new ScanFilter.Builder();
            byte[] manufacturerData = {};
            byte[] manufacturerMask = {};

            builder.setManufacturerData(1001, manufacturerData, manufacturerMask);
            final List<ScanFilter> scanFilter = new ArrayList<>();
            scanFilter.add(builder.build());


            scanCallback = new ScanCallback() {
                @Override
                public void onScanResult(int callbackType, ScanResult result) {
                    // in L the only value for callbackType is CALLBACK_TYPE_ALL_MATCHES, so
                    // we don't look at it's value.
                    ScanRecord record = result.getScanRecord();
                    byte[] data = record.getManufacturerSpecificData(1001);
                    ByteBuffer buffer = ByteBuffer.wrap(data);
                    final long hash = buffer.getLong();
                    final String deviceId = result.getDevice().getAddress();
                    if (cachedDevices.haveSeenHash(hash, deviceId)) {
                        return;
                    }
                    synchronized (scannerLock) {
                        if (pendingCalls.contains(deviceId)) {
                            Log.d("vanadium", "not connecting to " + deviceId + " because of pending connection");
                            return;
                        }
                        pendingCalls.add(deviceId);
                    }
                    BluetoothGattClientCallback.Callback ccb = new BluetoothGattClientCallback.Callback() {
                        @Override
                        public void handle(Map<UUID, Map<UUID, byte[]>> services) {
                            Set<Advertisement> advs = new HashSet<>();
                            for (Map.Entry<UUID, Map<UUID, byte[]>> entry : services.entrySet()) {
                                try {
                                    Advertisement adv =
                                            BleAdvertisementConverter.
                                                    bleAttrToVAdvertisement(entry.getValue());
                                    advs.add(adv);
                                } catch (IOException e) {
                                    Log.e("vanadium","Failed to convert advertisemetn" + e);
                                }
                            }
                            cachedDevices.saveDevice(hash, advs, deviceId);
                            synchronized (scannerLock) {
                                pendingCalls.remove(deviceId);
                            }
                            bluetoothLeScanner.startScan(scanFilter, new ScanSettings.Builder().
                                    setScanMode(ScanSettings.SCAN_MODE_BALANCED).build(), scanCallback);
                        }
                    };
                    BluetoothGattClientCallback cb = new BluetoothGattClientCallback(ccb);
                    bluetoothLeScanner.stopScan(scanCallback);
                    Log.d("vanadium", "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(scanFilter, new ScanSettings.Builder().
                    setScanMode(ScanSettings.SCAN_MODE_BALANCED).build(), scanCallback);
        }
    }

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

        int hash = advertisements.hashCode();

        AdvertiseData.Builder builder = new AdvertiseData.Builder();
        ByteBuffer buf = ByteBuffer.allocate(9);
        buf.put((byte) 8);
        buf.putLong(hash);
        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.i("vanadium", "Successfully started " + settingsInEffect);
                    }

                    @Override
                    public void onStartFailure(int errorCode) {
                        Log.i("vanadium", "Failed to start advertising " + errorCode);
                    }
                };
        bluetoothLeAdvertise.startAdvertising(settingsBuilder.build(), builder.build(),
                advertiseCallback);
    }
}