/*
 * Copyright (c) 2018 Intel Corporation.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/ztest.h>
#include <stdio.h>
#include <limits.h>
#include <zephyr/sys/__assert.h>
#include <zephyr/fs/fs.h>
#include "test_common.h"

#ifndef PATH_MAX
#define PATH_MAX 4096
#endif

int test_rmdir(const char *dir_path);

int test_mkdir(const char *dir_path, const char *file)
{
	int res;
	struct fs_file_t filep;
	char file_path[PATH_MAX] = { 0 };

	fs_file_t_init(&filep);
	res = sprintf(file_path, "%s/%s", dir_path, file);
	__ASSERT_NO_MSG(res < sizeof(file_path));

	if (check_file_dir_exists(dir_path)) {
		TC_PRINT("[%s] exists, delete it\n", dir_path);
		if (test_rmdir(dir_path)) {
			TC_PRINT("Error deleting dir %s\n", dir_path);
			return TC_FAIL;
		}
	} else {
		TC_PRINT("Creating new dir %s\n", dir_path);
	}

	/* Verify fs_mkdir() */
	res = fs_mkdir(dir_path);
	if (res) {
		TC_PRINT("Error creating dir[%d]\n", res);
		return res;
	}

	res = fs_open(&filep, file_path, FS_O_CREATE | FS_O_RDWR);
	if (res) {
		TC_PRINT("Failed opening file [%d]\n", res);
		return res;
	}

	TC_PRINT("Testing write to file %s\n", file_path);
	res = test_file_write(&filep, "NOTHING");
	if (res) {
		fs_close(&filep);
		return res;
	}

	res = fs_close(&filep);
	if (res) {
		TC_PRINT("Error closing file [%d]\n", res);
		return res;
	}

	TC_PRINT("Created dir %s!\n", dir_path);

	return res;
}

int test_lsdir(const char *path)
{
	int res;
	struct fs_dir_t dirp;
	struct fs_dirent entry;

	TC_PRINT("\nlsdir tests:\n");

	fs_dir_t_init(&dirp);

	/* Verify fs_opendir() */
	res = fs_opendir(&dirp, path);
	if (res) {
		TC_PRINT("Error opening dir %s [%d]\n", path, res);
		return res;
	}

	TC_PRINT("\nListing dir %s:\n", path);
	for (;;) {
		/* Verify fs_readdir() */
		res = fs_readdir(&dirp, &entry);

		/* entry.name[0] == 0 means end-of-dir */
		if (res || entry.name[0] == 0) {
			break;
		}

		if (entry.type == FS_DIR_ENTRY_DIR) {
			TC_PRINT("[DIR ] %s\n", entry.name);
		} else {
			TC_PRINT("[FILE] %s (size = %zu)\n",
				entry.name, entry.size);
		}
	}

	/* Verify fs_closedir() */
	fs_closedir(&dirp);

	return res;
}

int test_rmdir(const char *dir_path)
{
	int res;
	struct fs_dir_t dirp;
	static struct fs_dirent entry;

	fs_dir_t_init(&dirp);

	if (!check_file_dir_exists(dir_path)) {
		TC_PRINT("%s doesn't exist\n", dir_path);
		return TC_FAIL;
	}

	res = fs_opendir(&dirp, dir_path);
	if (res) {
		TC_PRINT("Error opening dir[%d]\n", res);
		return res;
	}

	TC_PRINT("\nRemoving files and sub directories in %s\n", dir_path);
	for (;;) {
		char file_path[PATH_MAX] = { 0 };

		res = fs_readdir(&dirp, &entry);

		/* entry.name[0] == 0 means end-of-dir */
		if (res || entry.name[0] == 0) {
			break;
		}

		/* Delete file or sub directory */
		sprintf(file_path, "%s/%s", dir_path, entry.name);
		__ASSERT_NO_MSG(res < sizeof(file_path));
		TC_PRINT("Removing %s\n", file_path);

		res = fs_unlink(file_path);
		if (res) {
			TC_PRINT("Error deleting file/dir [%d]\n", res);
			fs_closedir(&dirp);
			return res;
		}
	}

	fs_closedir(&dirp);

	/* Verify fs_unlink() */
	res = fs_unlink(dir_path);
	if (res) {
		TC_PRINT("Error removing dir [%d]\n", res);
		return res;
	}

	TC_PRINT("Removed dir %s!\n", dir_path);

	return res;
}
