/*
	static
*/
VError VFolder::ResolveAliasFolder( VFolder **ioFolder, bool inDeleteInvalidAlias)
{
	VError err = VE_OK;
	if ( (*ioFolder != NULL) && (*ioFolder)->fPath.IsFolder() && !(*ioFolder)->fFolder.Exists( false /* doesn't check alias */) )
	{
		// the folder doesn't exists
		// maybe is it an alias file?
		VString path = (*ioFolder)->fPath.GetPath();
		if (testAssert( path[path.GetLength()-1] == FOLDER_SEPARATOR))
		{
			path.Truncate( path.GetLength()-1);
			#if VERSIONWIN
			path += ".lnk";
			#endif
			VFile file( path);
			if (file.IsAliasFile() && file.Exists())
			{
				VFilePath resolvedPath;
				err = file.GetImpl()->ResolveAlias( resolvedPath);	// nothrow
				if (err == VE_OK)
				{
					if (resolvedPath.IsFolder())
					{
						(*ioFolder)->Release();
						*ioFolder = new VFolder( resolvedPath);
					}
					else if (inDeleteInvalidAlias)
					{
						err = file.Delete();
					}
					else
					{
						StThrowFileError errThrow( *ioFolder, VE_FILE_CANNOT_RESOLVE_ALIAS_TO_FOLDER);
						err = errThrow.GetError();
					}
				}
				else if (inDeleteInvalidAlias)
				{
					err = file.Delete();
				}
				else
				{
					if (IS_NATIVE_VERROR( err))
					{
						StThrowFileError errThrow( &file, VE_FILE_CANNOT_RESOLVE_ALIAS, err);
						err = errThrow.GetError();
					}
				}
			}
		}
	}
	return err;
}
VError VFolder::Delete( bool inRemoveContent ) const
{
	VError err;
	bool needThrow;
	if (IsEmpty())
	{
		err = fFolder.Delete();
		needThrow = IS_NATIVE_VERROR( err);
	}
	else
	{
		if ( inRemoveContent )
		{
			err = DeleteContents( true );
			if ( err == VE_OK )
				err = fFolder.Delete();
			needThrow = IS_NATIVE_VERROR( err);
		}
		else
		{
			err = VE_FOLDER_NOT_EMPTY;
			needThrow = true;
		}
	}

	xbox_assert( (err != VE_OK) || !fFolder.Exists( true));

	if (needThrow)
	{
		StThrowFileError errThrow( this, VE_FOLDER_CANNOT_DELETE, err);
		err = errThrow.GetError();
	}

	return err;
}
VError	VFolder::GetVolumeCapacity(sLONG8* outTotalBytes)const
{
#if !VERSION_LINUX

	VError err = fFolder.GetVolumeCapacity( outTotalBytes );

	if (IS_NATIVE_VERROR( err))
	{
		StThrowFileError errThrow( this, VE_FOLDER_CANNOT_GET_ATTRIBUTES, err);
		err = errThrow.GetError();
	}
	
	return err;

#else
    
    //jmo - Build fix rapide pour un truc qui n'est utilise que dans 4D.
    if(outTotalBytes!=NULL)
        *outTotalBytes=0;

    xbox_assert(false);
    return VE_UNIMPLEMENTED;

#endif
}
VError VFolder::MAC_GetPermissions( uWORD *outMode )
{
	VError err = fFolder.GetPermissions(outMode);
	
	if (IS_NATIVE_VERROR( err))
	{
		StThrowFileError errThrow( this, VE_FOLDER_CANNOT_GET_ATTRIBUTES, err);
		err = errThrow.GetError();
	}
	
	return err;
}
VError VFolder::WIN_SetAttributes( DWORD inAttrb) const
{
	VError err = fFolder.SetAttributes( inAttrb);

	if (IS_NATIVE_VERROR( err))
	{
		StThrowFileError errThrow( this, VE_FOLDER_CANNOT_SET_ATTRIBUTES, err);
		err = errThrow.GetError();
	}
	
	return err;
}
VError VFolder::MakeWritableByAll()
{
	VError err = fFolder.MakeWritableByAll();
	
	if (IS_NATIVE_VERROR( err))
	{
		StThrowFileError errThrow( this, VE_FOLDER_CANNOT_SET_ATTRIBUTES, err);
		err = errThrow.GetError();
	}
	
	return err;
}
VError VFolder::GetVolumeFreeSpace(sLONG8 *outFreeBytes, bool inWithQuotas ) const
{
	VError err = fFolder.GetVolumeFreeSpace( outFreeBytes, inWithQuotas );

	if (IS_NATIVE_VERROR( err))
	{
		StThrowFileError errThrow( this, VE_FOLDER_CANNOT_GET_ATTRIBUTES, err);
		err = errThrow.GetError();
	}
	
	return err;
}
VError VFolder::GetTimeAttributes( VTime* outLastModification, VTime* outCreationTime, VTime* outLastAccess ) const
{
	VError err = fFolder.GetTimeAttributes( outLastModification, outCreationTime, outLastAccess );

	if (IS_NATIVE_VERROR( err))
	{
		StThrowFileError errThrow( this, VE_FOLDER_CANNOT_GET_ATTRIBUTES, err);
		err = errThrow.GetError();
	}
	
	return err;
}
VError VFolder::SetTimeAttributes( const VTime *inLastModification, const VTime *inCreationTime, const VTime *inLastAccess ) const
{
	VError err = fFolder.SetTimeAttributes( inLastModification, inCreationTime, inLastAccess );

	if (IS_NATIVE_VERROR( err))
	{
		StThrowFileError errThrow( this, VE_FILE_CANNOT_GET_ATTRIBUTES, err);
		err = errThrow.GetError();
	}

	return err;
}
VError VFolder::Move( const VFolder& inNewParent, VFolder** outFolder ) const
{
	VError err = fFolder.Move( inNewParent, outFolder );

	if (IS_NATIVE_VERROR( err))
	{
		StThrowFileError errThrow( this, VE_FOLDER_CANNOT_RENAME, err);
		//errThrow->SetString( "newname", inName);
		err = errThrow.GetError();
	}

	return err;
}
VError VFolder::Rename( const VString& inName, VFolder** outFile ) const
{
	VError err = fFolder.Rename( inName, outFile );

	if (IS_NATIVE_VERROR( err))
	{
		StThrowFileError errThrow( this, VE_FOLDER_CANNOT_RENAME, err);
		errThrow->SetString( "newname", inName);
		err = errThrow.GetError();
	}

	return err;
}
VError VFolder::Create() const
{
	VError	err = VE_OK;
	
	// this is not an error if the folder already exists
	if (!fFolder.Exists( true))
	{
		err = fFolder.Create();
		xbox_assert( (err != VE_OK) || fFolder.Exists( true));

		if (IS_NATIVE_VERROR( err))
		{
			StThrowFileError errThrow( this, VE_FOLDER_CANNOT_CREATE, err);
			err = errThrow.GetError();
		}
	}
	return err;
}
VError VFolder::MoveToTrash() const
{
	VError	err = VE_OK;
	
	// this is not an error if the folder already exists
	if (fFolder.Exists( true))
	{
		err = fFolder.MoveToTrash();
		xbox_assert( (err != VE_OK) || !fFolder.Exists( true));
        
		if (IS_NATIVE_VERROR( err))
		{
			StThrowFileError errThrow( this, VE_CANNOT_MOVE_TO_TRASH, err);
			err = errThrow.GetError();
		}
	}
	return err;
}
VError VFolder::CopyTo( const VFolder& inDestinationFolder, VFolder **outFolder, FileCopyOptions inOptions) const
{
	VError err = VE_OK;
	VFolder *folder = NULL;

	if (IsSameFolder( &inDestinationFolder) || inDestinationFolder.GetPath().IsChildOf( GetPath()))
	{
		StThrowFileError errThrow( this, VE_CANNOT_COPY_ON_ITSELF);
		errThrow->SetString( "destination", inDestinationFolder.GetPath().GetPath());
		err = errThrow.GetError();
	}
	else
	{
		VString name;
		GetName( name);

		folder = new VFolder( inDestinationFolder, name);
		if (folder != NULL)
		{
			if ( ( (inOptions & FCP_Overwrite) != 0) && folder->Exists() )
				err = folder->Delete( true);
			if (err == VE_OK)
				err = CopyContentsTo( *folder, inOptions);
		}
		else
		{
			err = VE_MEMORY_FULL;
		}
	}

	if (outFolder != NULL)
	{
		*outFolder = folder;
		folder = NULL;
	}

	ReleaseRefCountable( &folder);
		
	return err;
}
VError VFolder::CopyContentsTo( const VFolder& inDestinationFolder, FileCopyOptions inOptions) const
{
	VError err = VE_OK;
	if (!inDestinationFolder.Exists())
	{
		// this easy case should be handled by system implementation
		err = inDestinationFolder.Create();
	}
	else if (IsSameFolder( &inDestinationFolder) || inDestinationFolder.GetPath().IsChildOf( GetPath()))
	{
		StThrowFileError errThrow( this, VE_CANNOT_COPY_ON_ITSELF);
		errThrow->SetString( "destination", inDestinationFolder.GetPath().GetPath());
		err = errThrow.GetError();
	}

	if (err == VE_OK)
	{
		bool ok = true;
		
		for( VFolderIterator folderIterator( this, FI_WANT_FOLDERS | FI_WANT_INVISIBLES) ; folderIterator.IsValid() && ok ; ++folderIterator)
		{
			VError err2 = folderIterator->CopyTo( inDestinationFolder, NULL, inOptions);
			if (err == VE_OK)
				err = err2;
			ok = (err == VE_OK) | ((inOptions & FCP_ContinueOnError) != 0);
		}
		
		for( VFileIterator fileIterator( this, FI_WANT_FILES | FI_WANT_INVISIBLES) ; fileIterator.IsValid() && ok ; ++fileIterator)
		{
			VError err2 = fileIterator->CopyTo( inDestinationFolder, NULL, inOptions);
			if (err == VE_OK)
				err = err2;
			ok = (err == VE_OK) | ((inOptions & FCP_ContinueOnError) != 0);
		}
	}
	
	return err;
}
bool VFolder::RevealInFinder( bool inInside) const
{
	bool done = false;
	if (inInside)
	{
		VFileIterator iter( this);
		VFile *firstFile = iter.First();
		if (firstFile != NULL)
			done = firstFile->RevealInFinder();
	}
	if (!done)
	{
		VError err = fFolder.RevealInFinder();

		if (IS_NATIVE_VERROR( err))
		{
			StThrowFileError errThrow( this, VE_FOLDER_CANNOT_REVEAL, err);
			err = errThrow.GetError();
		}
		done = err == VE_OK;
	}

	return done;
}