#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/utime.h>
#include <sys/stat.h>
#include <direct.h>
#include <io.h>
#include <windows.h>

void
	Recursive_Copy(
		const char* source_path,
		const char* dest_path,
		int mask_count,
		const char* masks[],
		bool delete_ok
	)
{
	//
	//------------------------------------------------
	// Get the mask to search in the current directory
	//------------------------------------------------
	//
	char local_mask[200];
	printf("Copying %s\n", source_path);
	strcpy(local_mask, source_path);
	strcat(local_mask, "\\*.*");
	bool dest_exists = !_access(dest_path, 0);

	//
	//------------------------------------------------
	// Spin through and find all non directory objects
	//------------------------------------------------
	//
	WIN32_FIND_DATA data;
	HANDLE handle = FindFirstFile(local_mask, &data);
	if (handle != INVALID_HANDLE_VALUE)
	{
		do
		{
			if (!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
			{

				//
				//-------------------------------------------
				// Create the official from and to file names
				//-------------------------------------------
				//
				char source[200];
				strcpy(source, source_path);
				strcat(source, "\\");
				strcat(source, data.cFileName);
				char dest[200];
				strcpy(dest, dest_path);
				strcat(dest, "\\");
				strcat(dest, data.cFileName);

				//
				//-----------------------------------------------------------------
				// See if we can get a handle to the destination file.  If so, lets
				// check its data before doing the copy
				//-----------------------------------------------------------------
				//
				bool copy = true;
				struct _stat dest_info;
				if (!_stat(dest, &dest_info))
				{
					struct _stat src_info;
					_stat(source, &src_info);
					copy = (src_info.st_mtime > dest_info.st_mtime);
					if (copy && !(dest_info.st_mode&_S_IWRITE))
						_chmod(dest, _S_IWRITE|_S_IREAD);
				}

				//
				//---------------------------
				// Copy the file if indicated
				//---------------------------
				//
				if (copy)
				{
					if (!dest_exists)
					{
						_mkdir(dest_path);
						dest_exists = true;
					}
					CopyFile(source, dest, FALSE);
				}

				//
				//---------------------------------------------------------------
				// Otherwise, update the read/write flag of the destination if it
				// is different from the source
				//---------------------------------------------------------------
				//
				else
				{
					int dest_mode = dest_info.st_mode&(_S_IWRITE|_S_IREAD);
					int src_mode = 
						(data.dwFileAttributes&FILE_ATTRIBUTE_READONLY) ?
							_S_IREAD : _S_IREAD|_S_IWRITE;
					if (dest_mode != src_mode)
						_chmod(dest, src_mode);
				}
			}
		} while (FindNextFile(handle, &data));
	}
	FindClose(handle);

	//
	//---------------------
	// Look for directories
	//---------------------
	//
	handle = FindFirstFile(local_mask, &data);
	if (handle != INVALID_HANDLE_VALUE)
	{
		do
		{
			if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			{
				if (
					!strcmp(data.cFileName, ".")
					 || !strcmp(data.cFileName, "..")
				)
					continue;
				int i;
				for (i=0; i<mask_count; ++i)
				{
					if (!_stricmp(data.cFileName, masks[i]))
						break;
				}
				if (i<mask_count)
					continue;
				char source[200];
				strcpy(source, source_path);
				strcat(source, "\\");
				strcat(source, data.cFileName);
				char dest[200];
				strcpy(dest, dest_path);
				strcat(dest, "\\");
				strcat(dest, data.cFileName);
				if (!dest_exists)
				{
					_mkdir(dest_path);
					dest_exists = true;
				}
				Recursive_Copy(source, dest, mask_count, masks, delete_ok);
			}
		} while (FindNextFile(handle, &data));
	}
	FindClose(handle);


	//
	//--------------------------------------------
	// Spin through and delete all obsolete things
	//--------------------------------------------
	//
	if (delete_ok)
	{
		strcpy(local_mask, dest_path);
		strcat(local_mask, "\\*.*");
		handle = FindFirstFile(local_mask, &data);
		if (handle != INVALID_HANDLE_VALUE)
		{
			do
			{
				if (!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
				{

					//
					//------------------------------
					// Create the official from name
					//------------------------------
					//
					char source[200];
					strcpy(source, source_path);
					strcat(source, "\\");
					strcat(source, data.cFileName);
					char dest[200];
					strcpy(dest, dest_path);
					strcat(dest, "\\");
					strcat(dest, data.cFileName);

					//
					//-----------------------------------------------------------------
					// See if we can get a handle to the destination file.  If so, lets
					// check its data before doing the copy
					//-----------------------------------------------------------------
					//
					struct _stat src_info;
					if (_stat(source, &src_info))
					{
						printf("Deleting %s\n", dest);
						_chmod(dest, _S_IWRITE|_S_IREAD);
						_unlink(dest);
					}
				}
			} while (FindNextFile(handle, &data));
		}
		FindClose(handle);
	}
}

int
	main(
		int argc,
		const char* argv[]
	)
{
	if (argc < 3 || argc > 4)
	{
		printf("Usage: CopyProject [-nodelete] <srcpath> <destpath>\n");
		return 1;
	}

	//
	//-------------------------------
	// First deal with the code files
	//-------------------------------
	//
	const char *masks[]={
		"Debug",
		"Armor",
		"Profile",
		"Release"
	};
	int source_base = 1;
	if (argc == 4)
		++source_base;
	Recursive_Copy(
		argv[source_base],
		argv[source_base+1],
		sizeof(masks)/sizeof(*masks),
		masks,
		argc == 3
	);
	return 0;
}
