#ifndef _xbFILETOOLS_
#define _xbFILETOOLS_
/*<<<***************************************************************************
The MIT License (MIT)

Copyright(C) 2013 - 2015 Marc Mirti Mancinelli, Christophe Lardau and Philippe Pamart (xdcube.org)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
////////////////////////////////////////////////////////////////////////////////
#Title: xbFileTools
#Project: xdcBase
////////////////////////////////////////////////////////////////////////////////
#Author: Marc MIRTI MANCINELLI
#History:
<05/02/2014: creation.
12/02/2014: this notice inserted.
***************************************************************************>>>*/

#ifndef _xbPTR_
#	include "xbPtr.h"
#endif

#ifndef _xbSTRING_
#	include "xbString.h"
#endif

#ifndef _xbDATETIME_
#	include "xbDateTime.h"
#endif

#ifndef _xbSECURITY_
#	include "xbSecurity.h"
#endif

#include <shobjidl.h>

extern int	xbEXPORT xbMatchPath(const xbString &fnameWildCard,const xbString &fname);
extern int	xbEXPORT xbMatchPathCase(const xbString &fnameWildCard,const xbString &fname);

xbString	xbEXPORT xbSubPath(const xbString &_path,xbString *pRet = NULL,bool *pbEndSlash = NULL);
xbString	xbEXPORT xbSubPathEnd(const xbString &_path,xbString *pRet = NULL,bool *pbStartSlash = NULL);

extern xbString xbEXPORT xbGetFilePath(HMODULE hMod = xbGetInstanceHandle(),bool bLongName = true);
extern xbString xbEXPORT xbGetFileName(HMODULE hMod = xbGetInstanceHandle(),bool bLongName = true);
extern xbString xbEXPORT xbGetFileName(LPCSTR pszFile);
extern xbString xbEXPORT xbGetFileNameExt(HMODULE hMod = xbGetInstanceHandle(),bool bLongName = true);
extern xbString xbEXPORT xbGetFileNameExt(LPCSTR pszFile);
extern xbString xbEXPORT xbGetFileExt(LPCSTR pszFile,bool bIncludePoint = true);
extern xbString xbEXPORT xbGetFileDir(HMODULE hMod = xbGetInstanceHandle(),bool bEndSlash = true,bool bLongName = true);
extern xbString xbEXPORT xbGetFileDir(LPCSTR pszFile,bool bEndSlash = true);

extern xbEXPORT bool xbPathExists(LPCSTR pszPath);
extern xbEXPORT bool xbFileExists(LPCSTR pszFile);
extern xbEXPORT bool xbDirExists(LPCSTR pszDir);
extern xbEXPORT bool xbMakeDir(const xbString &dir,bool bRecursive,const xbSecurityAttr *lpSecurityAttributes = NULL, xbOpMode opm =xbOp_Required,bool *pbCreated = NULL);

extern xbString xbEXPORT xbGetFullPath(LPCSTR pszFile);
extern xbString xbEXPORT xbGetLongPath(LPCSTR pszFile);
extern xbString xbEXPORT xbGetShortPath(LPCSTR pszFile);
extern xbString xbEXPORT xbGetUncPath(LPCSTR pszFile,xbOpMode opm =xbOp_Required);
extern xbString xbEXPORT xbGetLocalPath(LPCSTR pszFile,xbOpMode opm =xbOp_Required);
extern bool xbEXPORT xbCopyFile(LPCSTR pszSrce,LPCSTR pszDest,bool bFailIfExist,xbOpMode opm =xbOp_Required);
extern bool xbEXPORT xbMoveFile(LPCSTR pszSrce,LPCSTR pszDest,xbOpMode opm =xbOp_Required);
extern bool xbEXPORT xbDeleteFile(LPCSTR pszSrce,xbOpMode opm =xbOp_Optional);
extern bool xbEXPORT xbDeleteDir(LPCSTR pszSrce,xbOpMode opm =xbOp_Optional);

extern xbString	xbEXPORT xbGetFilePath(const xbString &file,const xbString &dfltpath,const xbString &dfltext);

extern bool xbEXPORT xbSetCurrentDir(const xbString &dir,xbOpMode opm =xbOp_Required);
extern xbString xbEXPORT xbGetCurrentDir(bool bEndSlash = true); 
extern xbString xbEXPORT xbGetSystemDir(bool bEndSlash = true); 
extern xbString xbEXPORT xbGetWindowsDir(bool bEndSlash = true); 
extern xbString xbEXPORT xbGetTempDir(bool bEndSlash = true); 
extern xbString xbEXPORT xbGetTempFile(const char *pszPrefix = NULL, uint uUnique = 0, const char *pszDir = NULL);
extern xbString xbEXPORT xbGetUserName();
extern xbString xbEXPORT xbGetComputerName();
extern bool		xbEXPORT xbGetComputerCode( DWORD* id );
extern xbString xbEXPORT xbGetShellFolder(int nFolder,bool bNoEndSlash = true,bool bCreate = true); //for nFolder see : SHGetSpecialFolderLocation
extern xbString xbEXPORT xbGetXdcPrgDir(bool bEndSlash = true,LPCSTR pAppDir=NULL,bool bCreate = true);
extern xbString xbEXPORT xbGetXdcPrgDataDir(bool bEndSlash = true,LPCSTR pAppDir=NULL,bool bCreate = true);
extern xbString xbEXPORT xbGetXdcMenuDir(bool bEndSlash = true,LPCSTR pAppDir=NULL,bool bCreate = true);

extern xbString	xbEXPORT xbPathSlash(const xbString &path); //os dep: Aslash for win, slash for linux

enum xbGetUserInfoType
{
	xbGetUserInfoType_Name,
	xbGetUserInfoType_Domain,
	xbGetUserInfoType_OtherDomain,
	xbGetUserInfoType_LogonServer,
	xbGetUserInfoType_Full
};

extern xbString xbEXPORT xbGetUserGroupsLocal();
extern xbString xbEXPORT xbGetUserGroups();
extern xbString xbEXPORT xbGetUserInfo(xbGetUserInfoType infoType);
extern xbString xbEXPORT xbGetUserDomain();
extern xbString xbEXPORT xbGetUserDomainController();

extern xbString xbEXPORT xbEndSlash(LPCSTR pszSrce,bool bAslash = true);
extern xbString xbEXPORT xbNoEndSlash(LPCSTR pszSrce);

extern bool xbEXPORT xbCreateShortCut(const xbString &path,const xbString &desc,const xbString &target,const xbString &arg,xbRefPtr<IShellLink> *pprShLink = NULL, DWORD dwClsContext = CLSCTX_ALL); //for nFolder see : SHGetSpecialFolderLocation

class xbEXPORT xbFileAttr
{
public:
	xbFileAttr()
	{
		m_attr = -1;
	}
	xbFileAttr(ulong attr)
	{
		m_attr = attr;
	}
	xbFileAttr(const xbString &file,xbOpMode opm =xbOp_Required);

	xbFileAttr(const xbFileAttr &attr)
	{
		m_attr = attr.m_attr;
	}
	xbFileAttr &operator=(const xbFileAttr &attr)
	{
		m_attr = attr.m_attr;
		return *this;
	}
	xbFileAttr &operator=(ulong attr)
	{
		m_attr = attr;
		return *this;
	}
	bool Set(const xbString &file,xbOpMode opm =xbOp_Required);

	operator ulong() const {return m_attr;}

	bool IsEmpty() const {return m_attr == -1;}
	bool IsValid() const {return m_attr != -1;}

	bool operator==(const xbFileAttr &attr) const {return m_attr == attr.m_attr;}
	bool operator!=(const xbFileAttr &attr) const {return m_attr != attr.m_attr;}
	bool operator&(ulong attr) const {return m_attr != -1 && (m_attr & attr) != 0;}
	bool HasAll(ulong attr) const {return m_attr != -1 && (m_attr & attr) != attr;}

	bool IsDir() const {return m_attr != -1 && (m_attr & FILE_ATTRIBUTE_DIRECTORY) != 0;}
	bool IsArchive() const {return m_attr != -1 && (m_attr & FILE_ATTRIBUTE_ARCHIVE) != 0;}
	bool IsCompressed() const {return m_attr != -1 && (m_attr & FILE_ATTRIBUTE_COMPRESSED) != 0;}
	bool IsEncrypted() const {return m_attr != -1 && (m_attr & FILE_ATTRIBUTE_ENCRYPTED) != 0;}
	bool IsHidden() const {return m_attr != -1 && (m_attr & FILE_ATTRIBUTE_HIDDEN) != 0;}
	bool IsNormal() const {return m_attr != -1 && (m_attr & FILE_ATTRIBUTE_NORMAL) != 0;}
	bool IsOffLine() const {return m_attr != -1 && (m_attr & FILE_ATTRIBUTE_OFFLINE) != 0;}
	bool IsReadOnly() const {return m_attr != -1 && (m_attr & FILE_ATTRIBUTE_READONLY) != 0;}
	bool IsTemporary() const {return m_attr != -1 && (m_attr & FILE_ATTRIBUTE_TEMPORARY) != 0;}
protected:
	ulong m_attr;
};

class xbEXPORT xbDirEnum
{
public:
	xbDirEnum()
	{
		m_pParent = NULL;
		m_dh = INVALID_HANDLE_VALUE;
		m_attrExcl = 0;
		m_attrIncl = -1;
		m_bDataValid = false;
		m_hr = E_FAIL;
	}
	xbDirEnum(const xbString &path,xbOpMode opm =xbOp_Required)
	{
		m_pParent = NULL;
		m_dh = INVALID_HANDLE_VALUE;
		m_attrExcl = 0;
		m_attrIncl = -1;
		m_bDataValid = false;
		m_hr = E_FAIL;
		Open(path,opm);
	}
	xbDirEnum(const xbDirEnum *pParent, const xbString &path,xbOpMode opm =xbOp_Required)
	{
		m_pParent = NULL;
		m_dh = INVALID_HANDLE_VALUE;
		m_attrExcl = 0;
		m_attrIncl = -1;
		m_bDataValid = false;
		m_hr = E_FAIL;
		Open(pParent,path,opm);
	}
	virtual ~xbDirEnum()
	{
		eProtect(Close());
	}
	bool IsOpened() const {return m_path.IsValid();}
	bool IsClosed() const {return m_path.IsEmpty();}

	bool Open(const xbDirEnum *pParent,const xbString &path,xbOpMode opm =xbOp_Required);
	bool Open(const xbString &path,xbOpMode opm =xbOp_Required)
	{
		return Open(NULL,path,opm);
	}
	void Reset();
	void Close();

	void ResetAttrExt() {ResetAttr();ResetExt();}
	void ResetAttr();
	void ExcludeAttr(ulong attr);
	void IncludeAttr(ulong attr);
	void ResetExt();
	void ExcludeExt(const xbString &ext);
	void IncludeExt(const xbString &ext);
	void ExcludeExt(const xbArray<xbString> &ext);
	void IncludeExt(const xbArray<xbString> &ext);

	bool Next(xbString *pFileName = NULL,bool bReqIfFirst = false);

	xbString GetName() const;
	xbString GetShortName() const;
	xbString GetPath() const;
	xbString GetShortPath() const;
	xbString GetFullPath() const;
	xbString GetFullShortPath() const;
	xbFileAttr GetAttr() const;
	xbDateTime	GetCreationDate() const;
	xbDateTime	GetAccessDate() const;
	xbDateTime	GetWriteDate() const;
	FILETIME	GetCreationFT() const;
	FILETIME	GetAccessFT() const;
	FILETIME	GetWriteFT() const;
	uint64	GetFileSize() const;

	bool IsAttrOk(ulong attr) const;
	bool IsExtOk(const xbString &ext) const;
	bool IsFileOk(ulong attr,const xbString &fname) const;

	HRESULT	GetError() const {return m_hr;}
	bool	IsEODerror() const {return m_hr == ERROR_NO_MORE_FILES;}
	bool	IsEOD() const {return !m_bDataValid;}

	xbString GetDir() const;
	xbString GetShortDir() const;

	void	CheckExt(xbArray<xbString> &ext,xbArray<xbString> &files,ulong &attr);
protected:
	xbString		m_path,m_dir;
	mutable xbString m_shortDir;
	bool			m_bDataValid;
	WIN32_FIND_DATA	m_data;
	HANDLE			m_dh;
	ulong			m_attrExcl,m_attrIncl;
	xbArray<xbString> m_extExcl,m_extIncl;
	xbArray<xbString> m_fileExcl,m_fileIncl;
	const xbDirEnum	*m_pParent;

	HRESULT			m_hr;
};

class xbEXPORT xbCRC32
{
protected:
		DWORD	m_crc	;
public:
				xbCRC32	( );
		void	Reset	( );
		void	Push	( const byte *src, uint count );
		DWORD	GetCRC	( ) { return m_crc^0xFFFFFFFF; }

//		void	FromStream( stream& st );
};

enum xbLaunchMode
{
	//Valid for shellexecute	: 0xFF000000
	xbLaunch_ShModeMask			= 0xFF000000,
	xbLaunch_ShellExecute		= 0x80000000,
	xbLaunch_WaitDDEend			= 0x40000000, //if dde supported

	//Valid for !shellexecute	: 0x00FF0000 (CreateProcess)
	xbLaunch_CpModeMask			= 0x00FF0000,
	xbLaunch_NoDetach			= 0x00800000,
	xbLaunch_NewConsole			= 0x00400000,

	//Valid for both			: 0x0000FF00
	xbLaunch_BothModeMask		= 0x0000FF00,
	xbLaunch_WaitEnd			= 0x00008000, //CAUTION: return in this case is process exit code

	//Open mode valid for both	: 0x0000000F
	xbLaunch_OpenModeMask		= 0x0000000F,
	xbLaunch_Hide				= 0x00000000,
	xbLaunch_Minimize			= 0x00000002,
	xbLaunch_Maximize			= 0x00000003,
	xbLaunch_ShowNA				= 0x00000004,
	xbLaunch_ShowMinNA			= 0x00000005,
	xbLaunch_Show				= 0x0000000F
};
HANDLE xbEXPORT xbLaunchFile(ulong mode, xbHWND hWinParent, const xbString &sExe, const xbString &sParam, const xbString &sDir);
ulong xbEXPORT xbWaitProcessEndExt(HANDLE hProcess,int millisecWaitTime = 60000,bool bProcessMsg = true); // impl in xbSync.h
ulong xbEXPORT xbWaitProcessEnd(HANDLE hProcess,int millisecWaitTime = 60000); // impl in xbSync.h

#endif
