/*
 * Java
 *
 * Copyright 2020-2024 MicroEJ Corp. All rights reserved.
 * This library is provided in source code for use, modification and test, subject to license terms.
 * Any modification of the source code will break MicroEJ Corp. warranties on the whole library.
 */
package ej.bluetooth.util;

import java.io.PrintStream;

import ej.bluetooth.BluetoothCharacteristic;
import ej.bluetooth.BluetoothDescriptor;
import ej.bluetooth.BluetoothPermissions;
import ej.bluetooth.BluetoothService;
import ej.bluetooth.BluetoothUuid;

/**
 * Provides utility methods related to GATT services.
 */
public class ServiceHelper {

	private ServiceHelper() {
		// private constructor
	}

	/**
	 * Returns the read permission for the given security level.
	 *
	 * @param securityLevel
	 *            the security level (see {@link SecurityLevels}).
	 * @return the read permission for the given security level (see {@link BluetoothPermissions}).
	 */
	public static int getReadPermission(int securityLevel) {
		switch (securityLevel) {
		case SecurityLevels.NONE:
			return BluetoothPermissions.READ;
		case SecurityLevels.ENCRYPT:
			return BluetoothPermissions.READ_ENCRYPT;
		case SecurityLevels.AUTH:
			return BluetoothPermissions.READ_AUTH;
		default:
			throw new IllegalArgumentException();
		}
	}

	/**
	 * Returns the write permission for the given security level.
	 *
	 * @param securityLevel
	 *            the security level (see {@link SecurityLevels}).
	 * @return the write permission for the given security level (see {@link BluetoothPermissions}).
	 */
	public static int getWritePermission(int securityLevel) {
		switch (securityLevel) {
		case SecurityLevels.NONE:
			return BluetoothPermissions.WRITE;
		case SecurityLevels.ENCRYPT:
			return BluetoothPermissions.WRITE_ENCRYPT;
		case SecurityLevels.AUTH:
			return BluetoothPermissions.WRITE_AUTH;
		default:
			throw new IllegalArgumentException();
		}
	}

	/**
	 * Returns the characteristic with the given UUID in the given service.
	 * <p>
	 * If multiple characteristics have the same UUID, any of them may be returned.
	 *
	 * @param service
	 *            the service to search in.
	 * @param characteristicUuid
	 *            the UUID of the characteristic to look for.
	 * @return the characteristic with the given UUID.
	 * @throws AttributeNotFoundException
	 *             if this service does not provide a characteristic with the given UUID.
	 */
	public static BluetoothCharacteristic getCharacteristic(BluetoothService service, BluetoothUuid characteristicUuid)
			throws AttributeNotFoundException {
		int numCharacteristics = service.getNumCharacteristics();
		for (int i = 0; i < numCharacteristics; i++) {
			BluetoothCharacteristic characteristic = service.getCharacteristic(i);
			if (characteristic.getUuid().equals(characteristicUuid)) {
				return characteristic;
			}
		}
		throw new AttributeNotFoundException();
	}

	/**
	 * Returns the descriptor with the given UUID in the given characteristic.
	 * <p>
	 * If multiple descriptors have the same UUID, any of them may be returned.
	 *
	 * @param characteristic
	 *            the characteristic to search in.
	 * @param descriptorUuid
	 *            the UUID of the descriptor to look for.
	 * @return the descriptor with the given UUID.
	 * @throws AttributeNotFoundException
	 *             if this characteristic does not provide a descriptor with the given UUID.
	 */
	public static BluetoothDescriptor getDescriptor(BluetoothCharacteristic characteristic,
			BluetoothUuid descriptorUuid) throws AttributeNotFoundException {
		int numDescriptors = characteristic.getNumDescriptors();
		for (int i = 0; i < numDescriptors; i++) {
			BluetoothDescriptor descriptor = characteristic.getDescriptor(i);
			if (descriptor.getUuid().equals(descriptorUuid)) {
				return descriptor;
			}
		}
		throw new AttributeNotFoundException();
	}

	/**
	 * Prints information on the given service to the given print stream.
	 *
	 * @param service
	 *            the service to inspect.
	 * @param printStream
	 *            the print stream to print to.
	 */
	public static void printService(BluetoothService service, PrintStream printStream) {
		// print service info
		printStream.println("[SERVICE] " + service.getUuid());

		int numCharacteristics = service.getNumCharacteristics();
		for (int c = 0; c < numCharacteristics; c++) {
			// print characteristic info
			BluetoothCharacteristic characteristic = service.getCharacteristic(c);
			String propertiesString = Integer.toHexString(characteristic.getProperties() & 0xFF);
			printStream.println("\t[CHAR] " + characteristic.getUuid() + " P=0x" + propertiesString);

			int numDescriptors = characteristic.getNumDescriptors();
			for (int d = 0; d < numDescriptors; d++) {
				// print descriptor info
				BluetoothDescriptor descriptor = characteristic.getDescriptor(d);
				printStream.println("\t\t[DESC] " + descriptor.getUuid());
			}
		}
	}
}
