package de.eseidinger.android.sensors.impl.bluetooth_le;

import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import de.eseidinger.android.sensors.api.IValueUpdateListener;
import de.eseidinger.android.sensors.util.BluetoothLeUtils;
import de.eseidinger.android.sensors.values.HeartRateValues;

/**
 * A connection to a Bluetooth LE heart rate sensor.
 */
public final class BluetoothLeHeartRateSensor extends AbstractBluetoothLeSensor<HeartRateValues> {

    /**
     * Get a connection to a Bluetooth LE heart rate sensor with a given address.
     *
     * @param address of the sensor
     * @return heart rate connection
     */
    public static BluetoothLeHeartRateSensor get(String address) {
        if (heartRateDeviceMap.containsKey(address)) {
            return heartRateDeviceMap.get(address);
        } else {
            BluetoothLeHeartRateSensor device = new BluetoothLeHeartRateSensor(address);
            heartRateDeviceMap.put(address, device);
            return device;
        }
    }

    private static final Map<String, BluetoothLeHeartRateSensor> heartRateDeviceMap = new HashMap<>();

    private final String address;

    private final GattRunnable onCharacteristicChange = new GattRunnable() {
        @Override
        public void run(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            if (UUID.fromString(BluetoothLeUtils.BT_LE_HEART_RATE_CHARACTERISTIC).
                    equals(characteristic.getUuid())) {
                int flag = characteristic.getProperties();
                int format = -1;
                if ((flag & 0x01) != 0) {
                    format = BluetoothGattCharacteristic.FORMAT_UINT16;
                } else {
                    format = BluetoothGattCharacteristic.FORMAT_UINT8;
                }
                int heartRate = characteristic.getIntValue(format, 1);
                updateValueListener(HeartRateValues.create(new Date().getTime(), heartRate));
            }
        }
    };

    private BluetoothLeHeartRateSensor(String address) {
        this.address = address;
    }

    @Override
    protected String getService() {
        return BluetoothLeUtils.BT_LE_HEART_RATE_SERVICE;
    }

    @Override
    protected String getCharacteristic() {
        return BluetoothLeUtils.BT_LE_HEART_RATE_CHARACTERISTIC;
    }

    @Override
    protected String getAddress() {
        return this.address;
    }

    @Override
    protected GattRunnable getOnCharacteristicChange() {
        return this.onCharacteristicChange;
    }
}
