// NameManager.cpp: implementation of the NameManager class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "mw4gameed2.h"
#include "NameManager.h"

#define NAMEARRAYSTARTSIZE 32

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
NameManager *NameManager::Instance;

NameManager::NameManager()
{
	ArraySize=0;
	NameArray=NULL;
	StringCount=0;
	Reset();
}

void NameManager::Delete()
{
	for(int i=0;i<StringCount;i++)
	{
		delete NameArray[i];
	}
	
	delete NameArray;
	NameArray=NULL;
}


void NameManager::Reset()
{
	Delete();
	ArraySize=NAMEARRAYSTARTSIZE;
	NameArray=new CString *[ArraySize];
	for(int i=0;i<ArraySize;i++) NameArray[i]=NULL;
	StringCount=0;
}

void NameManager::GrowArray()
{
	CString  **new_array=new CString  *[ArraySize*2];
	int i;
	for(i=0;i<ArraySize;i++) new_array[i]=NameArray[i];
	for(i=ArraySize;i<ArraySize*2;i++) new_array[i]=NULL;
	ArraySize*=2;
	delete NameArray;
	NameArray=new_array;
}

void NameManager::AddString(const CString &str)
{
	ASSERT(str.CompareNoCase(""));
	if(	StringCount>=(ArraySize-1)) GrowArray();
	ASSERT(NameArray[StringCount+1]==NULL);
	int pos;
	bool fnd;
	fnd=FindString(str,&pos);
	ASSERT(fnd==false && pos<=StringCount && pos>=0);
	for(int i=StringCount;i>pos;i--) NameArray[i]=NameArray[i-1];
	NameArray[pos]=new CString(str);
	StringCount++;
}

bool NameManager::IsUnique(const CString &str)
{
int pos;
	return !FindString(str,&pos);
}

bool NameManager::FindString(const CString &str,int *pos)
{
	int low,high,mid=0;
	low=0;
	high=StringCount-1;
	int diff;

	while((high-low)>1)
	{
	mid=low+((high-low)/2);
	ASSERT(NameArray[mid]!=NULL);
	diff=NumStrCompare(*NameArray[mid],str);
	if(diff<0)
	{
		low=mid;
	}
	else
		if(diff>0)
		{
			high=mid;
		}
		else 
		{
			*pos=mid;
			return true;
		}
	}
		
	if((high-low)==1)
	{
	diff=NumStrCompare(*NameArray[low],str);
	if(diff==0) {*pos=low; return true;}
	if(diff>0)	{*pos=low; return false;}
	diff=NumStrCompare(*NameArray[high],str);
	if(diff==0) {*pos=high; return true;}
	if(diff<0) *pos=high+1; else *pos=high;
	return false;

	}

		*pos=mid;
		return false;
}

void NameManager::RemoveString(int idx)
{
	ASSERT(idx<StringCount);
	ASSERT(StringCount<ArraySize);
	ASSERT(idx>=0);
	
	ASSERT(NameArray[idx]!=NULL);
	delete NameArray[idx];
	StringCount--;
	for(int i=idx;i<StringCount;i++) NameArray[i]=NameArray[i+1];
	NameArray[StringCount]=NULL;
}

int NameManager::Separate(const CString &newname,CString *basename)
{
	int sidx;
	for(sidx=newname.GetLength()-1;sidx>=0 && isdigit(newname[sidx]);sidx--);
	
	if(sidx>=0 && newname[sidx]=='_')
	{
		*basename=newname.Left(sidx);
		return atoi((LPCSTR)newname.Mid(sidx+1));
	}
	else
	{
		*basename=newname;
		return -1;
	}	

}

CString NameManager::MakeUnique(CString newname)
{
	int pos;
	if(FindString(newname,&pos)) 
	{ 
	CString basename,newbase;
	Separate(newname,&basename);

	int icr=999999;
	do
	{
	newname.Format("%s_%04i",basename,icr);
	icr*=2;
	}
	while(FindString(newname,&pos));
	
	ASSERT(pos!=0);
	
	icr=Separate(*NameArray[pos-1],&newbase);
	ASSERT(!basename.CompareNoCase(newbase));

	newname.Format("%s_%04i",basename,icr+1);
	}
	AddString(newname);
	return newname;
}

int NameManager::NumStrCompare(const CString &str1,const CString &str2)
{
CString str1_base,str2_base;
int str1_num,str2_num;


str1_num=Separate(str1,&str1_base);
str2_num=Separate(str2,&str2_base);

int diff=str1_base.CompareNoCase(str2_base);

if(diff==0) 
{
if(str1_num==str2_num)
	{		// This fixes 01 and 001 case
	return str1.GetLength()-str2.GetLength();
	}
	return str1_num-str2_num;
}
else return diff;

}


NameManager::~NameManager()
{
	Delete();
}
