/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.bluetooth;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * Public API for the Bluetooth GATT Profile server role.
 *
 * <p>This class provides Bluetooth GATT server role functionality,
 * allowing applications to create Bluetooth Smart services and
 * characteristics.
 *
 * <p>BluetoothGattServer is a proxy object for controlling the Bluetooth Service
 * via IPC.  Use {@link BluetoothManager#openGattServer} to get an instance
 * of this class.
 */
public final class BluetoothGattServer implements BluetoothProfile {
    private static final String TAG = "BluetoothGattServer";
    private static final boolean DBG = true;
    private static final boolean VDBG = false;

    private BluetoothAdapter mAdapter;
    private IBluetoothGatt mService;
    private BluetoothGattServerCallback mCallback;

    private Object mServerIfLock = new Object();
    private int mServerIf;
    private int mTransport;
    private BluetoothGattService mPendingService;
    private List<BluetoothGattService> mServices;

    private static final int CALLBACK_REG_TIMEOUT = 10000;

    /**
     * Bluetooth GATT interface callbacks
     */
    private final IBluetoothGattServerCallback mBluetoothGattServerCallback =
        new IBluetoothGattServerCallback.Stub() {
            /**
             * Application interface registered - app is ready to go
             * @hide
             */
            public void onServerRegistered(int status, int serverIf) {
                if (DBG) Log.d(TAG, "onServerRegistered() - status=" + status
                    + " serverIf=" + serverIf);
                synchronized(mServerIfLock) {
                    if (mCallback != null) {
                        mServerIf = serverIf;
                        mServerIfLock.notify();
                    } else {
                        // registration timeout
                        Log.e(TAG, "onServerRegistered: mCallback is null");
                    }
                }
            }

            /**
             * Callback reporting an LE scan result.
             * @hide
             */
            public void onScanResult(String address, int rssi, byte[] advData) {
                if (VDBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi);
                // no op
            }

            /**
             * Server connection state changed
             * @hide
             */
            public void onServerConnectionState(int status, int serverIf,
                                                boolean connected, String address) {
                if (DBG) Log.d(TAG, "onServerConnectionState() - status=" + status
                    + " serverIf=" + serverIf + " device=" + address);
                try {
                    mCallback.onConnectionStateChange(mAdapter.getRemoteDevice(address), status,
                                                      connected ? BluetoothProfile.STATE_CONNECTED :
                                                      BluetoothProfile.STATE_DISCONNECTED);
                } catch (Exception ex) {
                    Log.w(TAG, "Unhandled exception in callback", ex);
                }
            }

            /**
             * Service has been added
             * @hide
             */
            public void onServiceAdded(int status, BluetoothGattService service) {
                if (DBG) Log.d(TAG, "onServiceAdded() - handle=" + service.getInstanceId()
                    + " uuid=" + service.getUuid() + " status=" + status);

                if (mPendingService == null)
                    return;

                BluetoothGattService tmp = mPendingService;
                mPendingService = null;

                // Rewrite newly assigned handles to existing service.
                tmp.setInstanceId(service.getInstanceId());
                List<BluetoothGattCharacteristic> temp_chars = tmp.getCharacteristics();
                List<BluetoothGattCharacteristic> svc_chars = service.getCharacteristics();
                for (int i=0; i<svc_chars.size(); i++) {
                    BluetoothGattCharacteristic temp_char = temp_chars.get(i);
                    BluetoothGattCharacteristic svc_char = svc_chars.get(i);

                    temp_char.setInstanceId(svc_char.getInstanceId());

                    List<BluetoothGattDescriptor> temp_descs = temp_char.getDescriptors();
                    List<BluetoothGattDescriptor> svc_descs = svc_char.getDescriptors();
                    for (int j=0; j<svc_descs.size(); j++) {
                        temp_descs.get(j).setInstanceId(svc_descs.get(j).getInstanceId());
                    }
                }

                mServices.add(tmp);

                try {
                    mCallback.onServiceAdded((int)status, tmp);
                } catch (Exception ex) {
                    Log.w(TAG, "Unhandled exception in callback", ex);
                }
            }

            /**
             * Remote client characteristic read request.
             * @hide
             */
            public void onCharacteristicReadRequest(String address, int transId,
                            int offset, boolean isLong, int handle) {
                if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle);

                BluetoothDevice device = mAdapter.getRemoteDevice(address);
                BluetoothGattCharacteristic characteristic = getCharacteristicByHandle(handle);
                if (characteristic == null) {
                    Log.w(TAG, "onCharacteristicReadRequest() no char for handle " + handle);
                    return;
                }

                try {
                    mCallback.onCharacteristicReadRequest(device, transId, offset, characteristic);
                } catch (Exception ex) {
                    Log.w(TAG, "Unhandled exception in callback", ex);
                }
            }

            /**
             * Remote client descriptor read request.
             * @hide
             */
            public void onDescriptorReadRequest(String address, int transId,
                            int offset, boolean isLong, int handle) {
                if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle);

                BluetoothDevice device = mAdapter.getRemoteDevice(address);
                BluetoothGattDescriptor descriptor = getDescriptorByHandle(handle);
                if (descriptor == null) {
                    Log.w(TAG, "onDescriptorReadRequest() no desc for handle " + handle);
                    return;
                }

                try {
                    mCallback.onDescriptorReadRequest(device, transId, offset, descriptor);
                } catch (Exception ex) {
                    Log.w(TAG, "Unhandled exception in callback", ex);
                }
            }

            /**
             * Remote client characteristic write request.
             * @hide
             */
            public void onCharacteristicWriteRequest(String address, int transId,
                            int offset, int length, boolean isPrep, boolean needRsp,
                            int handle, byte[] value) {
                if (VDBG) Log.d(TAG, "onCharacteristicWriteRequest() - handle=" + handle);

                BluetoothDevice device = mAdapter.getRemoteDevice(address);
                BluetoothGattCharacteristic characteristic = getCharacteristicByHandle(handle);
                if (characteristic == null) {
                    Log.w(TAG, "onCharacteristicWriteRequest() no char for handle " + handle);
                    return;
                }

                try {
                    mCallback.onCharacteristicWriteRequest(device, transId, characteristic,
                                                           isPrep, needRsp, offset, value);
                } catch (Exception ex) {
                    Log.w(TAG, "Unhandled exception in callback", ex);
                }

            }

            /**
             * Remote client descriptor write request.
             * @hide
             */
            public void onDescriptorWriteRequest(String address, int transId, int offset,
                            int length, boolean isPrep, boolean needRsp, int handle, byte[] value) {
                if (VDBG) Log.d(TAG, "onDescriptorWriteRequest() - handle=" + handle);

                BluetoothDevice device = mAdapter.getRemoteDevice(address);
                BluetoothGattDescriptor descriptor = getDescriptorByHandle(handle);
                if (descriptor == null) {
                    Log.w(TAG, "onDescriptorWriteRequest() no desc for handle " + handle);
                    return;
                }

                try {
                    mCallback.onDescriptorWriteRequest(device, transId, descriptor,
                                                       isPrep, needRsp, offset, value);
                } catch (Exception ex) {
                    Log.w(TAG, "Unhandled exception in callback", ex);
                }
            }

            /**
             * Execute pending writes.
             * @hide
             */
            public void onExecuteWrite(String address, int transId,
                                       boolean execWrite) {
                if (DBG) Log.d(TAG, "onExecuteWrite() - "
                    + "device=" + address + ", transId=" + transId
                    + "execWrite=" + execWrite);

                BluetoothDevice device = mAdapter.getRemoteDevice(address);
                if (device == null) return;

                try {
                    mCallback.onExecuteWrite(device, transId, execWrite);
                } catch (Exception ex) {
                    Log.w(TAG, "Unhandled exception in callback", ex);
                }
            }

            /**
             * A notification/indication has been sent.
             * @hide
             */
            public void onNotificationSent(String address, int status) {
                if (VDBG) Log.d(TAG, "onNotificationSent() - "
                    + "device=" + address + ", status=" + status);

                BluetoothDevice device = mAdapter.getRemoteDevice(address);
                if (device == null) return;

                try {
                    mCallback.onNotificationSent(device, status);
                } catch (Exception ex) {
                    Log.w(TAG, "Unhandled exception: " + ex);
                }
            }

            /**
             * The MTU for a connection has changed
             * @hide
             */
            public void onMtuChanged(String address, int mtu) {
                if (DBG) Log.d(TAG, "onMtuChanged() - "
                    + "device=" + address + ", mtu=" + mtu);

                BluetoothDevice device = mAdapter.getRemoteDevice(address);
                if (device == null) return;

                try {
                    mCallback.onMtuChanged(device, mtu);
                } catch (Exception ex) {
                    Log.w(TAG, "Unhandled exception: " + ex);
                }
            }
        };

    /**
     * Create a BluetoothGattServer proxy object.
     */
    /*package*/ BluetoothGattServer(IBluetoothGatt iGatt, int transport) {
        mService = iGatt;
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mCallback = null;
        mServerIf = 0;
        mTransport = transport;
        mServices = new ArrayList<BluetoothGattService>();
    }

    /**
     * Returns a characteristic with given handle.
     * @hide
     */
    /*package*/ BluetoothGattCharacteristic getCharacteristicByHandle(int handle) {
        for(BluetoothGattService svc : mServices) {
            for(BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
                if (charac.getInstanceId() == handle)
                    return charac;
            }
        }
        return null;
    }

    /**
     * Returns a descriptor with given handle.
     * @hide
     */
    /*package*/ BluetoothGattDescriptor getDescriptorByHandle(int handle) {
        for(BluetoothGattService svc : mServices) {
            for(BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
                for(BluetoothGattDescriptor desc : charac.getDescriptors()) {
                    if (desc.getInstanceId() == handle)
                        return desc;
                }
            }
        }
        return null;
    }

    /**
     * Close this GATT server instance.
     *
     * Application should call this method as early as possible after it is done with
     * this GATT server.
     */
    public void close() {
        if (DBG) Log.d(TAG, "close()");
        unregisterCallback();
    }

    /**
     * Register an application callback to start using GattServer.
     *
     * <p>This is an asynchronous call. The callback is used to notify
     * success or failure if the function returns true.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param callback GATT callback handler that will receive asynchronous
     *                 callbacks.
     * @return true, the callback will be called to notify success or failure,
     *         false on immediate error
     */
    /*package*/ boolean registerCallback(BluetoothGattServerCallback callback) {
        if (DBG) Log.d(TAG, "registerCallback()");
        if (mService == null) {
            Log.e(TAG, "GATT service not available");
            return false;
        }
        UUID uuid = UUID.randomUUID();
        if (DBG) Log.d(TAG, "registerCallback() - UUID=" + uuid);

        synchronized(mServerIfLock) {
            if (mCallback != null) {
                Log.e(TAG, "App can register callback only once");
                return false;
            }

            mCallback = callback;
            try {
                mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback);
            } catch (RemoteException e) {
                Log.e(TAG,"",e);
                mCallback = null;
                return false;
            }

            try {
                mServerIfLock.wait(CALLBACK_REG_TIMEOUT);
            } catch (InterruptedException e) {
                Log.e(TAG, "" + e);
                mCallback = null;
            }

            if (mServerIf == 0) {
                mCallback = null;
                return false;
            } else {
                return true;
            }
        }
    }

    /**
     * Unregister the current application and callbacks.
     */
    private void unregisterCallback() {
        if (DBG) Log.d(TAG, "unregisterCallback() - mServerIf=" + mServerIf);
        if (mService == null || mServerIf == 0) return;

        try {
            mCallback = null;
            mService.unregisterServer(mServerIf);
            mServerIf = 0;
        } catch (RemoteException e) {
            Log.e(TAG,"",e);
        }
    }

    /**
     * Returns a service by UUID, instance and type.
     * @hide
     */
    /*package*/ BluetoothGattService getService(UUID uuid, int instanceId, int type) {
        for(BluetoothGattService svc : mServices) {
            if (svc.getType() == type &&
                svc.getInstanceId() == instanceId &&
                svc.getUuid().equals(uuid)) {
                return svc;
            }
        }
        return null;
    }

    /**
     * Initiate a connection to a Bluetooth GATT capable device.
     *
     * <p>The connection may not be established right away, but will be
     * completed when the remote device is available. A
     * {@link BluetoothGattServerCallback#onConnectionStateChange} callback will be
     * invoked when the connection state changes as a result of this function.
     *
     * <p>The autoConnect paramter determines whether to actively connect to
     * the remote device, or rather passively scan and finalize the connection
     * when the remote device is in range/available. Generally, the first ever
     * connection to a device should be direct (autoConnect set to false) and
     * subsequent connections to known devices should be invoked with the
     * autoConnect parameter set to true.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param autoConnect Whether to directly connect to the remote device (false)
     *                    or to automatically connect as soon as the remote
     *                    device becomes available (true).
     * @return true, if the connection attempt was initiated successfully
     */
    public boolean connect(BluetoothDevice device, boolean autoConnect) {
        if (DBG) Log.d(TAG, "connect() - device: " + device.getAddress() + ", auto: " + autoConnect);
        if (mService == null || mServerIf == 0) return false;

        try {
            mService.serverConnect(mServerIf, device.getAddress(),
                               autoConnect ? false : true,mTransport); // autoConnect is inverse of "isDirect"
        } catch (RemoteException e) {
            Log.e(TAG,"",e);
            return false;
        }

        return true;
    }

    /**
     * Disconnects an established connection, or cancels a connection attempt
     * currently in progress.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param device Remote device
     */
    public void cancelConnection(BluetoothDevice device) {
        if (DBG) Log.d(TAG, "cancelConnection() - device: " + device.getAddress());
        if (mService == null || mServerIf == 0) return;

        try {
            mService.serverDisconnect(mServerIf, device.getAddress());
        } catch (RemoteException e) {
            Log.e(TAG,"",e);
        }
    }

    /**
     * Send a response to a read or write request to a remote device.
     *
     * <p>This function must be invoked in when a remote read/write request
     * is received by one of these callback methods:
     *
     * <ul>
     *      <li>{@link BluetoothGattServerCallback#onCharacteristicReadRequest}
     *      <li>{@link BluetoothGattServerCallback#onCharacteristicWriteRequest}
     *      <li>{@link BluetoothGattServerCallback#onDescriptorReadRequest}
     *      <li>{@link BluetoothGattServerCallback#onDescriptorWriteRequest}
     * </ul>
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param device The remote device to send this response to
     * @param requestId The ID of the request that was received with the callback
     * @param status The status of the request to be sent to the remote devices
     * @param offset Value offset for partial read/write response
     * @param value The value of the attribute that was read/written (optional)
     */
    public boolean sendResponse(BluetoothDevice device, int requestId,
                                int status, int offset, byte[] value) {
        if (VDBG) Log.d(TAG, "sendResponse() - device: " + device.getAddress());
        if (mService == null || mServerIf == 0) return false;

        try {
            mService.sendResponse(mServerIf, device.getAddress(), requestId,
                                  status, offset, value);
        } catch (RemoteException e) {
            Log.e(TAG,"",e);
            return false;
        }
        return true;
    }

    /**
     * Send a notification or indication that a local characteristic has been
     * updated.
     *
     * <p>A notification or indication is sent to the remote device to signal
     * that the characteristic has been updated. This function should be invoked
     * for every client that requests notifications/indications by writing
     * to the "Client Configuration" descriptor for the given characteristic.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param device The remote device to receive the notification/indication
     * @param characteristic The local characteristic that has been updated
     * @param confirm true to request confirmation from the client (indication),
     *                false to send a notification
     * @throws IllegalArgumentException
     * @return true, if the notification has been triggered successfully
     */
    public boolean notifyCharacteristicChanged(BluetoothDevice device,
                    BluetoothGattCharacteristic characteristic, boolean confirm) {
        if (VDBG) Log.d(TAG, "notifyCharacteristicChanged() - device: " + device.getAddress());
        if (mService == null || mServerIf == 0) return false;

        BluetoothGattService service = characteristic.getService();
        if (service == null) return false;

        if (characteristic.getValue() == null) {
            throw new IllegalArgumentException("Chracteristic value is empty. Use "
                    + "BluetoothGattCharacteristic#setvalue to update");
        }

        try {
            mService.sendNotification(mServerIf, device.getAddress(),
                    characteristic.getInstanceId(), confirm,
                    characteristic.getValue());
        } catch (RemoteException e) {
            Log.e(TAG,"",e);
            return false;
        }

        return true;
    }

    /**
     * Add a service to the list of services to be hosted.
     *
     * <p>Once a service has been addded to the the list, the service and its
     * included characteristics will be provided by the local device.
     *
     * <p>If the local device has already exposed services when this function
     * is called, a service update notification will be sent to all clients.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param service Service to be added to the list of services provided
     *                by this device.
     * @return true, if the service has been added successfully
     */
    public boolean addService(BluetoothGattService service) {
        if (DBG) Log.d(TAG, "addService() - service: " + service.getUuid());
        if (mService == null || mServerIf == 0) return false;

        mPendingService = service;

        try {
            mService.addService(mServerIf, service);
        } catch (RemoteException e) {
            Log.e(TAG,"",e);
            return false;
        }

        return true;
    }

    /**
     * Removes a service from the list of services to be provided.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param service Service to be removed.
     * @return true, if the service has been removed
     */
    public boolean removeService(BluetoothGattService service) {
        if (DBG) Log.d(TAG, "removeService() - service: " + service.getUuid());
        if (mService == null || mServerIf == 0) return false;

        BluetoothGattService intService = getService(service.getUuid(),
                                service.getInstanceId(), service.getType());
        if (intService == null) return false;

        try {
            mService.removeService(mServerIf, service.getInstanceId());
            mServices.remove(intService);
        } catch (RemoteException e) {
            Log.e(TAG,"",e);
            return false;
        }

        return true;
    }

    /**
     * Remove all services from the list of provided services.
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     */
    public void clearServices() {
        if (DBG) Log.d(TAG, "clearServices()");
        if (mService == null || mServerIf == 0) return;

        try {
            mService.clearServices(mServerIf);
            mServices.clear();
        } catch (RemoteException e) {
            Log.e(TAG,"",e);
        }
    }

    /**
     * Returns a list of GATT services offered by this device.
     *
     * <p>An application must call {@link #addService} to add a serice to the
     * list of services offered by this device.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @return List of services. Returns an empty list
     *         if no services have been added yet.
     */
    public List<BluetoothGattService> getServices() {
        return mServices;
    }

    /**
     * Returns a {@link BluetoothGattService} from the list of services offered
     * by this device.
     *
     * <p>If multiple instances of the same service (as identified by UUID)
     * exist, the first instance of the service is returned.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param uuid UUID of the requested service
     * @return BluetoothGattService if supported, or null if the requested
     *         service is not offered by this device.
     */
    public BluetoothGattService getService(UUID uuid) {
        for (BluetoothGattService service : mServices) {
            if (service.getUuid().equals(uuid)) {
                return service;
            }
        }

        return null;
    }


    /**
     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
     * with {@link BluetoothProfile#GATT} as argument
     *
     * @throws UnsupportedOperationException
     */
    @Override
    public int getConnectionState(BluetoothDevice device) {
        throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
    }

    /**
     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
     * with {@link BluetoothProfile#GATT} as argument
     *
     * @throws UnsupportedOperationException
     */
    @Override
    public List<BluetoothDevice> getConnectedDevices() {
        throw new UnsupportedOperationException
            ("Use BluetoothManager#getConnectedDevices instead.");
    }

    /**
     * Not supported - please use
     * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
     * with {@link BluetoothProfile#GATT} as first argument
     *
     * @throws UnsupportedOperationException
     */
    @Override
    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
        throw new UnsupportedOperationException
            ("Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
    }
}
