
#include "browse.hh"

Browse::~Browse ()
{
	while (this->Close ());
}

bool		Browse::Open (const std::string& path)
{
#if defined (OS_UNIX)
	DIR*	dir;

	if (!(dir = opendir ((this->GetPath () + path).c_str ())))
		return false;

	this->stack.push_back (StackItem (path, dir));
#elif defined (OS_WINDOWS)
	StackItemData	item_data;

	if ((item_data.handle = FindFirstFile ((this->GetPath () + path + "/*").c_str (), &item_data.find_data)) == INVALID_HANDLE_VALUE)
		return false;

	item_data.first = true;

	this->stack.push_back (StackItem (path, item_data));
#endif

	return true;
}

bool	Browse::Close ()
{
	if (this->stack.size () == 0)
		return false;

#if defined (OS_UNIX)
	closedir (this->stack.back ().second);
#elif defined (OS_WINDOWS)
	FindClose (this->stack.back ().second.handle);
#endif

	this->stack.pop_back ();

	return true;
}

const std::string&	Browse::GetFile () const
{
	return this->file;
}

const std::string	Browse::GetFull () const
{
	return this->GetPath () + this->GetFile ();
}

const std::string			Browse::GetPath () const
{
	Stack::const_iterator	iterator;
	std::string				path;

	iterator = this->stack.begin ();

	if (iterator != this->stack.end ())
	{
		path = iterator->first;
		++iterator;
	}

	while (iterator != this->stack.end ())
	{
		path = path + "/" + iterator->first;
		++iterator;
	}

	if (path != "")
		path = path + "/";

	return path;
}

bool	Browse::IsDir (bool special) const
{
	return this->is_dir && (special || (this->file != "." && this->file != ".."));
}

bool	Browse::Next ()
{
	if (this->stack.size () == 0)
		return false;

#if defined (OS_UNIX)
	struct dirent	*entity;
	struct stat		fstat;

	if (!(entity = readdir (this->stack.back ().second)))
		return false;

	if (lstat ((this->GetPath () + entity->d_name).c_str (), &fstat))
		return false;

	this->file = entity->d_name;
	this->is_dir = ((fstat.st_mode & S_IFMT) == S_IFDIR);
#elif defined (OS_WINDOWS)
	StackItemData*	item_data = &this->stack.back ().second;

	if (item_data->first)
		item_data->first = false;
	else if (!FindNextFile (item_data->handle, &item_data->find_data))
		return false;

	this->file = item_data->find_data.cFileName;
	this->is_dir = (item_data->find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
#endif

	return true;
}
