#include <sfdo-basedir.h>
#include <sfdo-desktop.h>
#include <stdlib.h>
#include <string.h>

#include "common/api.h"
#include "common/membuild.h"
#include "common/sized.h"
#include "sfdo-desktop/internal.h"

#define APPLICATIONS_SUFFIX "applications/"

SFDO_API struct sfdo_desktop_ctx *sfdo_desktop_ctx_create(struct sfdo_basedir_ctx *basedir_ctx) {
	struct sfdo_desktop_ctx *ctx = calloc(1, sizeof(*ctx));
	if (ctx == NULL) {
		return NULL;
	}

	logger_setup(&ctx->logger);

	if (basedir_ctx != NULL) {
		size_t n_dirs;
		const struct sfdo_string *data_dirs = sfdo_basedir_get_data_dirs(basedir_ctx, &n_dirs);

		size_t mem_size = 0;
		for (size_t i = 0; i < n_dirs; i++) {
			mem_size += data_dirs[i].len + SFDO_SIZED_LEN(APPLICATIONS_SUFFIX) + 1;
		}

		struct sfdo_string *dirs = calloc(n_dirs, sizeof(*dirs));
		if (dirs == NULL) {
			goto err;
		}

		struct sfdo_membuild mem_buf;
		if (!sfdo_membuild_setup(&mem_buf, mem_size)) {
			free(dirs);
			goto err;
		}

		for (size_t i = 0; i < n_dirs; i++) {
			const struct sfdo_string *data_dir = &data_dirs[i];
			dirs[i].data = sfdo_membuild_curr(&mem_buf);
			SFDO_MEMBUILD_ADD(
					&mem_buf, {data_dir->data, data_dir->len}, SFDO_SIZED_LIT(APPLICATIONS_SUFFIX));
			dirs[i].len = sfdo_membuild_nulterm(&mem_buf);
		}

		sfdo_membuild_validate(&mem_buf);

		ctx->default_basedirs = dirs;
		ctx->default_basedirs_mem = mem_buf.data;
		ctx->default_n_basedirs = n_dirs;
	}

	return ctx;

err:
	sfdo_desktop_ctx_destroy(ctx);
	return NULL;
}

SFDO_API void sfdo_desktop_ctx_destroy(struct sfdo_desktop_ctx *ctx) {
	if (ctx == NULL) {
		return;
	}

	free(ctx->default_basedirs);
	free(ctx->default_basedirs_mem);
	free(ctx);
}

SFDO_API void sfdo_desktop_ctx_set_log_handler(struct sfdo_desktop_ctx *ctx,
		enum sfdo_log_level level, sfdo_log_handler_func_t func, void *data) {
	logger_configure(&ctx->logger, level, func, data);
}
