//	CFolderUrl.c

#include "FSUtils.h"
#include "CDesktop.h"

#include "CRoseServers.h"
#include "CGeneratorWindow.h"
#include "CDiskUrl.h"
#include "CFileUrl.h"
#include "CFolderUrl.h"

OSErr	CFolderUrl::IFolderUrl(
	CDiskUrl			*urlDiskP, 
	CFolderUrl			*urlParentFolderP, 
	Gen_Item			*itemP, 
	EntryIndex			directoryIndex)
{
	OSErr				err = noErr;
	DiskLocSpecUnion	locSpec;
	
	i_myEntryCachedB	= FALSE;

	locSpec.pro = SetRboShort(0);

	i_generatorP	= NULL;
	i_itemP			= itemP;
	i_roseDocB		= FALSE;
	i_iconSuiteH	= NULL;

	err = _inherited::IFolder(
		urlDiskP, urlParentFolderP, locSpec, directoryIndex, directoryIndex);
	
	return err;
}

typedef struct {
	CGenerator		*genP;
	Boolean			foundB;
} RoseGenScanData;

Boolean		CB_S_ScanForGen(CWindow *window, void *data);
Boolean		CB_S_ScanForGen(CWindow *window, void *data)
{
	Boolean		abortB = FALSE;
	
	if (window->i_windowType == ADFS_Window_GENERATOR) {
		CGeneratorWindow	*thiz = (CGeneratorWindow *)window;
		RoseGenScanData		*scanP = (RoseGenScanData *)data;
		
		if (scanP->genP == thiz->i_generator) {
			scanP->foundB	= TRUE;
			abortB			= TRUE;
		}
	}
	
	return abortB;
}

void			CFolderUrl::Dispose(void)
{
	if (i_generatorP && !i_generatorP->i_windowP0) {
		//	save?
		i_generatorP->Dispose();
	}
	
	if (i_iconSuiteH) {
		DisposeIconSuite((IconSuiteRef)i_iconSuiteH, TRUE);
		i_iconSuiteH = NULL;
	}
	
	_inherited::Dispose();
}

OSErr			CFolderUrl::AddEntries(Boolean normalB, Boolean deletedB)
{
	OSErr				err		= noErr;
	Gen_MakeEntryData	data;
	CEntry				*entryP = i_topicRef.cTopic ? (CEntry *)this : (CEntry *)i_cDisk.url;
	
	data.dirIndexS			= 0;	//	relative to entire directory
	data.normalB			= TRUE;
	data.deletedB			= FALSE;
	data.blocksInVolumeL	= 0;
	data.headerBlockS		= 0;
	
	if (!err) err = entryP->i_topicRef.cTopic->O_SetRecent();
	if (!err) err = ForEachEntry(Url_MakeNewEntryCB, &data);
	if (!err) err = _inherited::AddEntries(normalB, deletedB);
	
	return err;
}

OSErr			CFolderUrl::ForEachEntry(URL_ForEachEntryCB Url_ForEachUserCB, void *data)
{
	OSErr				err			= noErr;
	Gen_LinkContent		*contentP	= Rose_ResolveRef(i_itemP, Gen_Ref_DEST);

	if (contentP->type == GEN_Link_FILE) {

		if (i_generatorP == NULL) {
			Boolean		folderB;
			
			err = FSpIsFolder(&contentP->u.file, &folderB);
			
			if (!err) {
				i_generatorP = Gen_OpenFSSpec(
					folderB ? Gen_GetFile_FS_FOLDER : Gen_GetFile_ROSE, 
					kGenFileType, &contentP->u.file, NULL, FALSE);

				if (!i_generatorP) {
					ReportErrorStr(err = -1, "Trouble loading rose file");
				}
			}
		}
		
		if (i_generatorP) {
			Gen_ForEachData			feData;

			feData.thiz					= this;
			feData.Url_ForEachUserCB	= Url_ForEachUserCB;
			feData.data					= data;
			
			err = i_generatorP->i_list->Iterate(kIter_FOR_EACH_ENTRY, &feData);
		}
	}

	return err;
}

//	static
OSErr	CFolderUrl::Url_MakeNewEntryCB(
	CFolderUrl			*thiz, 
	Gen_Item			*itemP, 
	EntryIndex			indexL, 
	Boolean				*done, 
	void				*data)
{
	OSErr				err			= noErr;
	Gen_MakeEntryData	*dataP		= (Gen_MakeEntryData *)data;

	err	= thiz->MakeNewEntry(itemP, indexL, dataP, NULL, FALSE);

	return err;
}

OSErr			CFolderUrl::MakeNewEntry(
	Gen_Item			*itemP, 
	EntryIndex			indexL, 
	Gen_MakeEntryData	*dataP, 
	CEntry				**newEntry0, 
	Boolean				verifyB)
{
	OSErr	err		= noErr;
	
	if (i_generatorP->i_prefs.mode != GEN_Mode_GO || indexL > 0) {
		Gen_LinkContent		*contentP	= Rose_ResolveRef(itemP, Gen_Ref_DEST);
		Boolean				folderB		= FALSE;
		CEntry				*entryP		= NULL;
		Boolean				roseDocB	= FALSE;
		
		(dataP->dirIndexS)++;	
		
		if (newEntry0) {
			*newEntry0 = NULL;
		}
		
		if (contentP->type == GEN_Link_FILE) {
			err = FSpIsFolder(&contentP->u.file, &folderB);
			
			if (!err && !folderB) {
				FInfo		fInfo;
				
				err		= FSpGetFInfo(&contentP->u.file, &fInfo);
				folderB	= fInfo.fdType == kGenFileType;
				roseDocB = folderB;
			}
		}

		if (!err && folderB) {
			CFolderUrl		*cFolder;

			if (NewObject(cFolder, CFolderUrl, err)) {
				O_CTopic		*topic;
				
				err = i_cDisk.url->i_desktop->i_cOutline->O_GetRecent(&topic);
				
				if (!err) {
					entryP = cFolder;
					err = cFolder->IFolderUrl(i_cDisk.url, this, itemP, dataP->dirIndexS);
					
					cFolder->i_roseDocB = roseDocB;
				}
				
				if (!err) err = topic->O_SetRecent();
			}
		} else {
			CFileUrl	*cFile;
			
			if (NewObject(cFile, CFileUrl, err)) {
				entryP = cFile;
				err = cFile->IFileUrl(i_cDisk.url, this, itemP, dataP->dirIndexS);
			}
		}
			
		if (err && entryP) {
			entryP->Dispose();
		} else if (newEntry0) {
			*newEntry0 = entryP;
		}
	}

	return err;
}

DateTimeRec		*CFolderUrl::GetCreatedTime(DateTimeRec *dt)
{
	*dt = i_itemP->resource.source.date;
	
	return dt;
}

void			CFolderUrl::SetCreatedTime(DateTimeRec *dt)
{
	i_itemP->resource.source.date = *dt;
}

DateTimeRec		*CFolderUrl::GetModifiedTime(DateTimeRec *dt)
{
	*dt = i_itemP->resource.dest.date;
	
	return dt;
}

void			CFolderUrl::SetModifiedTime(DateTimeRec *dt)
{
	i_itemP->resource.dest.date = *dt;
}

DateTimeRec		*CFolderUrl::GetModifiedTimeRemote(DateTimeRec *dt)
{
	Gen_LinkContent		*contentP = Rose_ResolveRef(i_itemP, Gen_Ref_DEST);

	switch (contentP->type) {

		case GEN_Link_PICT_FILE:
		case GEN_Link_FILE: {
			DateTimeRec		creDate;
			
			(void)FSpGetFileDates(&contentP->u.file, &creDate, dt);
			break;
		}
	}
	
	return dt;
}

void			CFolderUrl::RemoteChanged(void)
{
	DateTimeRec		dt;
	
/*
	if (rose doc) {
		dispose all children
		re-init
	} else {
		reverse loop local, delete any that have been deleted from remote
			meanwhile comparing dates of matches and recursing as necessary
		
		loop remote, match with local, add any to local that are new at remote
	}
*/
	
	SetModifiedTime(GetModifiedTimeRemote(&dt));
	InvalStat(ADFS_Stat_MOD_DATE);
}

char			*CFolderUrl::GetName(char *buf)
{
	if (!GetParentFolder()) {
		i_cDisk.url->GetName(buf);
	} else {
		_inherited::GetName(buf);
		
		if (buf[0] == 0) {
			Rose_GetName(i_itemP, Gen_Ref_SRC, buf);
			_inherited::SetName(buf);
		}
	}
	
	return buf;
}

typedef struct {
	char		*name;
	Boolean		unique;
} GetUniqueNameRec;

static	OSErr	GetUniqueNameCB(
	CFolderUrl			*thiz, 
	Gen_Item			*itemP, 
	EntryIndex			entryIndex, 
	Boolean				*done, 
	void				*data
) {
	GetUniqueNameRec	*nameRec = (GetUniqueNameRec *)data;
	char				nameAC[GEN_MaxTextLen];
	
	Rose_GetName(itemP, Gen_Ref_SRC, nameAC);

	if (strcmp(nameAC, nameRec->name) == 0) {
		nameRec->unique	= FALSE;
		*done			= TRUE;
	}

	return noErr;
}

Boolean			CFolderUrl::GetUniqueName(char *fileName)
{
	OSErr				err		= noErr;
	Boolean				done	= FALSE;
	char				newName[GEN_MaxTextLen];
	GetUniqueNameRec	nameRec;
	short				loop;
	
	nameRec.name	= newName;
	nameRec.unique	= TRUE;
	
	strcpy(newName, fileName);
	err	= ForEachEntry(GetUniqueNameCB, &nameRec);
	
	if (err) {
		nameRec.unique	= FALSE;
	} else if (!nameRec.unique) {
		for (loop = 1; !done && loop <= 99; loop++) {
			nameRec.unique	= TRUE;
			sprintf(newName, "%s %d", fileName, loop);
			err	= ForEachEntry(GetUniqueNameCB, &nameRec);

			if (err) {
				done			= TRUE;
				nameRec.unique	= FALSE;
			} else if (nameRec.unique) {
				done = TRUE;
				strcpy(fileName, newName);
			}
		}
	}
	
	return nameRec.unique;
}

OSErr		CFolderUrl::NewFolder(CEntry **newFolderH)
{
	OSErr		err	= noErr;

	err = NewFile(TRUE, newFolderH);

	return err;
}

OSErr			CFolderUrl::NewFile(Boolean isFolderB, CEntry **entryH)
{
	OSErr				err			= noErr;
	O_CTopic			*topic		= NULL;
	CEntry				*newEntry	= NULL;

/*
	*entryH = NULL;
	
	if (isFolderB) {
		strcpy(fileName, "Untitled Rose");
	} else {
		strcpy(fileName, "Untitled");
	}
	
	if (!GetUniqueName(fileName)) {
		ReportError(err = IC_Err_FILE_ALREADY_EXISTS);
		goto new_file_done;
	}
	
	if (isFolderB) {
		//	make a new rose document
	}
	
	topic = GetEntryTopic(this);
		
	err = topic->O_SetRecent();
	if (err) goto new_file_error;

	//	not necessariy *this*!  (could be CDisk)
	newEntry = GetTopicEntry(topic);
	if (!newEntry) goto new_file_error;
	
	newEntry->i_addTopicIndex = entryLoc.dirIndex - 1;

	Gen_MakeEntryData		data;
	
	structclr(data);
	data.dirIndexS			= newEntry->i_addTopicIndex;
	data.normalB			= TRUE;
	
	err = MakeNewEntry(
		dirEntryP, 
		entryLoc.block, 
		entryLoc.entryIndex, 
		&data, 
		&newEntry, 
		FALSE);
		
	if (err) goto new_file_error;
	
	goto new_file_done;

	//	if error, try to back out, ignore any other errors
	new_file_error:
	newEntry = NULL;

	dirEntryP = GetEntry(entryLoc.block, entryLoc.entryIndex);
	if (dirEntryP) {
		dirEntryP->typeName.stnl.storageType = Pro_Storage_INACTIVE;
		(void)i_cDisk.pro->SetBlock();
		
		if (isFolderB && newBlock != 0) {
			(void)i_cDisk.pro->FreeBlock(newBlock);
		}
	}

	if (dec_dir_countB) {
		(void)IncrementDirCount(-1);
	}
	
	new_file_done:
	*entryH = newEntry;
	
	i_myEntryCachedB = FALSE;
*/	
	return err;
}

void			CFolderUrl::ConformStrLen(char* nameStr)
{
	short	lengthS = strlen(nameStr);
	
	if (lengthS > GEN_MaxTextLen) {
		nameStr[lengthS] = GEN_MaxTextLen;
	}
}


void			CFolderUrl::GetAccessBits(Gen_AccessBits *bits)
{
	_inherited::GetAccessBits(bits);
}

void			CFolderUrl::SetAccessBits(Gen_AccessBits *bits)
{
	_inherited::SetAccessBits(bits);
}

void			CFolderUrl::SetTwirled(Boolean twirledB)
{
	OSErr			err = noErr;
	
	i_itemP->b.twirledB = twirledB;
	
	if (!i_generatorP) {
		(void)AddEntries(TRUE, FALSE);
	}
	
	_inherited::SetTwirled(twirledB);
}

Boolean			CFolderUrl::GetTwirled(void)
{
	return i_itemP->b.twirledB;
}

CEntry			*CFolderUrl::GetEntryFromItem(Gen_Item *itemP)
{
	EntryIndex		curIndex, maxIndex = CountEntries();
	CEntry			*entryP = NULL, *curEntryP;
	Boolean			foundB = FALSE;
	
	for (curIndex = 0; curIndex < maxIndex; curIndex++) {
		curEntryP = GetIndEntry(curIndex);
		
		if (curEntryP) {
			if (curEntryP->i_type == FSObject_FOLDER) {
				foundB = ((CFolderUrl *)curEntryP)->i_itemP == itemP;
			} else {
				foundB = ((CFileUrl *)curEntryP)->i_itemP == itemP;
			}

			if (foundB) {
				entryP = curEntryP;
				break;
			}
		}
	}
	
	return entryP;
}

OSErr			CFolderUrl::PutFileNewEntry(Handle fileH)
{
	OSErr		err = noErr;

	return err;
}

void			CFolderUrl::SetName(char *buf)
{
//	Gen_LinkContent		*contentP = Rose_ResolveRef(i_itemP, Gen_Ref_SRC);

//	Rose_SetText(contentP, buf);
//	_inherited::SetName(buf);
}


ulong		CFolderUrl::GetPhysicalSize(void)
{
	if (i_physical_sizeL == 0) {
		long			curEntryL, numEntriesL = CountEntries();
		
		for (curEntryL = 0; curEntryL < numEntriesL; curEntryL++) {
			CEntry		*entryP = GetIndEntry(curEntryL);
			
			if (!entryP->IsDeleted()) {
				i_physical_sizeL += entryP->GetPhysicalSize();
			}
		}
	}
	
	return i_physical_sizeL;
}

ulong		CFolderUrl::GetLogicalSize(void)
{
	if (i_logical_sizeL == 0) {
		long			curEntryL, numEntriesL = CountEntries();
		
		for (curEntryL = 0; curEntryL < numEntriesL; curEntryL++) {
			CEntry		*entryP = GetIndEntry(curEntryL);
			
			if (!entryP->IsDeleted()) {
				i_logical_sizeL += entryP->GetLogicalSize();
			}
		}
	}
	
	return i_logical_sizeL;
}

Boolean		CFolderUrl::IsDeleted(void)
{
	Boolean		deletedB	= _inherited::IsDeleted();
	
	if (!deletedB && i_type != FSObject_DISK_ROOT_FOLDER) {
		
	}

	return deletedB;
}

OSErr			CFolderUrl::Delete(Boolean warnB, CDialogCopy *copyP0)
{
	OSErr		err				= noErr;

//		if (!err) err = _inherited::Delete(warnB, copyP0);
	
	return err;
}


ADFS_IconType			CFolderUrl::GetIconType(void)
{
	extern Handle	g_iconSuiteH;
	ADFS_IconType	icon = ADFS_Icon_CUSTOM;

	if (!i_iconSuiteH) {
		Gen_LinkContent		*contentP	= Rose_ResolveRef(i_itemP, Gen_Ref_DEST);

		if (
			contentP->type == GEN_Link_FILE
			|| contentP->type == GEN_Link_PICT_FILE
		) {
			i_iconSuiteH = FSpGetIconSuite(&contentP->u.file);
		}
	}
	
	if (i_iconSuiteH) {
		g_iconSuiteH = i_iconSuiteH;
	} else {
		icon = i_roseDocB
			? ADFS_Icon_ROSE_DOCUMENT 
			: _inherited::GetIconType();
	}

	return icon;
}

char			*CFolderUrl::GetDescription(char *buf)
{
	if (i_roseDocB) {
		strcpy(buf, "Rose Document");
	} else {
		strcpy(buf, "Finder Folder");
	}

	return buf;
}

void			CFolderUrl::Open(void)
{
	CFolderUrl		*parentP = (CFolderUrl *)GetParentFolder();
	
	if (parentP) {
		parentP->i_generatorP->Generate(i_itemP);
	} else {
		gRoseServers->i_generator->Generate(i_itemP);
	}
}

