#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <3ds.h>

#include "error.h"
#include "m4a.h"
#include "playback.h"

/* TODO: Integrate proper AAC decoder library (libfaad2, fdk-aac, or minimp4) */
/* For now, this is a stub implementation */

static size_t*			buffSize;
static uint32_t			rate = 44100;
static uint8_t			channels = 2;

static int initM4a(const char* file);
static uint32_t rateM4a(void);
static uint8_t channelM4a(void);
static uint64_t decodeM4a(void* buffer);
static void exitM4a(void);
static size_t getFileSamplesM4a(void);

/**
 * Set decoder parameters for M4A/AAC.
 *
 * \param	decoder Structure to store parameters.
 */
void setM4a(struct decoder_fn* decoder)
{
	decoder->init = &initM4a;
	decoder->rate = &rateM4a;
	decoder->channels = &channelM4a;
	buffSize = &(decoder->buffSize);
	decoder->decode = &decodeM4a;
	decoder->exit = &exitM4a;
	decoder->getFileSamples = &getFileSamplesM4a;
}

/**
 * Check if a file is an M4A/AAC/ALAC file.
 *
 * \param	file	File location.
 * \return			0 on success, -1 on failure.
 */
int isM4a(const char* file)
{
	FILE* ftest = fopen(file, "rb");
	uint32_t fileSig;
	uint32_t ftypSig;
	
	if(ftest == NULL)
		return -1;
	
	/* Read first 4 bytes (should be size of ftyp atom) */
	if(fread(&fileSig, 4, 1, ftest) == 0)
	{
		fclose(ftest);
		return -1;
	}
	
	/* Read next 4 bytes (should be 'ftyp') */
	if(fread(&ftypSig, 4, 1, ftest) == 0)
	{
		fclose(ftest);
		return -1;
	}
	
	fclose(ftest);
	
	/* Check for 'ftyp' signature (0x70797466 in little-endian) */
	if(ftypSig == 0x70797466)
		return 0;
	
	return -1;
}

static int initM4a(const char* file)
{
	(void)file;
	
	/* TODO: Initialize AAC decoder */
	/* This requires:
	 * 1. Parse MP4 container to find AAC audio track
	 * 2. Extract decoder config (sample rate, channels, etc.)
	 * 3. Initialize AAC decoder with config
	 */
	
	/* Set default values for now */
	rate = 44100;
	channels = 2;
	*buffSize = rate * channels * sizeof(int16_t);
	
	errno = FILE_NOT_SUPPORTED;
	return -1;
}

static uint32_t rateM4a(void)
{
	return rate;
}

static uint8_t channelM4a(void)
{
	return channels;
}

static uint64_t decodeM4a(void* buffer)
{
	(void)buffer;
	
	/* TODO: Decode AAC frame */
	/* This requires:
	 * 1. Read next AAC frame from MP4 container
	 * 2. Decode AAC frame to PCM samples
	 * 3. Write PCM samples to buffer
	 * 4. Return number of samples decoded
	 */
	
	return 0;
}

static void exitM4a(void)
{
	/* TODO: Clean up AAC decoder */
}

static size_t getFileSamplesM4a(void)
{
	/* TODO: Calculate total samples from MP4 metadata */
	return 0;
}
