#ifndef _COMMON_FINDDATA_HPP_
#define _COMMON_FINDDATA_HPP_
#ifndef _COMMON_WINDOWS_HPP_
#include <common/windows.hpp>
#endif
#ifndef _COMMON_STRING_HPP_
#include <common/string.hpp>
#endif
#ifndef _COMMON_SYSTEMTIME_HPP_
#include <common/systime.hpp>
#endif
#ifndef _COMMON_FILETIME_HPP_
#include <common/filetime.hpp>
#endif

class FindData : private WIN32_FIND_DATA
{
public:
	enum FileAttributes{FileArchive=FILE_ATTRIBUTE_ARCHIVE,FileDirectory=FILE_ATTRIBUTE_DIRECTORY,
				 FileHidden=FILE_ATTRIBUTE_HIDDEN,FileNormal=FILE_ATTRIBUTE_NORMAL,
				 FileReadOnly=FILE_ATTRIBUTE_READONLY,FileSystem=FILE_ATTRIBUTE_SYSTEM,
				 FileTemporary=FILE_ATTRIBUTE_TEMPORARY};
	FindData(void);
	FindData(const FindData &someFindData);
	virtual ~FindData();
	WORD findFirst(const String &searchFileName,DWORD attributes=(DWORD)FileArchive);
  WORD findNext(void);
	FindData &operator=(const FindData &someFindData);
	WORD operator==(const FindData &someFindData)const;
	operator WIN32_FIND_DATA &(void);
	DWORD attributes(void)const;
	void attributes(DWORD attributes);
	SystemTime creationTime(void)const;
	void creationTime(const SystemTime &creationTime);
	SystemTime lastAccessTime(void)const;
	void lastAccessTime(const SystemTime &lastAccessTime);
	SystemTime lastModifyTime(void)const;
	void lastModifyTime(const SystemTime &lastModifyTime);
	DWORD sizeHigh(void)const;
	void sizeHigh(DWORD sizeHigh);
	DWORD sizeLow(void)const;
	void sizeLow(DWORD sizeLow);
	String fileName(void)const;
	void fileName(String fileName);
	String altFileName(void)const;
	void altFileName(String altFileName);
private:
	void zeroInit(void);
  void destroyFind(void);
	HANDLE mhFindHandle;
};

inline
FindData::FindData(void)
: mhFindHandle(INVALID_HANDLE_VALUE)
{
	zeroInit();
}

inline
FindData::FindData(const FindData &someFindData)
: mhFindHandle(INVALID_HANDLE_VALUE)
{
	*this=someFindData;
}

inline
FindData::~FindData()
{
  destroyFind();
}

inline
FindData::operator WIN32_FIND_DATA &(void)
{
	return *this;
}

inline
DWORD FindData::attributes(void)const
{
	return WIN32_FIND_DATA::dwFileAttributes;
}

inline
void FindData::attributes(DWORD attributes)
{
	WIN32_FIND_DATA::dwFileAttributes=attributes;
}

inline
SystemTime FindData::creationTime(void)const
{
	return (FileTime&)WIN32_FIND_DATA::ftCreationTime;
}

inline
void FindData::creationTime(const SystemTime &creationTime)
{
	(FileTime&)WIN32_FIND_DATA::ftCreationTime=creationTime;
}

inline
SystemTime FindData::lastAccessTime(void)const
{
	return (FileTime&)WIN32_FIND_DATA::ftLastAccessTime;
}

inline
void FindData::lastAccessTime(const SystemTime &lastAccessTime)
{
	(FileTime&)WIN32_FIND_DATA::ftLastAccessTime=lastAccessTime;
}

inline
SystemTime FindData::lastModifyTime(void)const
{
	return (FileTime&)WIN32_FIND_DATA::ftLastWriteTime;
}

inline
void FindData::lastModifyTime(const SystemTime &lastModifyTime)
{
	(FileTime&)WIN32_FIND_DATA::ftLastWriteTime=lastModifyTime;
}

inline
DWORD FindData::sizeHigh(void)const
{
	return WIN32_FIND_DATA::nFileSizeHigh;
}

inline
void FindData::sizeHigh(DWORD sizeHigh)
{
	WIN32_FIND_DATA::nFileSizeHigh=sizeHigh;
}

inline
DWORD FindData::sizeLow(void)const
{
	return WIN32_FIND_DATA::nFileSizeLow;
}

inline
void FindData::sizeLow(DWORD sizeLow)
{
	WIN32_FIND_DATA::nFileSizeLow=sizeLow;
}

inline
String FindData::fileName(void)const
{
	return WIN32_FIND_DATA::cFileName;
}

inline
void FindData::fileName(String fileName)
{
	WORD nameLength(fileName.length());

	if(fileName.isNull())return;
	if(nameLength>=sizeof(WIN32_FIND_DATA::cFileName))fileName.length(sizeof(WIN32_FIND_DATA::cFileName)-1);
	::strcpy(WIN32_FIND_DATA::cFileName,(LPSTR)fileName);
}

inline
String FindData::altFileName(void)const
{
	return WIN32_FIND_DATA::cAlternateFileName;
}

inline
WORD FindData::findNext(void)
{
	if(INVALID_HANDLE_VALUE==mhFindHandle)return FALSE;
	return ::FindNextFile(mhFindHandle,&((WIN32_FIND_DATA&)*this));
}

inline
void FindData::zeroInit(void)
{
	::memset(&((WIN32_FIND_DATA&)*this),0,sizeof(WIN32_FIND_DATA));
}
#endif
