#ifndef __Traversal_h__
#define __Traversal_h__

#include "BGDNet.h"
#include "FileListing.h"
#include "FileAttrUpdate.h"

class CTraversalProgressDlg;

//
// Класс "Обход файловой системы"
// Предназначен для обхода сети, сервера, тома или каталога в отдельном потоке.
//
class CFileSystemTraversal
{
public:

  CFileSystemTraversal( void );

  virtual ~CFileSystemTraversal( void );

  void run( const char* startPath, bool recursive, CWnd* pParentWnd = NULL );
  // Запускает обход. startPath - указатель на строку, содержащую
  // путь к серверу, тому или каталогу, начиная с которого необходимо
  // осуществить обход. Если startPath указывает на пустую строку,
  // осуществляется обход всей сети. recursive - признак рекурсивного
  // обхода подкаталогов. pParentWnd - указатель на родительское окно,
  // которое запускает обход.

  void stop( void );
  // Останавливает обход и ожидает его завершения обхода.

  CString curDir( void ) const;
  // Возвращает строку, содержащую текущий каталог.

  LONG fileCount( void ) const;
  // Возвращает количество обработанных файлов.

  LONG dirCount( void ) const;
  // Возвращает количество обработанных каталогов.

  LONG errCount( void ) const;
  // Возвращает количество возникших ошибок.

protected:

  virtual void onFinished( void );
  // Вызывается по окончании обхода.

  virtual void onServer( BGDNet::Server* pSrv );
  // Вызывается для каждого сервера. По молчанию не делает ничего.

  virtual void onVolume( BGDNet::Volume* pVol );
  // Вызывается для каждого тома. По молчанию не делает ничего.

  virtual void onDirectory( BGDNet::Directory* pDir );
  // Вызывается для каждого каталога. По молчанию не делает ничего.

  virtual void onFile( BGDNet::File* pFile );
  // Вызывается для каждого файла. По молчанию не делает ничего.

  virtual void onError( const CString& obj, const CString& e );
  // Вызывается при возникновении ошибок. obj - ссылка на строку, содержащую
  // название объекта, при обходе которого возникла ошибка. e - ссылка
  // на строку, описывающую ошибку. По молчанию не делает ничего.

private:

  static DWORD WINAPI traverseThread( LPVOID pParam );
  // Главная функция потока, в котором выполняется обход.

  void traverse( void );
  // Главная функция обхода.

  void traverseNetwork( void );
  // Обход всей сети.

  void traverseServer( const BGDNet::Server* pSrv );
  // Обход сервера. Возвращает false если обход был прерван.
  
  void traverseDir( BGDNet::Directory* pDir );
  // Обход каталога. Возвращает false если обход был прерван.

  CString m_startPath;
  // Строка, содержащая стартовый путь.

  CString m_curDir;
  // Строка, содержащая текущий каталог.

  LONG m_errCount;
  // Количество возникших ошибок.

  LONG m_fileCount;
  // Количество обработанных файлов.

  LONG m_dirCount;
  // Количество обработанных каталогов.

  mutable CRITICAL_SECTION m_cs;
  // Критическая секция, используемая для синхронизации

  HANDLE m_hThread;
  // Дескриптор потока

  LONG m_stopFlag;
  // Признак остановки обхода.

  CTraversalProgressDlg* m_pProgressDlg;
  // Указатель на диалог, отображающий прогресс обхода.

  bool m_isRecursive;
  // Признак рекурсивного обхода.
};

//
// Класс "Формирование списка файлов"
//
class CFileListingFormation : public CFileSystemTraversal
{
public:

  explicit CFileListingFormation( CFileListing* pList );
  // Конструктор. pList указывает на список файлов, который
  // будет формироваться.

protected:

  virtual void onFile( BGDNet::File* pFile );
  virtual void onError( const CString& obj, const CString& e );

  BGDNet::Context m_ctx;
  // Контекст, используемый для получения имен владельцев.

private:

  CFileListing* m_pList;
  // Указатель на формируемый список файлов.
};

//
// Класс "Изменение атрибутов файлов"
//
class CGlobalFileAttrUpdate : public CFileListingFormation
{
public:

  CGlobalFileAttrUpdate( CFileListing* pList, CFileAttrUpdate* pAttrUpdate );
  // Конструктор. pList указывает на список файлов, который
  // будет формироваться. pAttrUpdate указывает на необходимое
  // изменение атрибутов файлов.

protected:

  virtual void onFile( BGDNet::File* pFile );

private:

  CFileAttrUpdate* m_pAttrUpdate;
  // Указатель на необходимое изменение атрибутов файлов.
};

#endif //__Traversal_h__
