// 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.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import android.os.Build;
import android.util.Log;

import com.google.common.collect.Queues;

import java.util.ArrayDeque;
import java.util.Iterator;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * A reader that reads Vanadium Gatt services from remote Gatt servers.
 */
class GattReader extends BluetoothGattCallback {
    private static final String TAG = Driver.TAG;

    // A handler that will get called when a GATT service is read.
    interface Handler {
        void onGattRead(BluetoothDevice device, BluetoothGattService service);

        void onGattReadFailed(BluetoothDevice device);
    }

    // TODO(jhahn): What's the maximum MTU size in Android?
    // Android seems to support up to 517 bytes. But there is no documentation on it.
    private static final int MTU = 512;

    // We serialize all Gatt requests. We cancel the request if it takes too
    // long or hangs in order to prevent it from blocking other tasks.
    //
    // TODO(jhahn): Revisit the timeout.
    private static final long GATT_TIMEOUT_MS = 10000; // 10 seconds.

    private final Context mContext;

    private final ScheduledThreadPoolExecutor mExecutor;

    private final Set<UUID> mScanUuids;
    private final UUID mScanBaseUuid, mScanMaskUuid;
    private final Handler mHandler;

    private final ArrayDeque<BluetoothDevice> mPendingReads;

    private BluetoothDevice mCurrentDevice;
    private BluetoothGatt mCurrentGatt;
    private ScheduledFuture mCurrentGattConnectionTimeout;
    private BluetoothGattService mCurrentService;
    private Iterator<BluetoothGattService> mCurrentServiceIterator;
    private Iterator<BluetoothGattCharacteristic> mCurrentCharacteristicIterator;

    /**
     * Creates a new Gatt reader.
     * <p/>
     *
     * An empty uuids means all Vanadium services and baseUuid and maskUuid will be used to
     * filter Vanadium services.
     */
    GattReader(Context context, Set<UUID> uuids, UUID baseUuid, UUID maskUuid, Handler handler) {
        mContext = context;
        mExecutor = new ScheduledThreadPoolExecutor(1);
        mScanUuids = uuids;
        mScanBaseUuid = baseUuid;
        mScanMaskUuid = maskUuid;
        mHandler = handler;
        mPendingReads = Queues.newArrayDeque();
    }

    /**
     * Reads a specified service from a remote device as well as their characteristics.
     * <p/>
     * This is an asynchronous operation. Once service read is completed, the onGattRead() or
     * onServiceReadFailed() callback is triggered.
     */
    synchronized void readDevice(BluetoothDevice device) {
        mPendingReads.add(device);
        if (mCurrentDevice == null) {
            maybeReadNextDevice();
        }
    }

    /**
     * Closes the Gatt reader cancelling the current read and deleting all pending requests.
     */
    synchronized void close() {
        if (mCurrentGatt != null) {
            mCurrentGatt.close();
        }
        mExecutor.shutdown();
        mPendingReads.clear();
    }

    private synchronized void maybeReadNextDevice() {
        mCurrentGatt = null;
        mCurrentGattConnectionTimeout = null;
        mCurrentService = null;
        mCurrentServiceIterator = null;
        mCurrentCharacteristicIterator = null;

        mCurrentDevice = mPendingReads.poll();
        if (mCurrentDevice == null) {
            return;
        }

        if ((mCurrentDevice.getType() == BluetoothDevice.DEVICE_TYPE_CLASSIC
                        || mCurrentDevice.getType() == BluetoothDevice.DEVICE_TYPE_DUAL)
                && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            mCurrentGatt =
                    mCurrentDevice.connectGatt(
                            mContext, false, this, BluetoothDevice.TRANSPORT_BREDR);
        } else {
            mCurrentGatt = mCurrentDevice.connectGatt(mContext, false, this);
        }
        mCurrentGattConnectionTimeout =
                mExecutor.schedule(
                        new Runnable() {
                            @Override
                            public void run() {
                                Log.e(TAG, "gatt connection timed out: " + mCurrentDevice);
                                cancelAndMaybeReadNextDevice();
                            }
                        },
                        GATT_TIMEOUT_MS,
                        TimeUnit.MILLISECONDS);
    }

    private synchronized void finishAndMaybeReadNextDevice() {
        mCurrentGattConnectionTimeout.cancel(false);
        mCurrentGatt.close();

        maybeReadNextDevice();
    }

    private synchronized void cancelAndMaybeReadNextDevice() {
        mCurrentGattConnectionTimeout.cancel(false);
        mCurrentGatt.close();

        final BluetoothDevice device = mCurrentDevice;
        mExecutor.submit(
                new Runnable() {
                    @Override
                    public void run() {
                        mHandler.onGattReadFailed(device);
                    }
                });
        maybeReadNextDevice();
    }

    @Override
    public synchronized void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        super.onConnectionStateChange(gatt, status, newState);
        if (gatt != mCurrentGatt) {
            // This must be for an old Gatt connection which has been already cancelled. Ignore it.
            gatt.close();
            return;
        }

        if (status != BluetoothGatt.GATT_SUCCESS || newState != BluetoothGatt.STATE_CONNECTED) {
            Log.e(TAG, "connection failed: " + mCurrentDevice + " , status: " + status);
            cancelAndMaybeReadNextDevice();
            return;
        }

        // Reset the connection timer.
        if (!mCurrentGattConnectionTimeout.cancel(false)) {
            // Already cancelled.
            return;
        }

        // MTU exchange is not allowed on a BR/EDR physical link.
        // (Bluetooth Core Specification Volume 3, Part G, 4.3.1)
        //
        // There is no way to get the actual link type. So we use the device type for it.
        // It is not clear whether DEVICE_TYPE_DUAL is on a BR/EDR physical link, but
        // it is safe to not exchange MTU for that type too.
        int deviceType = mCurrentDevice.getType();
        if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP
                && deviceType != BluetoothDevice.DEVICE_TYPE_CLASSIC
                && deviceType != BluetoothDevice.DEVICE_TYPE_DUAL) {
            if (!gatt.requestMtu(MTU)) {
                Log.e(TAG, "requestMtu failed: " + mCurrentDevice);
                cancelAndMaybeReadNextDevice();
            }
        } else {
            if (!gatt.discoverServices()) {
                Log.e(TAG, "discoverServices failed: " + mCurrentDevice);
                cancelAndMaybeReadNextDevice();
            }
        }
    }

    @Override
    public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
        super.onMtuChanged(gatt, mtu, status);

        if (status != BluetoothGatt.GATT_SUCCESS) {
            Log.w(TAG, "onMtuChanged failed: " + mCurrentDevice + ", status: " + status);
            cancelAndMaybeReadNextDevice();
            return;
        }

        if (!gatt.discoverServices()) {
            Log.e(TAG, "discoverServices failed: " + mCurrentDevice);
            cancelAndMaybeReadNextDevice();
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        super.onServicesDiscovered(gatt, status);

        if (status != BluetoothGatt.GATT_SUCCESS) {
            Log.e(TAG, "onServicesDiscovered failed: " + mCurrentDevice + ", status: " + status);
            cancelAndMaybeReadNextDevice();
            return;
        }

        mCurrentServiceIterator = gatt.getServices().iterator();
        maybeReadNextService();
    }

    private boolean isTargetService(UUID uuid) {
        if (mScanUuids.contains(uuid)) {
            return true;
        }
        return mScanUuids.isEmpty()
                && (uuid.getMostSignificantBits() & mScanMaskUuid.getMostSignificantBits())
                        == mScanBaseUuid.getMostSignificantBits()
                && (uuid.getLeastSignificantBits() & mScanMaskUuid.getLeastSignificantBits())
                        == mScanBaseUuid.getLeastSignificantBits();
    }

    private void maybeReadNextService() {
        while (mCurrentServiceIterator.hasNext()) {
            mCurrentService = mCurrentServiceIterator.next();
            if (!isTargetService(mCurrentService.getUuid())) {
                continue;
            }

            mCurrentCharacteristicIterator = mCurrentService.getCharacteristics().iterator();
            maybeReadNextCharacteristic();
            return;
        }

        // All services have been read. Finish the current device read.
        finishAndMaybeReadNextDevice();
    }

    @Override
    public void onCharacteristicRead(
            BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        super.onCharacteristicRead(gatt, characteristic, status);

        if (status != BluetoothGatt.GATT_SUCCESS) {
            Log.e(TAG, "onCharacteristicRead failed: " + mCurrentDevice + ", status: " + status);
            cancelAndMaybeReadNextDevice();
            return;
        }

        maybeReadNextCharacteristic();
    }

    private void maybeReadNextCharacteristic() {
        if (!mCurrentCharacteristicIterator.hasNext()) {
            // All characteristics have been read. Finish the current service read.
            final BluetoothDevice device = mCurrentDevice;
            final BluetoothGattService service = mCurrentService;
            mExecutor.submit(
                    new Runnable() {
                        @Override
                        public void run() {
                            mHandler.onGattRead(device, service);
                        }
                    });
            maybeReadNextService();
            return;
        }

        BluetoothGattCharacteristic characteristic = mCurrentCharacteristicIterator.next();
        if (!mCurrentGatt.readCharacteristic(characteristic)) {
            Log.e(TAG, "readCharacteristic failed: " + mCurrentDevice);
            cancelAndMaybeReadNextDevice();
        }
    }
}
