#include <common/stdlib.hpp>
#include <common/profile.hpp>
#include <common/pathfnd.hpp>

Profile::Profile(void)
: mIniPathFileName("UNSET"), mStringUnset("UNSET"), mIsOkay(FALSE)
{
}

Profile::Profile(String iniFileName,String unsetString)
: mIniPathFileName(iniFileName), mStringUnset(unsetString), mIsOkay(FALSE)
{
	mIsOkay=verifyInitializationFile(iniFileName);
}

Profile::~Profile()
{
}

WORD Profile::readProfileString(const String &sectionString,const String &itemString,String &returnString)const
{
	if(!isOkay())return FALSE;

  returnString.reserve(MaxProfileLength+1);
	::GetPrivateProfileString((LPSTR)sectionString,(LPSTR)itemString,(LPSTR)mStringUnset,(LPSTR)returnString,MaxProfileLength,mIniPathFileName);
  if(returnString==mStringUnset)return FALSE;
	expandEmbeddedMacro(returnString);
	return TRUE;
}

WORD Profile::readProfileBlock(const String &sectionString,Block<String> &sectionBlock,Statement statementType)
{
	String tempString;
	String itemString;
	Block<String> tempBlock;
	char *ptr;

	sectionBlock.remove();
	if(!readProfileString(sectionString,String((char*)0),tempString))return FALSE;
	ptr=(LPSTR)tempString;
	while(TRUE)
	{
		if(!ptr||!*ptr)break;
		tempBlock.insert(&String(ptr));
		ptr+=(::strlen(ptr)+1);
	}
	for(int index=0;index<(int)tempBlock.size();index++)
	{
		readProfileString(sectionString,tempBlock[index],itemString);
		if(Pure==statementType)
		{
			tempString=tempBlock[index];
			tempString+="=";
      tempString+=itemString;
		}
    else tempString=itemString;
		expandEmbeddedMacro(tempString);
		sectionBlock.insert(&tempString);
	}
	return (int)sectionBlock.size();
}

WORD Profile::writeProfileString(const String &sectionString,const String &itemString,const String &textString)
{
	return ::WritePrivateProfileString((LPSTR)sectionString,(LPSTR)itemString,(LPSTR)textString,mIniPathFileName);
}

WORD Profile::writeProfileBlock(const String &sectionString,Block<String> &itemStrings,Block<String> &textStrings)
{
	WORD blockSize((int)itemStrings.size());
	if(textStrings.size()!=blockSize)return FALSE;
	for(int i=0;i<blockSize;i++)writeProfileString(sectionString,itemStrings[i],textStrings[i]);
	return TRUE;
}

BOOL Profile::readSectionNames(Block<String> &sectionNames)
{
	char strBuffer[2048];
	char *ptrBuff;

  sectionNames.remove();
	if(!isOkay())return FALSE;
  ::GetPrivateProfileSectionNames(strBuffer,sizeof(strBuffer),mIniPathFileName);
	ptrBuff=strBuffer;
	while(ptrBuff&&*ptrBuff)
	{
	  sectionNames.insert(&String(ptrBuff));
		ptrBuff+=::strlen(ptrBuff)+1;
	}
	return sectionNames.size()?TRUE:FALSE;
}

WORD Profile::setIniFile(String iniFileName)
{
	mIsOkay=verifyInitializationFile(iniFileName);
  return mIsOkay;
}

WORD Profile::verifyInitializationFile(String iniFileName)
{
	PathFind pathFind;

	if(!pathFind.findFile(iniFileName,mIniPathFileName))return FALSE;
  return TRUE;
}

WORD Profile::verifyDirectory(String &pathDirectoryName)
{
	String currentWorkDir;
	int resultCode;

	::getcwd(currentWorkDir,String::MaxString);
	resultCode=::chdir(pathDirectoryName);
	::chdir(currentWorkDir);
	return !resultCode;
}

void Profile::makePathFileName(String &fileNameString)
{
	String tempString(fileNameString);
	String currentDriveString;

	drivePathName(currentDriveString);
	currentDriveString+=fileNameString;
	fileNameString=currentDriveString;
}

String Profile::removeExtension(String strPathFileName)
{
	char *ptr;

  if(strPathFileName.isNull())return String();
	ptr=strPathFileName.str()+(strPathFileName.length()-1);
	while(*ptr!='.'&&ptr>=strPathFileName.str())ptr--;
	if(*ptr=='.')*ptr=0;
	return strPathFileName;
}

String Profile::getExtension(String strPathFileName)
{
	char *ptr;

  if(strPathFileName.isNull())return String();
	ptr=strPathFileName.str()+(strPathFileName.length()-1);
	while(*ptr!='.'&&ptr>=strPathFileName.str())ptr--;
	if(ptr<strPathFileName.str()||*ptr!='.')return String();
	return ptr;
}

WORD Profile::makeFileName(String &pathFileName)
{
	String tempString(pathFileName);
	int extLen;
	char *ptr;

	ptr=tempString.str()+(tempString.length()-1);
	if(!ptr||(extLen=::strlen(ptr))<4)return FALSE;
	if(extLen>4)*(ptr+4)=0;
	while(*ptr!='\\'&&*ptr!='/'&&*ptr!=':'&&ptr>=(char*)tempString)ptr--;
	if(ptr<(char*)tempString)ptr++;
	pathFileName=ptr;
	return TRUE;
}

bool Profile::makeFileName(const String &strPathFileName,String &strFileName)
{
	int strLen;
	char *ptr;

	if(strPathFileName.isNull())return false;
	strLen=strPathFileName.length();
	ptr=(char*)(String&)strPathFileName+(strLen-1);
  while(*ptr!='\\'&&*ptr!='/'&&*ptr!=':'&&ptr>=(char*)(String&)strPathFileName)ptr--;
	strFileName=(ptr+1);
	return false;
}

bool Profile::verifyPathFileName(const String &somePathFileName)
{
	FILE *fp;

	fp=::fopen(somePathFileName,"rb");
	if(fp)::fclose(fp);
	return (fp?TRUE:FALSE);
}

bool Profile::makeDirectoryName(String &directoryName)
{
	String tempString(directoryName);
	char *ptr;

	if(0!=(ptr=::strchr(tempString,'*')))
	{
    if(ptr==(LPSTR)tempString)return false;
		*(--ptr)=0;
    directoryName=tempString;
		return TRUE;
	}
  ptr=tempString.str()+(tempString.length()-1);
	if(!ptr)return false;
	while(*ptr!='\\'&&*ptr!='/'&&*ptr!=':'&&ptr>=(char*)tempString)ptr--;
	if(ptr<(char*)tempString)return false;
	*(ptr)=0;
	directoryName=tempString;
	return true;
}

void Profile::expandEmbeddedMacro(String &someString)const
{
	String macroSyncChar("$(");
	String macroEndChar(")");
	String macroString;
	String tempString;
	String resultString;
	char *ptr;
	char *envPtr;
	char tempChar;

  if(someString.isNull())return;
	tempString=someString;
	ptr=::strstr(tempString,macroSyncChar);
	if(!ptr)return;
	tempChar=*ptr;
	*ptr=0;
	resultString=tempString;
	*ptr=tempChar;
	ptr+=2;
	ptr=::strtok(ptr,macroEndChar);
	if(!ptr)return;
	if(0==(envPtr=::getenv(ptr)))resultString+=mStringUnset;
	else resultString+=envPtr;
	ptr=::strtok(0,"\0");
	if(ptr)resultString+=ptr;
	someString=resultString;
}
