/*  $Id: directory_scanner_unix.cpp,v 1.16 2004/03/09 15:36:12 sphair Exp $
**
**  ClanLib Game SDK
**  Copyright (C) 2003  The ClanLib Team
**  For a total list of contributers see the file CREDITS.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This library is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
**  Lesser General Public License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*/

#include <API/Core/System/error.h>
#ifdef HAVE_LIBGEN_H
#include <libgen.h>
#endif
#include <fnmatch.h>
#include <unistd.h>
#include "directory_scanner_unix.h"

CL_DirectoryScanner_Unix::CL_DirectoryScanner_Unix ()
	: dir_temp (NULL), entry (NULL)
{
}

bool CL_DirectoryScanner_Unix::scan (const std::string& arg_path_name)
{
	path_name   = arg_path_name;
	use_pattern = false;

	if (path_name.empty ())
	  path_name = ".";

	if(dir_temp)
		closedir(dir_temp);

	dir_temp = opendir(path_name.c_str());
	if (dir_temp == NULL)
		return false;
	else
		return true;
}

bool CL_DirectoryScanner_Unix::scan (const std::string& arg_path_name, 
				     const std::string& arg_file_pattern)
{
	path_name    = arg_path_name;
	file_pattern = arg_file_pattern;
	use_pattern  = true;

	if (path_name.empty ())
	  path_name = ".";

	if(dir_temp)
		closedir(dir_temp);

	dir_temp = opendir(path_name.c_str());
	if (dir_temp == NULL)
		return false;
	else
		return true;
}

CL_DirectoryScanner_Unix::~CL_DirectoryScanner_Unix()
{
	if(dir_temp)
		closedir(dir_temp);
}

std::string CL_DirectoryScanner_Unix::get_directory_path()
{
	return path_name;
}

int CL_DirectoryScanner_Unix::get_size()
{
	return (int)statbuf.st_size;
}

std::string CL_DirectoryScanner_Unix::get_name()
{
	return file_name;
}

std::string CL_DirectoryScanner_Unix::get_pathname()
{
	return path_name + "/" + file_name;
}

bool CL_DirectoryScanner_Unix::is_directory()
{
	return (statbuf.st_mode & S_IFDIR);
}

bool CL_DirectoryScanner_Unix::is_hidden()
{
	return file_name[0] == '.' && file_name[1] != 0 && file_name[1] != '.';
}

bool CL_DirectoryScanner_Unix::is_readable()
{
	return access((path_name + "/" + file_name).c_str(), R_OK) == 0;
}

bool CL_DirectoryScanner_Unix::is_writable()
{
	return access((path_name + "/" + file_name).c_str(), W_OK) == 0;
}

bool CL_DirectoryScanner_Unix::next()
{	
	if(!dir_temp)
		throw("Directory scanner not initialized");

	entry = readdir(dir_temp);

	if( entry == NULL )
		return false;

	file_name = entry->d_name;

	if (stat((path_name + "/" + file_name).c_str(), &statbuf) == -1)
		memset(&statbuf, 0, sizeof(statbuf));

	if (use_pattern)
	{
		if (fnmatch(file_pattern.c_str(), file_name.c_str(), FNM_PATHNAME) == 0)
			return true;
		else
			return next();
	} else {
		return true;
	}
}


