//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
//=============================================================================//

#include "cbase.h"
#include "wavefile.h"
#include "sentence.h"
#include "iscenemanagersound.h"
#include "SoundEmitterSystem/isoundemittersystembase.h"
#include "snd_wave_source.h"
#include "cmdlib.h"
#include "workspacemanager.h"
#include "vcdfile.h"
#include "workspacebrowser.h"
#include "multiplerequest.h"
#include "UtlBuffer.h"
#include "scenemanager_tools.h"

//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *name - 
//-----------------------------------------------------------------------------
CWaveFile::CWaveFile( CVCDFile *vcd, CSoundEntry *se, char const *filename ) 
	: m_pOwner( vcd ), m_pOwnerSE( se )
{
	m_bSentenceLoaded = false;

	m_Sentence.Reset();

	Q_strncpy( m_szName, filename, sizeof( m_szName ) );

	m_pWaveFile = NULL;

	Q_snprintf( m_szFileName, sizeof( m_szFileName ), "sound/%s", filename );
}

CWaveFile::~CWaveFile()
{
}

//-----------------------------------------------------------------------------
// Purpose: 
// Output : int
//-----------------------------------------------------------------------------
int CWaveFile::GetLanguageId()
{
	return GetWorkspaceManager()->GetLanguageId();
}

void CWaveFile::EnsureSentence()
{
	if ( m_bSentenceLoaded )
		return;

	m_bSentenceLoaded = true;

	if ( m_szFileName[ 0 ] )
	{
		SceneManager_LoadSentenceFromWavFile( m_szFileName, m_Sentence );
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CWaveFile::HasLoadedSentenceInfo() const
{
	return m_bSentenceLoaded;
}


CVCDFile *CWaveFile::GetOwnerVCDFile()
{
	return m_pOwner;
}

CSoundEntry *CWaveFile::GetOwnerSoundEntry()
{
	return m_pOwnerSE;
}

//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *name - 
//-----------------------------------------------------------------------------
void CWaveFile::SetName( char const *filename )
{
	if ( !Q_stricmp( m_szName, filename ) )
		return;

	Q_strncpy( m_szName, filename, sizeof( m_szName ) );

	Q_snprintf( m_szFileName, sizeof( m_szFileName ), "sound/%s", filename );

	if ( m_szFileName[ 0 ] )
	{
		SceneManager_LoadSentenceFromWavFile( m_szFileName, m_Sentence );
		m_bSentenceLoaded = true;
	}
}

char const	*CWaveFile::GetName() const
{
	return m_szName;
}

char const *CWaveFile::GetFileName() const
{
	return m_szFileName;
}

char const	*CWaveFile::GetSentenceText()
{
	EnsureSentence();
	return m_Sentence.GetText();
}

void CWaveFile::SetSentenceText( char const *newText )
{
	EnsureSentence();
	if ( !Q_stricmp( GetSentenceText(), newText ) )
		return;

	if ( !IsCheckedOut() )
	{
		int retval = MultipleRequest( va( "Check out '%s'?", GetFileName() ) );
		if ( retval != 0 )
			return;

		VSS_Checkout( GetFileName() );
	}

	m_Sentence.SetText( newText );

	SceneManager_SaveSentenceToWavFile( GetFileName(), m_Sentence );
}

void CWaveFile::ValidateTree( mxTreeView *tree, mxTreeViewItem* parent )
{
}

void CWaveFile::Play()
{
	if ( !m_pWaveFile )
	{
		m_pWaveFile = sound->FindOrAddSound( m_szFileName );
	}

	if ( !m_pWaveFile )
	{
		Con_Printf( "Can't play '%s', no wave file loaded\n", GetFileName() );
		return;
	}

	Con_Printf( "Playing '%s' : '%s'\n", GetFileName(), GetSentenceText() );

	CAudioMixer *temp;
	sound->PlaySound( m_pWaveFile, &temp );
}

bool CWaveFile::GetVoiceDuck()
{
	EnsureSentence();
	return m_Sentence.GetVoiceDuck();
}

void CWaveFile::SetVoiceDuck( bool duck )
{
	EnsureSentence();
	if ( GetVoiceDuck() == duck )
		return;

	m_Sentence.SetVoiceDuck( duck );

	if ( !IsCheckedOut() )
	{
		int retval = MultipleRequest( va( "Check out '%s'?", GetFileName() ) );
		if ( retval != 0 )
			return;

		VSS_Checkout( GetFileName() );
	}

	SceneManager_SaveSentenceToWavFile( GetFileName(), m_Sentence );
}

void CWaveFile::ToggleVoiceDucking()
{
	EnsureSentence();
	m_Sentence.SetVoiceDuck( !m_Sentence.GetVoiceDuck() );

	if ( !IsCheckedOut() )
	{
		int retval = MultipleRequest( va( "Check out '%s'?", GetFileName() ) );
		if ( retval != 0 )
			return;

		VSS_Checkout( GetFileName() );
	}

	SceneManager_SaveSentenceToWavFile( GetFileName(), m_Sentence );
}

bool CWaveFile::IsCheckedOut() const
{
	return filesystem->IsFileWritable( GetFileName() );
}

int CWaveFile::GetIconIndex() const
{
	if ( IsCheckedOut() )
	{
		return IMAGE_WAV_CHECKEDOUT;
	}
	else
	{
		return IMAGE_WAV;
	}
}


void CWaveFile::Checkout(bool updatestateicons /*= true*/)
{
	VSS_Checkout( GetFileName(), updatestateicons );
}

void CWaveFile::Checkin(bool updatestateicons /*= true*/)
{
	VSS_Checkin( GetFileName(), updatestateicons );
}


void CWaveFile::MoveChildUp( ITreeItem *child )
{
}

void CWaveFile::MoveChildDown( ITreeItem *child )
{
}

void CWaveFile::SetDirty( bool dirty )
{
	if ( GetOwnerVCDFile() )
	{
		GetOwnerVCDFile()->SetDirty( dirty );
	}
}

bool CWaveFile::IsChildFirst( ITreeItem *child )
{
	return false;
}

bool CWaveFile::IsChildLast( ITreeItem *child )
{
	return false;
}

//-----------------------------------------------------------------------------
// Purpose: 
// Input  : sentence - 
//-----------------------------------------------------------------------------
void CWaveFile::SetThreadLoadedSentence( CSentence& sentence )
{
	if ( m_bSentenceLoaded )
		return;

	m_bSentenceLoaded = true;
	m_Sentence = sentence;
}

#define WORD_DATA_EXTENSION	".txt"

//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *tempfile - 
//-----------------------------------------------------------------------------
void CWaveFile::ExportValveDataChunk( char const *tempfile )
{
	EnsureSentence();

	if ( m_Sentence.m_Words.Count() <= 0 )
	{
		Con_ColorPrintf( ERROR_R, ERROR_G, ERROR_B, "CWaveFile::ExportValveDataChunk:  Sentence has no word data\n" );
		return;
	}

	SafeCreatePath( va( "%s%s", SceneManager_GetGameDirectory(), (char *)tempfile ) );

	FileHandle_t fh = filesystem->Open( tempfile, "wb" );
	if ( !fh )
	{
		Con_ColorPrintf( ERROR_R, ERROR_G, ERROR_B, "CWaveFile::ExportValveDataChunk:  Unable to write to %s (read-only?)\n", tempfile );
		return;
	}
	else
	{
		// Buffer and dump data
		CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );

		m_Sentence.SaveToBuffer( buf );

		filesystem->Write( buf.Base(), buf.TellPut(), fh );
		filesystem->Close(fh);

		Con_Printf( "Exported %i words to %s\n", m_Sentence.m_Words.Count(), tempfile );
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *tempfile - 
//-----------------------------------------------------------------------------
void CWaveFile::ImportValveDataChunk( char const *tempfile )
{
	EnsureSentence();

	FileHandle_t fh = filesystem->Open( tempfile, "rb" );
	if ( !fh )
	{
		Con_ColorPrintf( ERROR_R, ERROR_G, ERROR_B, "CWaveFile::ImportValveDataChunk:  Unable to read from %s\n", tempfile );
		return;
	}

	int len = filesystem->Size( fh );
	if ( len <= 4 )
	{
		Con_ColorPrintf( ERROR_R, ERROR_G, ERROR_B, "CWaveFile::ImportValveDataChunk:  File %s has length 0\n", tempfile );
		return;
	}

	CSentence newSentence;

	unsigned char *buf = new unsigned char[ len + 1 ];

	filesystem->Read( buf, len, fh );
	filesystem->Close( fh );

	newSentence.InitFromDataChunk( (void *)( buf ), len );

	delete[] buf;

	// See if we can write it out...
	if ( !IsCheckedOut() )
	{
		int retval = MultipleRequest( va( "Check out '%s'?", GetFileName() ) );
		if ( retval != 0 )
			return;

		VSS_Checkout( GetFileName() );
	}

	if ( !IsCheckedOut() )
	{
		MakeFileWriteable( GetFileName() );
		Con_Printf( "Unable to check out %s, forcing it to be writable instead!\n", GetFileName() );
	}

	Con_Printf( "Imported %i words from %s\n", newSentence.m_Words.Count(), tempfile );

	m_Sentence = newSentence;

	SceneManager_SaveSentenceToWavFile( GetFileName(), m_Sentence );
}

void CWaveFile::GetPhonemeExportFile( char *path, int maxlen )
{
	char relative[ 512 ];
	strcpy( relative, GetFileName() );
	Q_StripExtension( relative, relative, sizeof( relative ) );
	Q_DefaultExtension( relative, WORD_DATA_EXTENSION, sizeof( relative ) );

	Q_snprintf( path, maxlen, "phonemes/%s", relative );
	Q_FixSlashes( path );
}