/*
============================================================================
 Name		: Configuration.cpp
 Author	  : yaoyang
 Version	 :
 Copyright   : 
 Description : CConfiguration implementation
============================================================================
*/

#include "Configuration.h"
//#include "Utils.h"

#include <eikenv.h>
#include <f32file.h>
#include <utf.h>


CConfiguration::CConfiguration()
{
	// No implementation required
	//iFsSessionPtr = NULL;
}


CConfiguration::~CConfiguration()
{
	if(!iHasSave){
		SaveL();
	}
	if ( iConfigItemArray ) {
		delete iConfigItemArray;
		iConfigItemArray=NULL;
	}
}

CConfiguration* CConfiguration::NewLC(const TDesC& aConfigFilePath)
{
	CConfiguration* self = new (ELeave)CConfiguration();
	CleanupStack::PushL(self);
	self->ConstructL(aConfigFilePath);
	return self;
}

CConfiguration* CConfiguration::NewL(const TDesC& aConfigFilePath)
{
	CConfiguration* self=CConfiguration::NewLC(aConfigFilePath);
	CleanupStack::Pop(); // self;
	return self;
}

void CConfiguration::ConstructL(const TDesC& aConfigFilePath)
{
	iFilePath = aConfigFilePath;
	iHasSave = true;
}

TBool CConfiguration::Get(const TDesC& aKey, TDes& aValue)
{
	TBool loadResult = LoadL();
	if(!loadResult)
		return false;

	for(TInt i = 0; i < iConfigItemArray->Count(); i ++){
		if(iConfigItemArray->At(i).iKey == aKey){
			aValue.Copy(iConfigItemArray->At(i).iValue);
			return true;
		}
	}
	return false;
}

TBool CConfiguration::Set(const TDesC& aKey, const TDesC& aValue)
{
	if(aKey.Length() > 32 || aValue.Length() > 128)
		return false;

	TBuf<128> value;
	TBool hasKey = Get(aKey, value);
	if(hasKey){
		for(TInt i = 0; i < iConfigItemArray->Count(); i ++){
			if(iConfigItemArray->At(i).iKey == aKey){
				iConfigItemArray->At(i).iValue.Copy(aValue);
			}
		}
	}
	else{
		TConfigItem configItem;
		configItem.iKey.Copy(aKey);
		configItem.iValue.Copy(aValue);
		iConfigItemArray->AppendL(configItem);
	}
	iHasSave = SaveL();
	return true;
}

void CConfiguration::ParseLine(TDesC& aLine, TDes& akey, TDes& aValue)
{
	TBuf<1> tag(_L("="));
	TInt pos = aLine.Find(tag);
	if(pos == KErrNotFound){
		akey = _L("");
		aValue = _L("");
	}
	else{
		akey = aLine.Mid(0, pos);
		aValue = aLine.Mid(pos + 1);
	}
}

TBool CConfiguration::SaveL()
{
	return SaveInternalL(CEikonEnv::Static()->FsSession());
}

TBool CConfiguration::SaveInternalL(RFs& aFs)
{
	RFs& fsSession = aFs;//CEikonEnv::Static()->FsSession();
	RFile file;
	int pos = iFilePath.LocateReverse( '\\' );
	TPtrC dirName = iFilePath.Left( pos+1 );
	aFs.MkDirAll(dirName);
	
	TInt errCode = file.Replace(fsSession, iFilePath, EFileWrite);
	if(errCode != KErrNone)
		return false;
	
	TBuf8<2> header;
	TChar c;
	c = 0xff;
	header.Append(c);
	c = 0xfe;
	header.Append(c);
	file.Write(header);

	for(TInt i = 0; i < iConfigItemArray->Count(); i ++){
		TBuf<512> line;
		line.Append(iConfigItemArray->At(i).iKey);
		line.Append(_L("="));
		
		line.Append(iConfigItemArray->At(i).iValue);
		line.Append(_L("\r\n"));
		TPtr8 ptr((TUint8*)line.Ptr(), line.Length()*2, line.Length()*2) ;
		file.Write(ptr);
	}
	file.Close();
	return true;
}

TBool CConfiguration::LoadL()
{
	TBool val = EFalse;
	RFs fs;
	if ( fs.Connect() )
		return val;
	val = LoadInternalL(fs);
	fs.Close();
	return val;
}

TBool CConfiguration::LoadInternalL(RFs& aFs)
{
	delete iConfigItemArray;
	iConfigItemArray = new(ELeave)CArrayFixFlat<TConfigItem>(3);
	
	RFs& fsSession = aFs;//CEikonEnv::Static()->FsSession();
	RFile file;
	TInt nErr = file.Open(fsSession, iFilePath, EFileRead|EFileShareAny);
	if (nErr)
	{
		return EFalse;
	}

	TFileText fileText;
	fileText.Set(file);
	HBufC* line = HBufC::NewLC(160);
	TPtr linePtr = line->Des();
	
	while (fileText.Read(linePtr) == KErrNone){
		TBuf<32> key;
		TBuf<128> value;
		TConfigItem item;
		ParseLine(linePtr, key, value);
		if(key.Length() != 0){
			item.iKey.Append(key);
			item.iValue.Append(value);
			iConfigItemArray->AppendL(item);
		}
	}
	CleanupStack::PopAndDestroy(); //line
	file.Close();

	return ETrue;
}
