#ifndef _COMMON_DISKINFO_HPP_
#define _COMMON_DISKINFO_HPP_
#ifndef _COMMON_WINDOWS_HPP_
#include <common/windows.hpp>
#endif
#ifndef _COMMON_BLOCK_HPP_
#include <common/block.hpp>
#endif
#ifndef _COMMON_STRING_HPP_
#include <common/string.hpp>
#endif
#ifndef _COMMON_FINDDATA_HPP_
#include <common/finddata.hpp>
#endif

class DiskInfo : public FindData
{
public:
	enum DriveType{DriveUnknown=0,DriveNoRoot=1,DriveRemovable=DRIVE_REMOVABLE,DriveFixed=DRIVE_FIXED,DriveRemote=DRIVE_REMOTE,DriveCDROM=DRIVE_CDROM,DriveRamDisk=DRIVE_RAMDISK};
	DiskInfo(void);
	virtual ~DiskInfo();
	DWORD getDiskFreeSpace(String pathFileName=String())const;
	DWORD getDiskUsage(String pathFileName=String())const;
	DWORD getCurrentDirectory(String &currentDirectory)const;
  DWORD setCurrentDirectory(const String &currentDirectory)const;
  WORD createDirectory(const String &pathDirectoryName)const;
	WORD getLogicalDrives(Block<String> &driveStrings)const;
	WORD getFixedLogicalDrives(Block<String> &driveStrings)const;
	DriveType getDriveType(String pathFileName=String())const;
	bool unlink(const String &pathFileName)const;
	BOOL copyFile(const String &strExistingFile,const String &strNewFile,BOOL overwrite=TRUE);
  BOOL rename(const String &strExistingFileName,const String &strNewFile);
private:
  String rootPath(String pathFileName)const;
};

inline
DiskInfo::DiskInfo(void)
{
}

inline
DiskInfo::~DiskInfo()
{
}

inline
DWORD DiskInfo::getDiskFreeSpace(String pathFileName)const
{
	DWORD sectorsPerCluster;
	DWORD bytesPerSector;
	DWORD freeClusters;
	DWORD totalClusters;

	pathFileName=rootPath(pathFileName);
	if(!::GetDiskFreeSpace((pathFileName.isNull()?(LPSTR)0:(LPSTR)pathFileName),&sectorsPerCluster,&bytesPerSector,&freeClusters,&totalClusters))return FALSE;
	return freeClusters*sectorsPerCluster*bytesPerSector;
}

inline
DWORD DiskInfo::getDiskUsage(String pathFileName)const
{
	DWORD sectorsPerCluster;
	DWORD bytesPerSector;
	DWORD freeClusters;
	DWORD totalClusters;

	pathFileName=rootPath(pathFileName);
	if(!::GetDiskFreeSpace((pathFileName.isNull()?(LPSTR)0:(LPSTR)pathFileName),&sectorsPerCluster,&bytesPerSector,&freeClusters,&totalClusters))return FALSE;
	return (totalClusters*sectorsPerCluster*bytesPerSector)-(freeClusters*sectorsPerCluster*bytesPerSector);
}

inline
DWORD DiskInfo::setCurrentDirectory(const String &currentDirectory)const
{
	if(currentDirectory.isNull())return FALSE;
  return ::SetCurrentDirectory((LPSTR)currentDirectory);
}

inline
WORD DiskInfo::createDirectory(const String &pathDirectoryName)const
{
  if(pathDirectoryName.isNull())return FALSE;
  return ::CreateDirectory(pathDirectoryName,(LPSECURITY_ATTRIBUTES)0);
}

inline
String DiskInfo::rootPath(String pathFileName)const
{
	String rootPath;

	if(pathFileName.isNull())return rootPath;
	rootPath=pathFileName.betweenString(0,'\\');
	rootPath+="\\";
	return rootPath;
}

inline
DiskInfo::DriveType DiskInfo::getDriveType(String pathFileName)const
{
	pathFileName=rootPath(pathFileName);
	return (DriveType)::GetDriveType((pathFileName.isNull()?(LPSTR)0:(LPSTR)pathFileName));
}

inline
bool DiskInfo::unlink(const String &pathFileName)const
{
	if(pathFileName.isNull())return false;
	if(DriveCDROM==getDriveType(pathFileName))return false;
	return ::DeleteFile(pathFileName);
}
#endif
