/*
 * Copyright (C) 2014 Tieto Poland
 *
 * 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.
 *
 */

#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <malloc.h>
#include <dlfcn.h>

#include "audio-msg.h"
#include "hal-audio.h"
#include "hal-log.h"
#include "src/shared/util.h"
#include "profiles/audio/a2dp-codecs.h"

#define APTX_SO_NAME	"libbt-aptx.so"

struct aptx_data {
	a2dp_aptx_t aptx;

	void *enc;
};

static const a2dp_aptx_t aptx_presets[] = {
	{
		.info = {
			.vendor_id = APTX_VENDOR_ID,
			.codec_id = APTX_CODEC_ID,
		},
		.frequency = APTX_SAMPLING_FREQ_44100 |
						APTX_SAMPLING_FREQ_48000,
		.channel_mode = APTX_CHANNEL_MODE_STEREO,
	},
	{
		.info = {
			.vendor_id = APTX_VENDOR_ID,
			.codec_id = APTX_CODEC_ID,
		},
		.frequency = APTX_SAMPLING_FREQ_48000,
		.channel_mode = APTX_CHANNEL_MODE_STEREO,
	},
	{
		.info = {
			.vendor_id = APTX_VENDOR_ID,
			.codec_id = APTX_CODEC_ID,
		},
		.frequency = APTX_SAMPLING_FREQ_44100,
		.channel_mode = APTX_CHANNEL_MODE_STEREO,
	},
};

static void *aptx_handle;
static int aptx_btencsize;
static int (*aptx_init)(void *, short);
static int (*aptx_encode)(void *, void *, void *, void *);

static bool aptx_load(void)
{
	const char * (*aptx_version)(void);
	const char * (*aptx_build)(void);
	int (*aptx_sizeofenc)(void);

	aptx_handle = dlopen(APTX_SO_NAME, RTLD_LAZY);
	if (!aptx_handle) {
		error("APTX: failed to open library %s (%s)", APTX_SO_NAME,
								dlerror());
		return false;
	}

	aptx_version = dlsym(aptx_handle, "aptxbtenc_version");
	aptx_build = dlsym(aptx_handle, "aptxbtenc_build");

	if (aptx_version && aptx_build)
		info("APTX: using library version %s build %s", aptx_version(),
								aptx_build());
	else
		warn("APTX: cannot retrieve library version");

	aptx_sizeofenc = dlsym(aptx_handle, "SizeofAptxbtenc");
	aptx_init = dlsym(aptx_handle, "aptxbtenc_init");
	aptx_encode = dlsym(aptx_handle, "aptxbtenc_encodestereo");
	if (!aptx_sizeofenc || !aptx_init || !aptx_encode) {
		error("APTX: failed initialize library");
		dlclose(aptx_handle);
		aptx_handle = NULL;
		return false;
	}
	aptx_btencsize = aptx_sizeofenc();

	info("APTX: codec library initialized (size=%d)", aptx_btencsize);

	return true;
}

static void aptx_unload(void)
{
	if (!aptx_handle)
		return;

	dlclose(aptx_handle);
	aptx_handle = NULL;
}

static int aptx_get_presets(struct audio_preset *preset, size_t *len)
{
	int i;
	int count;
	size_t new_len = 0;
	uint8_t *ptr = (uint8_t *) preset;
	size_t preset_size = sizeof(*preset) + sizeof(a2dp_aptx_t);

	DBG("");

	count = sizeof(aptx_presets) / sizeof(aptx_presets[0]);

	for (i = 0; i < count; i++) {
		preset = (struct audio_preset *) ptr;

		if (new_len + preset_size > *len)
			break;

		preset->len = sizeof(a2dp_aptx_t);
		memcpy(preset->data, &aptx_presets[i], preset->len);

		new_len += preset_size;
		ptr += preset_size;
	}

	*len = new_len;

	return i;
}

static bool aptx_codec_init(struct audio_preset *preset, uint16_t payload_len,
							void **codec_data)
{
	struct aptx_data *aptx_data;

	DBG("");

	if (preset->len != sizeof(a2dp_aptx_t)) {
		error("APTX: preset size mismatch");
		return false;
	}

	aptx_data = new0(struct aptx_data, 1);
	if (!aptx_data)
		return false;

	memcpy(&aptx_data->aptx, preset->data, preset->len);

	aptx_data->enc = calloc(1, aptx_btencsize);
	if (!aptx_data->enc) {
		error("APTX: failed to create encoder");
		free(aptx_data);
		return false;
	}

	/* 1 = big-endian, this is what devices are using */
	aptx_init(aptx_data->enc, 1);

	*codec_data = aptx_data;

	return true;
}

static bool aptx_cleanup(void *codec_data)
{
	struct aptx_data *aptx_data = (struct aptx_data *) codec_data;

	free(aptx_data->enc);
	free(codec_data);

	return true;
}

static bool aptx_get_config(void *codec_data, struct audio_input_config *config)
{
	struct aptx_data *aptx_data = (struct aptx_data *) codec_data;

	config->rate = aptx_data->aptx.frequency & APTX_SAMPLING_FREQ_48000 ?
								48000 : 44100;
	config->channels = AUDIO_CHANNEL_OUT_STEREO;
	config->format = AUDIO_FORMAT_PCM_16_BIT;

	return true;
}

static size_t aptx_get_buffer_size(void *codec_data)
{
	/* TODO: return actual value */
	return 0;
}

static size_t aptx_get_mediapacket_duration(void *codec_data)
{
	/* TODO: return actual value */
	return 0;
}

static ssize_t aptx_encode_mediapacket(void *codec_data, const uint8_t *buffer,
					size_t len, struct media_packet *mp,
					size_t mp_data_len, size_t *written)
{
	struct aptx_data *aptx_data = (struct aptx_data *) codec_data;
	const int16_t *ptr = (const void *) buffer;
	size_t bytes_in = 0;
	size_t bytes_out = 0;

	while ((len - bytes_in) >= 16 && (mp_data_len - bytes_out) >= 4) {
		int pcm_l[4], pcm_r[4];
		int i;

		for (i = 0; i < 4; i++) {
			pcm_l[i] = ptr[0];
			pcm_r[i] = ptr[1];
			ptr += 2;
		}

		aptx_encode(aptx_data->enc, pcm_l, pcm_r, &mp->data[bytes_out]);

		bytes_in += 16;
		bytes_out += 4;
	}

	*written = bytes_out;

	return bytes_in;
}

static bool aptx_update_qos(void *codec_data, uint8_t op)
{
	/*
	 * aptX has constant bitrate of 352kbps (with constant 4:1 compression
	 * ratio) thus QoS is not possible here.
	 */

	return false;
}

static const struct audio_codec codec = {
	.type = A2DP_CODEC_VENDOR,
	.use_rtp = false,

	.load = aptx_load,
	.unload = aptx_unload,

	.get_presets = aptx_get_presets,

	.init = aptx_codec_init,
	.cleanup = aptx_cleanup,
	.get_config = aptx_get_config,
	.get_buffer_size = aptx_get_buffer_size,
	.get_mediapacket_duration = aptx_get_mediapacket_duration,
	.encode_mediapacket = aptx_encode_mediapacket,
	.update_qos = aptx_update_qos,
};

const struct audio_codec *codec_aptx(void)
{
	return &codec;
}
