/*
** Copyright (C) 2001 Albert L. Faber
**  
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** 
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
** 
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software 
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/


#include "StdAfx.h"
#include "CDPLayerIni.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#include <stdlib.h>


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CDPlayerIni::CDPlayerIni(  )
{

	// Avoid needless copy constructors for speed reasons
	m_vSection.reserve( 50 );
}


CDPlayerIni::~CDPlayerIni()
{
	Clear();
}


bool CDPlayerIni::IsSectionString( const CString&  strTest )
{
	CString strItem( strTest );

	if ( strItem.GetLength() < 2 )
		return false;

	// quick check, to speed it up a bit
	if ( _T( '[' ) != strItem[ 0 ] )
	{
		return false;
	}
	else
	{
		strItem.TrimRight();

		if (	strItem.GetLength() > 2 && strItem.Left(1) == _T( '[' ) && 
				strItem.Right(1) == _T( ']' ) ) 
		{
			return true;
		}
	}
	return false;
}


bool CDPlayerIni::Read( const CString& strFileName )
{
	FILE*	pFile = NULL;
	DWORD	dwBytes = 0;
	TCHAR	buf[ 1024 ];
	int		nSection = -1;
	int		nEntry = 0;

	Clear();

	CMutex	processLock( TRUE, _T( "CDEX_CPI" ) );

	pFile = _tfopen( strFileName, _T( "r" ) );

	if ( NULL != pFile  )
	{

		while ( NULL !=  _fgetts( buf, sizeof( buf ) -1 , pFile ) )
		{
			// kill new line character
			if ( buf[ _tcslen( buf ) -1 ] == _T( '\n' ) )
			{
				buf[ _tcslen( buf ) -1 ] = _T( '\0' );
			}

			CString strBuf( buf );

			if ( IsSectionString( strBuf ) ) 
			{
				ASTRING vNewEntry;
				vNewEntry.reserve( 16 );

				nSection++;
				m_vSection.push_back( strBuf );
				m_vvEntries.push_back( vNewEntry );
			}
			else
			{
				if ( nSection >= 0 && strBuf.GetLength() > 0 )
				{
					m_vvEntries[ nSection ].push_back( strBuf );
				}
			}
		}

		fclose( pFile );
	}

	processLock.Unlock();

	return true;
}

bool CDPlayerIni::Write( const CString& strFileName )
{
	FILE*	pFile = NULL;
	int		nItem = 0;
	int		nStringItems = m_vSection.size();
	int		nSection = 0;

	CMutex	processLock( TRUE, _T( "CDEX_CPI" ) );

	pFile = _tfopen( strFileName, _T( "w" ) );

	if ( NULL != pFile  )
	{
		for ( nSection = 0; nSection < m_vSection.size(); nSection++)
		{

			if ( nSection > 0 )
			{
				fputs( "\n" , pFile );
			}

			CString strLine( m_vSection[ nSection ] + "\n" );
			_fputts( strLine, pFile );

			for ( nItem = 0; nItem < m_vvEntries[ nSection ].size(); nItem++)
			{
				CString strLine( m_vvEntries[ nSection ][ nItem ] + "\n" );
				_fputts( strLine, pFile );
			}
		}

		fclose( pFile );
	}

	processLock.Unlock();

	return true;
}

// **********************************************************************************

void CDPlayerIni::Clear()
{
	m_vSection.clear();
	m_vvEntries.clear();
}

// **********************************************************************************



int CDPlayerIni::FindSection( const CString& strSection )
{
	CString strSectionTag;
	int		nIdx = 0;

	strSectionTag.Format( _T( "[%s]" ) , strSection );

	strSectionTag.TrimLeft();
	strSectionTag.TrimRight();

	for ( nIdx = 0 ; nIdx < m_vSection.size(); nIdx++ )
	{
		CString strLine( m_vSection[ nIdx ] );

		strLine.TrimLeft();
		strLine.TrimRight();
		

		if ( 0 == strSectionTag.CompareNoCase( strLine ) )
		{
			return nIdx;
		}
	}

	return -1;
}

int CDPlayerIni::InsertSection( const CString& strSection )
{
	ASSERT( -1 == FindSection( strSection ) );

	CString strSectionTag;

	strSectionTag.Format( _T( "[%s]" ), strSection );

	ASTRING vNewEntry;

	m_vSection.push_back( strSectionTag );
	m_vvEntries.push_back( vNewEntry );

	return m_vvEntries.size() - 1;
}


int CDPlayerIni::FindItem( int nSec, const CString& strItem, CString &strVal)
{
	ASSERT( nSec >=0 );
	ASSERT( nSec < m_vvEntries.size() );
	ASSERT( strItem );

	int nItem = 0;

	CString strItemTag(strItem);
	CString strLook;

	strItemTag+= _T( "=" );

	int iLen = strItemTag.GetLength();

	for ( nItem = 0; nItem < m_vvEntries[ nSec ].size(); nItem++ )
	{
		// get the current item
		strLook = m_vvEntries[ nSec ][ nItem ];

		// compare item
		if ( 0 == strItemTag.CompareNoCase( strLook.Left( iLen ) ) ) 
		{
			// return proper value
			if ( strLook.GetLength() == iLen )
			{
				strVal = _T( "" );
				return nItem;
			}
			else
			{
				strVal = strLook.Right( strLook.GetLength() - iLen );
				return nItem;
			}
		}
	}

	return -1;
}




bool CDPlayerIni::RemoveSection(const CString& strSection)
{
/*
	ASTRING_IT itStart = FindSection( strSection );
	ASTRING_IT itEnd = itStart;

	if ( NULL != itStart )
	{
		while ( itEnd < m_vSection.end() &&
				false == IsSection( itEnd) )
		{
			itEnd++;
		}
		m_vSection.erase( itStart, itEnd );
	}
*/
	return true;
}


// **********************************************************************************

bool CDPlayerIni::SetValue(const CString& strSection, const CString& strItem, const CString& cVal)
{
	m_ThreadLock.Lock();

	int nSection = -1;
	int nItem = -1;

	CString strVal;
	CString strValue;
	strVal.Format( _T( "%s=%s" ), strItem, cVal );

	if ( -1 == ( nSection = FindSection( strSection ) ) )
	{
		nSection = InsertSection( strSection );
	}

	if ( -1 == ( nItem = FindItem( nSection, strItem, strValue) ) )
	{
		m_vvEntries[ nSection ].push_back( strVal );
	} else
	{
		m_vvEntries[ nSection ][ nItem ] = strVal;
	}

	m_ThreadLock.Unlock();
	return true;
}

bool CDPlayerIni::SetValue(const CString& strSection, const CString& strItem, const int iVal)
{
	CString strEntry;
	strEntry.Format( _T( "%d" ), iVal );
	return SetValue( strSection, strItem, strEntry );
}

bool CDPlayerIni::SetValue(const CString& strSection, const CString& strItem, const long lVal)
{
	return SetValue( strSection, strItem, (int) lVal );
}

bool CDPlayerIni::SetValue(const CString& strSection, const CString& strItem, const DWORD dwVal)
{
	return SetValue( strSection, strItem, (int)dwVal );
}



// **********************************************************************************


CString CDPlayerIni::GetValue( const CString& strSection, const CString& strItem, CString strDefault )
{
	m_ThreadLock.Lock();

	CString		strVal = strDefault;
	int			nSection = -1;
	int			nItem = -1;

	if ( -1 != ( nSection = FindSection( strSection ) ) )
	{
		if ( -1 != ( nItem = FindItem( nSection, strItem, strVal) ) )
		{
			m_ThreadLock.Unlock();
			return CString( strVal );
		}
	}


	m_ThreadLock.Unlock();

	return strDefault;
}

INT CDPlayerIni::GetValue( const CString& strSection, const CString& strItem, const INT nDefault )
{
	m_ThreadLock.Lock();

	int		nSection = -1;
	int		nItem = -1;
	CString strVal;

	if ( -1 != ( nSection = FindSection( strSection ) ) )
	{
		if ( -1 != ( nItem = FindItem( nSection, strItem, strVal) ) )
		{
			m_ThreadLock.Unlock();
			return _ttoi( strVal );
		}
	}

	m_ThreadLock.Unlock();

	return nDefault;
}


LONG CDPlayerIni::GetValue( const CString& strSection, const CString& strItem, const LONG nDefault )
{
	return (LONG) GetValue ( strSection, strItem, (INT) nDefault );
}

DWORD CDPlayerIni::GetValue( const CString& strSection, const CString& strItem, const DWORD nDefault )
{
	return (DWORD) GetValue ( strSection, strItem, (INT) nDefault );
}



