/**
 *  @file ins_ut_audio.c
 *  @details config unit test
 *
 */

#include <stdlib.h>
#include <string.h>
//#include "unittest.h"
#include "unittest/device/audio/ins_ut_audio.h"
#include "ins_mw_config.h"
#include "ins_pal_error_code.h"
#include "ins_comm_log.h"

#include "ins_dev_audio.h"
#include "AmbaAudio_CODEC.h"
#include "SvcPlat.h"
#include "AmbaAEncFlow.h"
#include "AmbaMisraFix.h"
#include "AmbaADecFlow.h"
#include "AmbaUtility.h"

#include "SvcAudioTask.h"

#include "ins_dev_pcm2wav.h"
#include "ins_pal_system.h"

static  uint32_t g_EncNum = 0U;
static AMBA_FS_FILE  *p_file = NULL;
static uint64_t DecId;

static int32_t InsUT_Device_AudioInit(int32_t argc, char **argv)
{
    InsDev_Audio_t * p_audio_dev = InsDev_Audio_Init(0);
    int32_t part = 0;

	argc = argc;
	argv = argv;
    //if(argc > 0)
	//{
	//	INSLOG_E("argc = %d\n", argc);
	//    for(int i = 0; i < argc; i++)
	//    {
	//        INSLOG_E("argv[%d] = %s\n", i, argv[i]);
	//    }
	//}
//    if(argc < 1)
//    {
//        INSLOG_W("Input para not enough!");
//        return INSERR_NG;
//    }
//    part = atoi(argv[0]);
    part = part;
    p_audio_dev = p_audio_dev;
	SvcAudioTask_Config();
	
    return (int32_t)0;
}

static int32_t InsUT_Device_AudioSetSpkVol(int32_t argc, char **argv)
{
    InsDev_Audio_t * p_audio_dev = InsDev_Audio_Init(0);
    int32_t volume = 0;

#if 0
    if(argc > 0)
	{
		INSLOG_E("argc = %d\n", argc);
	    for(int i = 0; i < argc; i++)
	    {
	        INSLOG_E("argv[%d] = %s\n", i, argv[i]);
	    }
	}
#endif
    if(argc < 1)
    {
        INSLOG_W("Input para not enough!");
        return INSERR_NG;
    }
    volume = atoi(argv[0]);
    
    return (int32_t)p_audio_dev->set_spk_volume(volume);
}

static void InsUT_Device_AinCtrl(uint32_t Chan, uint32_t Op)
{
    if ((g_pPlatCbEntry != NULL) && (g_pPlatCbEntry->pCbAinCtrl != NULL))
    {
        g_pPlatCbEntry->pCbAinCtrl(Chan, Op);
    }
    else
    {
        INSLOG_W("qqqqq, g_pPlatCbEntry = 0x%x, pCbAinCtrl = 0x%x!", g_pPlatCbEntry, g_pPlatCbEntry->pCbAinCtrl);
    }
}

static int32_t InsUT_Device_AudioRecordStart(int32_t argc, char **argv)
{
	argc = argc;
	argv = argv;
    //if(argc > 0)
	//{
	//	INSLOG_E("argc = %d\n", argc);
	//    for(int i = 0; i < argc; i++)
	//    {
	//        INSLOG_E("argv[%d] = %s\n", i, argv[i]);
	//    }
	//}
    AmbaAEncFlow_EncAudioOnly(1U);
    AmbaAEncFlow_Start(InsUT_Device_AinCtrl, 1U, 1U);
    g_EncNum = 1U;
    
    INSLOG_W("record start!");

    return (int32_t)0;
}

static int32_t InsUT_Device_AudioRecPcm2Wav(int32_t argc, char **argv)
{
    int32_t ret_val = INSERR_OK;
	InsUtil_Audio_PcmInfo_t pcm_info;
	const char   file_name[32] = "c:\\SVC_Aduio_0.pcm";	//"c:\\sample.pcm";	//SVC_Aduio_0.pcm
	const char   wav_file_name[32] = "c:\\SVC_Aduio_0.wav";

    INSPAL_UNUSED(&argc);
    INSPAL_UNUSED(&argv);
	
	pcm_info.num_channels = 4;
	pcm_info.sample_rate = 48000;
	pcm_info.bits_per_sample = 32;
	if(ENUM_ENCODE_PCM == get_encode_mode())
	{
		ret_val = InsUtil_Audio_Pcm2Wav(wav_file_name, file_name, &pcm_info);
		if(INSERR_OK != ret_val)
	    {
	        INSLOG_W(INSLOG_TAG, "wav to pcm fail:%d", ret_val, 0U);
	    }
		else
		{
			INSLOG_W(INSLOG_TAG, "wav to pcm ok:%d", ret_val, 0U);
		}
	}
	
    return ret_val;
}

static int32_t InsUT_Device_AudioRecordStop(int32_t argc, char **argv)
{
	argc = argc;
	argv = argv;
    //if(argc > 0)
	//{
	//	INSLOG_E("argc = %d\n", argc);
	//    for(int i = 0; i < argc; i++)
	//    {
	//        INSLOG_E("argv[%d] = %s\n", i, argv[i]);
	//    }
	//}
    AmbaAEncFlow_Stop(InsUT_Device_AinCtrl, 1U, g_EncNum);
    AmbaAEncFlow_EncAudioOnly(0U);
    INSLOG_W("record stop!");

	InsUT_Device_AudioRecPcm2Wav(argc, argv);
	
    return (int32_t)0;
}

static void InsUT_Device_AoutCtrl(UINT32 Chan, UINT32 Op)
{
    if ((g_pPlatCbEntry != NULL) && (g_pPlatCbEntry->pCbAoutCtrl != NULL))
	{
        g_pPlatCbEntry->pCbAoutCtrl(Chan, Op);
    }
}

static int32_t InsUT_Device_AudioPlay(int32_t argc, char **argv)
{
	int32_t rval = INSERR_OK;
	char FileName[50] = "c:\\SVC_Aduio_0.pcm";	//"c:\\sample.pcm";
    uint32_t FileInfo;
	const char *FileName_Base = "c:\\";
    const char *PCM_extension = ".pcm";
	
	argc = argc;
	argv = argv;
	if(argc > 0)
	{
		INSLOG_E("argc = %d\n", argc);
	    for(int i = 0; i < argc; i++)
	    {
	        INSLOG_E("argv[%d] = %s\n", i, argv[i]);
	    }
	}
//	if(argc < 1)
//    {
//        INSLOG_W("Input para not enough!");
//        return INSERR_NG;
//    }
	if(argc > 0)
	{
		memset(FileName, 0, sizeof(FileName));
		//strcat(FileName, argv[0]);
		sprintf(FileName, "%s%s%s", FileName_Base, argv[0], PCM_extension);
		INSLOG_E("FileName = %s\n", FileName);
		rval = AmbaFS_FileOpen(FileName, "rb", &p_file);
	}
	else
	{
		rval = AmbaFS_FileOpen(FileName, "rb", &p_file);
	}
    if(rval != INSERR_OK)
    {
        INSLOG_E("[Device] audio open file fail!");
        return rval;
    }
	
    AmbaMisra_TypeCast(&FileInfo, &(p_file));
    AmbaADecFlow_Setup(AMBA_AUDIO_TYPE_PCM, AMBA_AUDIO_SOURCE_AUDIO, FileInfo, NULL, &DecId);
    AmbaADecFlow_FeedTaskCreate(DecId);
    AmbaADecFlow_DecStart(DecId);
    AmbaADecFlow_OupStart(DecId, InsUT_Device_AoutCtrl);
			
    INSLOG_W("play audio!");

    return (int32_t)0;
}

static int32_t InsUT_Device_AudioPlayAac(int32_t argc, char **argv)
{
	int32_t rval = INSERR_OK;
	char   FileName[50] = "c:\\SVC_Aduio_0.aac";
    uint32_t FileInfo;
	
	const char *FileName_Base = "c:\\";
    const char *AAC_extension = ".aac";
	
	argc = argc;
	argv = argv;
    //if(argc > 0)
	//{
	//	INSLOG_E("argc = %d\n", argc);
	//    for(int i = 0; i < argc; i++)
	//    {
	//        INSLOG_E("argv[%d] = %s\n", i, argv[i]);
	//    }
	//}

	if(argc > 0)
	{
		memset(FileName, 0, sizeof(FileName));
		//strcat(FileName, argv[0]);
		sprintf(FileName, "%s%s%s", FileName_Base, argv[0], AAC_extension);
		INSLOG_E("FileName = %s\n", FileName);
		rval = AmbaFS_FileOpen(FileName, "rb", &p_file);
	}
	else
	{
		rval = AmbaFS_FileOpen(FileName, "rb", &p_file);
	}
    if(rval != INSERR_OK)
    {
        INSLOG_E("[Device] audio open file fail!");
        return rval;
    }
	
    AmbaMisra_TypeCast(&FileInfo, &(p_file));
    AmbaADecFlow_Setup(AMBA_AUDIO_TYPE_AAC, AMBA_AUDIO_SOURCE_AUDIO, FileInfo, NULL, &DecId);
    AmbaADecFlow_FeedTaskCreate(DecId);
    AmbaADecFlow_DecStart(DecId);
    AmbaADecFlow_OupStart(DecId, InsUT_Device_AoutCtrl);
			
    INSLOG_W("play audio!");

    return (int32_t)0;
}

static int32_t InsUT_Device_AudioPlayStop(int32_t argc, char **argv)
{
	int32_t rval = INSERR_OK;
	
	argc = argc;
	argv = argv;
//	if(argc > 0)
//	{
//		INSLOG_E("argc = %d\n", argc);
//	    for(int i = 0; i < argc; i++)
//	    {
//	        INSLOG_E("argv[%d] = %s\n", i, argv[i]);
//	    }
//	}
//	if(argc < 1)
//    {
//        INSLOG_W("Input para not enough!");
//        return INSERR_NG;
//    }

	AmbaADecFlow_Stop(DecId, 0U, InsUT_Device_AoutCtrl);
    (void)AmbaFS_FileClose(p_file);
    AmbaADecFlow_Delete(DecId);
    AmbaADecFlow_FeedTaskDelete(DecId);
	
    return (int32_t)rval;
}

static int32_t InsUT_Device_AudioPcm2Wav(int32_t argc, char **argv)
{
	int32_t rval = INSERR_OK;
	const char   file_name[32] = "c:\\SVC_Aduio_0.pcm";	//"c:\\sample.pcm";	//SVC_Aduio_0.pcm
	const char   wav_file_name[32] = "c:\\SVC_Aduio_0.wav";
	InsUtil_Audio_PcmInfo_t pcm_info;

	argc = argc;
	argv = argv;
    //if(argc > 0)
	//{
	//	INSLOG_E("argc = %d\n", argc);
	//    for(int i = 0; i < argc; i++)
	//    {
	//        INSLOG_E("argv[%d] = %s\n", i, argv[i]);
	//    }
	//}
//	pcm_info.num_channels = 4;
//	pcm_info.sample_rate = 48000;
//	pcm_info.bits_per_sample = 32;
//	(void)InsUtil_Audio_Pcm2WavOpen(file_name, &pcm_info);
	pcm_info.num_channels = 4;
	pcm_info.sample_rate = 48000;
	pcm_info.bits_per_sample = 32;
	InsUtil_Audio_Pcm2Wav(wav_file_name, file_name, &pcm_info);
    INSLOG_W("pcm to wav!");

    return (int32_t)rval;
}

static int32_t InsUT_Device_AudioSetEncodeMode(int32_t argc, char **argv)
{
	int32_t rval = INSERR_OK;

	argc = argc;
	argv = argv;
	if(argc > 0)
	{
		INSLOG_E("argc = %d\n", argc);
	    for(int i = 0; i < argc; i++)
	    {
	        INSLOG_E("argv[%d] = %s\n", i, argv[i]);
	    }
	}
    if(argc < 1)
    {
        INSLOG_W("Input para not enough!");
		INSLOG_W("set_mode aac --> set mode to aac!");
		INSLOG_W("set_mode pcm --> set mode to pcm!");
		
        return INSERR_NG;
    }
	if (AmbaUtility_StringCompare(argv[0], "aac", 3U) == 0)
    {
        set_encode_mode(ENUM_ENCODE_AAC);
		INSLOG_W("change to aac!");
    }
	else if (AmbaUtility_StringCompare(argv[0], "pcm", 3U) == 0)
    {
        set_encode_mode(ENUM_ENCODE_PCM);
		INSLOG_W("change to pcm!");
    }
	else
	{
		INSLOG_W("set_mode aac --> set mode to aac!");
		INSLOG_W("set_mode pcm --> set mode to pcm!");
	}
	
    return (int32_t)rval;
}

InsUT_Unittest_CmdInfo_t g_ut_cmd_DevAudio[INSUT_CMDCNT_AUDIO] = 
{
    {InsUT_Device_AudioInit,            0, NULL, "init",        "init audio"},
	{InsUT_Device_AudioSetSpkVol,      	0, NULL, "spk_vol",     "set Speak Volume"},
    {InsUT_Device_AudioRecordStart,     0, NULL, "start",       "record start"},
    {InsUT_Device_AudioRecordStop,      0, NULL, "stop",        "record stop"},
	{InsUT_Device_AudioPlay,      		0, NULL, "play",        "play pcm audio"},
	{InsUT_Device_AudioPlayAac,      	0, NULL, "playaac",     "play aac audio"},
	{InsUT_Device_AudioPlayStop,      	0, NULL, "play_stop",        "stop play audio"},
	{InsUT_Device_AudioPcm2Wav,      	0, NULL, "pcm2wav",     "pcm to wav"},
	{InsUT_Device_AudioSetEncodeMode,	0, NULL, "set_mode",    "play aac audio"},
};

