/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 1, or (at your option)
** any later version.

** This program 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 General Public License for more details.
  
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
* Author : V.Antonevich <v_antonevich@hotmail.com> --- November 2000
*/

/*
* FileViewWatcher.cpp --- file modification watcher thread
*/

#include "stdafx.h"
#include "wincvs.h"
#include "FileViewWatcher.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

UINT KoWatcher::Run()
{
	CWincvsApp* app = (CWincvsApp *)AfxGetApp();

	for(;;)
	{
		// if a lot of changes happen suddenly in the folder, we
		// don't want WinCvs to die under the WM_FILECHANGE message,
		// so we need to slow down a bit.
		Sleep(app->m_isBackgroundProcess ? 2000 : 200);

		DWORD dw = WaitForMultipleObjects(m_count, m_handles, FALSE, INFINITE);
		switch (dw)
		{
			case WAIT_OBJECT_0 :
			{
				// process signal to start watching
				StopWatch();
				StartWatch();
				m_eventStartWatching.Unlock();
				break;
			}
			case WAIT_OBJECT_0 + 1 :
			{
				// process signal to terminate
				StopWatch();
				delete this;
				return 0;
			}
			case WAIT_OBJECT_0 + 2 :
			{
				// process file change signal
				StopWatch();
				PostMessage(m_hWnd, WM_FILECHANGE, 0, 0);
				break;
			}

		}
	}
	return 0;
}

bool KoWatcher::StartWatch()
{
	// retrieve parameters first
	TCHAR path[_MAX_PATH];
	bool isRecursive;
	m_section.Lock();
	lstrcpyn(path, m_path, _MAX_PATH);
	isRecursive = m_isRecursive;
	m_section.Unlock();

	// start watching
	HANDLE h =	FindFirstChangeNotification( 
					path, 
					isRecursive,
					FILE_NOTIFY_CHANGE_FILE_NAME |
					FILE_NOTIFY_CHANGE_DIR_NAME |
					//FILE_NOTIFY_CHANGE_SIZE |
					FILE_NOTIFY_CHANGE_LAST_WRITE |
					//FILE_NOTIFY_CHANGE_LAST_ACCESS |
#if _MSC_VER >= 1200
					//FILE_NOTIFY_CHANGE_CREATION | (makes Win98 fails)
#endif
					//FILE_NOTIFY_CHANGE_SECURITY |
					FILE_NOTIFY_CHANGE_ATTRIBUTES
				);
	if (h != INVALID_HANDLE_VALUE)
	{
		m_handles[2] = h;
		m_count = 3;
	}
	return m_count == 3;
}

// stops monitoring
void KoWatcher::StopWatch()
{
	if (m_count == 3 && m_handles[2] != INVALID_HANDLE_VALUE)
	{
		// reset and close the handle
		FindNextChangeNotification(m_handles[2]); 
		FindCloseChangeNotification(m_handles[2]);
		m_handles[2] = INVALID_HANDLE_VALUE;
		m_count = 2;
	}
}
