// Copyright 2000, Be Incorporated. All Rights Reserved.
// This file may be used under the terms of the Be Sample Code License.

#include <Directory.h>
#include <Path.h>
#include <stdio.h>
#include <Application.h>
#include <string.h>

#include "DirWalker.h"

DirWalker::DirWalker(const entry_ref &ref)
{
	rootref=entry_ref(ref);
	reflist.MakeEmpty();
	dirlist.MakeEmpty();
	
	AddEntries(&rootref);
	Rewind();
}

DirWalker::DirWalker(const char *path)
{
	get_ref_for_path(path,&rootref);
	reflist.MakeEmpty();
	dirlist.MakeEmpty();
	AddEntries(&rootref);
	Rewind();
}

DirWalker::~DirWalker()
{
	for(int i=0;;i++)
	{
		entry_ref *ref=(entry_ref*)reflist.ItemAt(i);
		if(!ref)
			break;
		delete ref;
	}
	for(int i=0;;i++)
	{
		entry_ref *ref=(entry_ref*)dirlist.ItemAt(i);
		if(!ref)
			break;
		delete ref;
	}
}

bool DirWalker::IsInDirList(const entry_ref *ref)
{
	for(int i=0;;i++)
	{
		entry_ref *dir=(entry_ref*)dirlist.ItemAt(i);
		if(!dir)
			break;
		if(*ref==*dir)
			return true;
	}
	return false;
}


status_t DirWalker::AddEntries(const entry_ref *ref)
{
	BEntry entry(ref,true); // traverse!
	entry_ref realref;
	entry.GetRef(&realref);

	if(entry.InitCheck()==B_OK)
	{
		if(entry.IsFile())
		{
			reflist.AddItem(new entry_ref(realref));
		}
		else if(entry.IsDirectory())
		{
			if(!IsInDirList(&realref)) // did we do this directory before
			{
				dirlist.AddItem(new entry_ref(realref)); // now we did
				
				BDirectory dir(&realref);
				entry_ref childref= *ref;
			
				while(dir.GetNextRef(&childref)==B_OK)
				{
					status_t result=AddEntries(&childref);
					if(result!=B_OK)
						return result;
				}
			}
		}
		else
		{
			// don't know what this is, but I can't handle it
		//	debug(("PANIC: unknown entry!\n"));
		}
	}
	else
	{
	//	debug(("InitCheck not OK\n"));
		return B_ERROR;
	}
	return B_OK;
}

void DirWalker::Rewind()
{
	index=0;
}

status_t DirWalker::NextRef(entry_ref *nextref)
{
//	debug(("NextRef1: %d\n",index));
	entry_ref *ref=(entry_ref*)reflist.ItemAt(index);
//	debug(("NextRef2: %08x\n",ref));
	if(ref)
	{
		*nextref=*ref;
		index++;
		return B_OK;
	}
//	debug(("returning error\n"));
	return B_ENTRY_NOT_FOUND;
}

