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

#include <errno.h>
#include <zephyr/kernel.h>
#include <limits.h>
#include <zephyr/posix/unistd.h>
#include <zephyr/posix/dirent.h>
#include <string.h>
#include <zephyr/sys/fdtable.h>
#include <zephyr/posix/sys/stat.h>
#include <zephyr/posix/fcntl.h>
#include <zephyr/fs/fs.h>

BUILD_ASSERT(PATH_MAX >= MAX_FILE_NAME, "PATH_MAX is less than MAX_FILE_NAME");

struct posix_fs_desc {
	union {
		struct fs_file_t file;
		struct fs_dir_t	dir;
	};
	bool is_dir;
	bool used;
};

static struct posix_fs_desc desc_array[CONFIG_POSIX_MAX_OPEN_FILES];

static struct fs_dirent fdirent;
static struct dirent pdirent;

static struct fd_op_vtable fs_fd_op_vtable;

static struct posix_fs_desc *posix_fs_alloc_obj(bool is_dir)
{
	int i;
	struct posix_fs_desc *ptr = NULL;
	unsigned int key = irq_lock();

	for (i = 0; i < CONFIG_POSIX_MAX_OPEN_FILES; i++) {
		if (desc_array[i].used == false) {
			ptr = &desc_array[i];
			ptr->used = true;
			ptr->is_dir = is_dir;
			break;
		}
	}
	irq_unlock(key);

	return ptr;
}

static inline void posix_fs_free_obj(struct posix_fs_desc *ptr)
{
	ptr->used = false;
}

static int posix_mode_to_zephyr(int mf)
{
	int mode = (mf & O_CREAT) ? FS_O_CREATE : 0;

	mode |= (mf & O_APPEND) ? FS_O_APPEND : 0;

	switch (mf & O_ACCMODE) {
	case O_RDONLY:
		mode |= FS_O_READ;
		break;
	case O_WRONLY:
		mode |= FS_O_WRITE;
		break;
	case O_RDWR:
		mode |= FS_O_RDWR;
		break;
	default:
		break;
	}

	return mode;
}

/**
 * @brief Open a file.
 *
 * See IEEE 1003.1
 */
int open(const char *name, int flags, ...)
{
	int rc, fd;
	struct posix_fs_desc *ptr = NULL;
	int zmode = posix_mode_to_zephyr(flags);

	if (zmode < 0) {
		return zmode;
	}

	fd = z_reserve_fd();
	if (fd < 0) {
		return -1;
	}

	ptr = posix_fs_alloc_obj(false);
	if (ptr == NULL) {
		z_free_fd(fd);
		errno = EMFILE;
		return -1;
	}

	fs_file_t_init(&ptr->file);

	rc = fs_open(&ptr->file, name, zmode);

	if (rc < 0) {
		posix_fs_free_obj(ptr);
		z_free_fd(fd);
		errno = -rc;
		return -1;
	}

	z_finalize_fd(fd, ptr, &fs_fd_op_vtable);

	return fd;
}

#if !defined(CONFIG_NEWLIB_LIBC) && !defined(CONFIG_PICOLIBC)
FUNC_ALIAS(open, _open, int);
#endif

static int fs_close_vmeth(void *obj)
{
	struct posix_fs_desc *ptr = obj;
	int rc;

	rc = fs_close(&ptr->file);
	posix_fs_free_obj(ptr);

	return rc;
}

static int fs_ioctl_vmeth(void *obj, unsigned int request, va_list args)
{
	int rc = 0;
	struct posix_fs_desc *ptr = obj;

	switch (request) {
	case ZFD_IOCTL_LSEEK: {
		off_t offset;
		int whence;

		offset = va_arg(args, off_t);
		whence = va_arg(args, int);

		rc = fs_seek(&ptr->file, offset, whence);
		if (rc == 0) {
			rc = fs_tell(&ptr->file);
		}
		break;
	}

	default:
		errno = EOPNOTSUPP;
		return -1;
	}

	if (rc < 0) {
		errno = -rc;
		return -1;
	}

	return rc;
}

/**
 * @brief Write to a file.
 *
 * See IEEE 1003.1
 */
static ssize_t fs_write_vmeth(void *obj, const void *buffer, size_t count)
{
	ssize_t rc;
	struct posix_fs_desc *ptr = obj;

	rc = fs_write(&ptr->file, buffer, count);
	if (rc < 0) {
		errno = -rc;
		return -1;
	}

	return rc;
}

/**
 * @brief Read from a file.
 *
 * See IEEE 1003.1
 */
static ssize_t fs_read_vmeth(void *obj, void *buffer, size_t count)
{
	ssize_t rc;
	struct posix_fs_desc *ptr = obj;

	rc = fs_read(&ptr->file, buffer, count);
	if (rc < 0) {
		errno = -rc;
		return -1;
	}

	return rc;
}

static struct fd_op_vtable fs_fd_op_vtable = {
	.read = fs_read_vmeth,
	.write = fs_write_vmeth,
	.close = fs_close_vmeth,
	.ioctl = fs_ioctl_vmeth,
};

/**
 * @brief Open a directory stream.
 *
 * See IEEE 1003.1
 */
DIR *opendir(const char *dirname)
{
	int rc;
	struct posix_fs_desc *ptr;

	ptr = posix_fs_alloc_obj(true);
	if (ptr == NULL) {
		errno = EMFILE;
		return NULL;
	}

	fs_dir_t_init(&ptr->dir);

	rc = fs_opendir(&ptr->dir, dirname);
	if (rc < 0) {
		posix_fs_free_obj(ptr);
		errno = -rc;
		return NULL;
	}

	return ptr;
}

/**
 * @brief Close a directory stream.
 *
 * See IEEE 1003.1
 */
int closedir(DIR *dirp)
{
	int rc;
	struct posix_fs_desc *ptr = dirp;

	if (dirp == NULL) {
		errno = EBADF;
		return -1;
	}

	rc = fs_closedir(&ptr->dir);

	posix_fs_free_obj(ptr);

	if (rc < 0) {
		errno = -rc;
		return -1;
	}

	return 0;
}

/**
 * @brief Read a directory.
 *
 * See IEEE 1003.1
 */
struct dirent *readdir(DIR *dirp)
{
	int rc;
	struct posix_fs_desc *ptr = dirp;

	if (dirp == NULL) {
		errno = EBADF;
		return NULL;
	}

	rc = fs_readdir(&ptr->dir, &fdirent);
	if (rc < 0) {
		errno = -rc;
		return NULL;
	}

	if (fdirent.name[0] == 0) {
		/* assume end-of-dir, leave errno untouched */
		return NULL;
	}

	rc = strlen(fdirent.name);
	rc = (rc < MAX_FILE_NAME) ? rc : (MAX_FILE_NAME - 1);
	(void)memcpy(pdirent.d_name, fdirent.name, rc);

	/* Make sure the name is NULL terminated */
	pdirent.d_name[rc] = '\0';
	return &pdirent;
}

/**
 * @brief Rename a file.
 *
 * See IEEE 1003.1
 */
int rename(const char *old, const char *new)
{
	int rc;

	rc = fs_rename(old, new);
	if (rc < 0) {
		errno = -rc;
		return -1;
	}

	return 0;
}

/**
 * @brief Remove a directory entry.
 *
 * See IEEE 1003.1
 */
int unlink(const char *path)
{
	int rc;

	rc = fs_unlink(path);
	if (rc < 0) {
		errno = -rc;
		return -1;
	}
	return 0;
}

/**
 * @brief Get file status.
 *
 * See IEEE 1003.1
 */
int stat(const char *path, struct stat *buf)
{
	int rc;
	struct fs_statvfs stat;

	if (buf == NULL) {
		errno = EBADF;
		return -1;
	}

	rc = fs_statvfs(path, &stat);
	if (rc < 0) {
		errno = -rc;
		return -1;
	}

	buf->st_size = stat.f_bsize * stat.f_blocks;
	buf->st_blksize = stat.f_bsize;
	buf->st_blocks = stat.f_blocks;
	return 0;
}

/**
 * @brief Make a directory.
 *
 * See IEEE 1003.1
 */
int mkdir(const char *path, mode_t mode)
{
	int rc;

	ARG_UNUSED(mode);

	rc = fs_mkdir(path);
	if (rc < 0) {
		errno = -rc;
		return -1;
	}

	return 0;
}
