#include "mof/sound/OggVorbisFile.hpp"
#include "mof/ConsoleIO.hpp"
#include <math.h>


static int _fseek64_wrap(FILE* f, __int64 off, int whence) 
{
	if (f == NULL) return -1;
	return fseek(f, off, whence);
}


mof::OggVorbisFile::OggVorbisFile(void)
{
	m_fp = NULL;
	m_pFormat = NULL;
	m_vorbisInfo = NULL;
}





mof::OggVorbisFile::~OggVorbisFile(void)
{
	close();
}



bool mof::OggVorbisFile::open(const mof::tstring& filename){
	
	m_fp = fopen(filename.c_str() , "rb");
	if(m_fp == NULL){
		*ConsoleOut::getInstance() << _T("Can't Open File --- ") << filename << std::endl;
		return false;
	}

	ov_callbacks callbacks = 
	{
		(size_t (*)(void *, size_t, size_t, void *)) fread,
		(int (*)(void *, __int64, int)) _fseek64_wrap,
		(int (*)(void *)) fclose,
		(long (*)(void *)) ftell
	};
	//int result = ov_open(m_fp, &m_vorbisFile , NULL, 0);
	int result = ov_open_callbacks(m_fp, &m_vorbisFile, NULL, 0, callbacks);
	if (result < 0) { 
		*ConsoleOut::getInstance() << _T("This is not OggVorbis file --- ") << filename << std::endl;
		ov_clear(&m_vorbisFile);
		fclose(m_fp);
		m_fp = NULL;
		return false;
	}

	m_vorbisInfo = ov_info(&m_vorbisFile , -1);

	m_pFormat = new WAVEFORMATEX;
	m_pFormat->cbSize = 0;
	m_pFormat->wFormatTag = WAVE_FORMAT_PCM;
	m_pFormat->nChannels = m_vorbisInfo->channels;
	m_pFormat->nSamplesPerSec = m_vorbisInfo->rate;
	m_pFormat->wBitsPerSample = 16;
	m_pFormat->nBlockAlign = m_pFormat->nChannels * 2;
	m_pFormat->nAvgBytesPerSec = m_pFormat->nSamplesPerSec * m_pFormat->nBlockAlign; 
    return true;

}


bool mof::OggVorbisFile::close(){
	delete m_pFormat;
	ov_clear(&m_vorbisFile);
	fclose(m_fp);
	m_fp = NULL;
	return true;
}



long mof::OggVorbisFile::read( BYTE* pBuffer1, long bufferSize1 , BYTE* pBuffer2 , long bufferSize2 ){
    int bitstream;
	long offset;
	long readSize;
	for(offset = 0 ; offset < bufferSize1 ; offset += readSize){
		readSize = ov_read(&m_vorbisFile , (char*)pBuffer1 + offset , bufferSize1 - offset ,  0 , 2 , 1, &bitstream);
		if (readSize <= 0)resetFile();	
	}

	if(bufferSize2 == 0)return 0;

	for(offset = 0 ; offset < bufferSize2 ; offset += readSize){
		readSize = ov_read(&m_vorbisFile , (char*)pBuffer2 + offset , bufferSize2 - offset ,  0 , 2 , 1, &bitstream);
		if (readSize <= 0)resetFile();
	}
	
	return 1;
}


long mof::OggVorbisFile::getSize(){
	return (long)ceil(m_vorbisInfo->channels * m_vorbisInfo->rate * ov_time_total(&m_vorbisFile , -1) * 2);
}



bool mof::OggVorbisFile::resetFile(){
	ov_pcm_seek(&m_vorbisFile , 0);
    return true;
}


WAVEFORMATEX* mof::OggVorbisFile::getFormat(){
	return m_pFormat;
}



