/*
 * Copyright (C) 2016 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 com.android.bluetooth.gatt;

import android.bluetooth.BluetoothUuid;
import android.bluetooth.le.AdvertiseData;
import android.os.ParcelUuid;
import android.util.Log;

import java.io.ByteArrayOutputStream;

class AdvertiseHelper {

    private static final String TAG = "AdvertiseHelper";

    private static final int DEVICE_NAME_MAX = 26;

    private static final int COMPLETE_LIST_16_BIT_SERVICE_UUIDS = 0X03;
    private static final int COMPLETE_LIST_32_BIT_SERVICE_UUIDS = 0X05;
    private static final int COMPLETE_LIST_128_BIT_SERVICE_UUIDS = 0X07;
    private static final int SHORTENED_LOCAL_NAME = 0X08;
    private static final int COMPLETE_LOCAL_NAME = 0X09;
    private static final int TX_POWER_LEVEL = 0x0A;
    private static final int SERVICE_DATA_16_BIT_UUID = 0X16;
    private static final int SERVICE_DATA_32_BIT_UUID = 0X20;
    private static final int SERVICE_DATA_128_BIT_UUID = 0X21;
    private static final int MANUFACTURER_SPECIFIC_DATA = 0XFF;

    public static byte[] advertiseDataToBytes(AdvertiseData data, String name) {

        if (data == null) {
            return new byte[0];
        }

        // Flags are added by lower layers of the stack, only if needed;
        // no need to add them here.

        ByteArrayOutputStream ret = new ByteArrayOutputStream();

        if (data.getIncludeDeviceName()) {
            try {
                byte[] nameBytes = name.getBytes("UTF-8");

                int nameLength = nameBytes.length;
                byte type;

                // TODO(jpawlowski) put a better limit on device name!
                if (nameLength > DEVICE_NAME_MAX) {
                    nameLength = DEVICE_NAME_MAX;
                    type = SHORTENED_LOCAL_NAME;
                } else {
                    type = COMPLETE_LOCAL_NAME;
                }

                ret.write(nameLength + 1);
                ret.write(type);
                ret.write(nameBytes, 0, nameLength);
            } catch (java.io.UnsupportedEncodingException e) {
                Log.e(TAG, "Can't include name - encoding error!", e);
            }
        }

        for (int i = 0; i < data.getManufacturerSpecificData().size(); i++) {
            int manufacturerId = data.getManufacturerSpecificData().keyAt(i);

            byte[] manufacturerData = data.getManufacturerSpecificData().get(manufacturerId);
            int dataLen = 2 + (manufacturerData == null ? 0 : manufacturerData.length);
            byte[] concated = new byte[dataLen];
            // First two bytes are manufacturer id in little-endian.
            concated[0] = (byte) (manufacturerId & 0xFF);
            concated[1] = (byte) ((manufacturerId >> 8) & 0xFF);
            if (manufacturerData != null) {
                System.arraycopy(manufacturerData, 0, concated, 2, manufacturerData.length);
            }

            ret.write(concated.length + 1);
            ret.write(MANUFACTURER_SPECIFIC_DATA);
            ret.write(concated, 0, concated.length);
        }

        if (data.getIncludeTxPowerLevel()) {
            ret.write(2 /* Length */);
            ret.write(TX_POWER_LEVEL);
            ret.write(0); // lower layers will fill this value.
        }

        if (data.getServiceUuids() != null) {
            ByteArrayOutputStream serviceUuids16 = new ByteArrayOutputStream();
            ByteArrayOutputStream serviceUuids32 = new ByteArrayOutputStream();
            ByteArrayOutputStream serviceUuids128 = new ByteArrayOutputStream();

            for (ParcelUuid parcelUuid : data.getServiceUuids()) {
                byte[] uuid = BluetoothUuid.uuidToBytes(parcelUuid);

                if (uuid.length == BluetoothUuid.UUID_BYTES_16_BIT) {
                    serviceUuids16.write(uuid, 0, uuid.length);
                } else if (uuid.length == BluetoothUuid.UUID_BYTES_32_BIT) {
                    serviceUuids32.write(uuid, 0, uuid.length);
                } else /*if (uuid.length == BluetoothUuid.UUID_BYTES_128_BIT)*/ {
                    serviceUuids128.write(uuid, 0, uuid.length);
                }
            }

            if (serviceUuids16.size() != 0) {
                ret.write(serviceUuids16.size() + 1);
                ret.write(COMPLETE_LIST_16_BIT_SERVICE_UUIDS);
                ret.write(serviceUuids16.toByteArray(), 0, serviceUuids16.size());
            }

            if (serviceUuids32.size() != 0) {
                ret.write(serviceUuids32.size() + 1);
                ret.write(COMPLETE_LIST_32_BIT_SERVICE_UUIDS);
                ret.write(serviceUuids32.toByteArray(), 0, serviceUuids32.size());
            }

            if (serviceUuids128.size() != 0) {
                ret.write(serviceUuids128.size() + 1);
                ret.write(COMPLETE_LIST_128_BIT_SERVICE_UUIDS);
                ret.write(serviceUuids128.toByteArray(), 0, serviceUuids128.size());
            }
        }

        if (!data.getServiceData().isEmpty()) {
            for (ParcelUuid parcelUuid : data.getServiceData().keySet()) {
                byte[] serviceData = data.getServiceData().get(parcelUuid);

                byte[] uuid = BluetoothUuid.uuidToBytes(parcelUuid);
                int uuidLen = uuid.length;

                int dataLen = uuidLen + (serviceData == null ? 0 : serviceData.length);
                byte[] concated = new byte[dataLen];

                System.arraycopy(uuid, 0, concated, 0, uuidLen);

                if (serviceData != null) {
                    System.arraycopy(serviceData, 0, concated, uuidLen, serviceData.length);
                }

                if (uuid.length == BluetoothUuid.UUID_BYTES_16_BIT) {
                    ret.write(concated.length + 1);
                    ret.write(SERVICE_DATA_16_BIT_UUID);
                    ret.write(concated, 0, concated.length);
                } else if (uuid.length == BluetoothUuid.UUID_BYTES_32_BIT) {
                    ret.write(concated.length + 1);
                    ret.write(SERVICE_DATA_32_BIT_UUID);
                    ret.write(concated, 0, concated.length);
                } else /*if (uuid.length == BluetoothUuid.UUID_BYTES_128_BIT)*/ {
                    ret.write(concated.length + 1);
                    ret.write(SERVICE_DATA_128_BIT_UUID);
                    ret.write(concated, 0, concated.length);
                }
            }
        }

        return ret.toByteArray();
    }
}
