/*
 * Copyright (C) the libgit2 contributors. All rights reserved.
 *
 * This file is part of libgit2, distributed under the GNU GPL v2 with
 * a Linking Exception. For full terms see the included COPYING file.
 */
#define GIT__WIN32_NO_WRAP_DIR
#include "posix.h"

git__DIR *git__opendir(const char *dir)
{
	git_win32_path filter_w;
	git__DIR *new = NULL;
	size_t dirlen, alloclen;

	if (!dir || !git_win32__findfirstfile_filter(filter_w, dir))
		return NULL;

	dirlen = strlen(dir);

	if (GIT_ADD_SIZET_OVERFLOW(&alloclen, sizeof(*new), dirlen) ||
		GIT_ADD_SIZET_OVERFLOW(&alloclen, alloclen, 1) ||
		!(new = git__calloc(1, alloclen)))
		return NULL;

	memcpy(new->dir, dir, dirlen);

	new->h = FindFirstFileW(filter_w, &new->f);

	if (new->h == INVALID_HANDLE_VALUE) {
		giterr_set(GITERR_OS, "Could not open directory '%s'", dir);
		git__free(new);
		return NULL;
	}

	new->first = 1;
	return new;
}

int git__readdir_ext(
	git__DIR *d,
	struct git__dirent *entry,
	struct git__dirent **result,
	int *is_dir)
{
	if (!d || !entry || !result || d->h == INVALID_HANDLE_VALUE)
		return -1;

	*result = NULL;

	if (d->first)
		d->first = 0;
	else if (!FindNextFileW(d->h, &d->f)) {
		if (GetLastError() == ERROR_NO_MORE_FILES)
			return 0;
		giterr_set(GITERR_OS, "Could not read from directory '%s'", d->dir);
		return -1;
	}

	/* Convert the path to UTF-8 */
	if (git_win32_path_to_utf8(entry->d_name, d->f.cFileName) < 0)
		return -1;

	entry->d_ino = 0;

	*result = entry;

	if (is_dir != NULL)
		*is_dir = ((d->f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);

	return 0;
}

struct git__dirent *git__readdir(git__DIR *d)
{
	struct git__dirent *result;
	if (git__readdir_ext(d, &d->entry, &result, NULL) < 0)
		return NULL;
	return result;
}

void git__rewinddir(git__DIR *d)
{
	git_win32_path filter_w;

	if (!d)
		return;

	if (d->h != INVALID_HANDLE_VALUE) {
		FindClose(d->h);
		d->h = INVALID_HANDLE_VALUE;
		d->first = 0;
	}

	if (!git_win32__findfirstfile_filter(filter_w, d->dir))
		return;

	d->h = FindFirstFileW(filter_w, &d->f);

	if (d->h == INVALID_HANDLE_VALUE)
		giterr_set(GITERR_OS, "Could not open directory '%s'", d->dir);
	else
		d->first = 1;
}

int git__closedir(git__DIR *d)
{
	if (!d)
		return 0;

	if (d->h != INVALID_HANDLE_VALUE) {
		FindClose(d->h);
		d->h = INVALID_HANDLE_VALUE;
	}

	git__free(d);
	return 0;
}

