// 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.lang.reflect.Method;
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);
        mExecutor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
        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(boolean graceful) {
        mPendingReads.clear();
        if (graceful) {
            // Wait until the current read finishes to avoid messing up the Bluetooth stack.
            while (mCurrentDevice != null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    break;
                }
            }
        }
        mExecutor.shutdown();
        if (mCurrentGatt != null) {
            mCurrentGatt.close();
        }
    }

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

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

        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);
        // Try to refresh the failed Gatt.
        try {
            Method method = mCurrentGatt.getClass().getMethod("refresh", new Class[0]);
            if (method != null) {
                method.invoke(mCurrentGatt, new Object[0]);
            }
        } catch (Exception e) {
            Log.e(TAG, "An exception occured while refreshing device");
        }
        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;
        }

        // TODO(jhahn): Do we really need this?
        if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);
        }

        // 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();
        }
    }
}
