/*
 * Copyright (c) 2021 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include <zephyr/logging/log_internal.h>
#include <zephyr/logging/log_ctrl.h>
#include <zephyr/syscall_handler.h>

/* Implementation of functions related to controlling logging sources and backends:
 * - getting/setting source details like name, filtering
 * - controlling backends filtering
 */

/** @brief Get compiled level of the log source.
 *
 * @param source_id Source ID.
 * @return Level.
 */
static inline uint8_t log_compiled_level_get(uint32_t source_id)
{
	return __log_const_start[source_id].level;
}

void z_log_runtime_filters_init(void)
{
	/*
	 * Initialize aggregated runtime filter levels (no backends are
	 * attached yet, so leave backend slots in each dynamic filter set
	 * alone for now).
	 *
	 * Each log source's aggregated runtime level is set to match its
	 * compile-time level. When backends are attached later on in
	 * log_init(), they'll be initialized to the same value.
	 */
	for (int i = 0; i < z_log_sources_count(); i++) {
		uint32_t *filters = z_log_dynamic_filters_get(i);
		uint8_t level = log_compiled_level_get(i);

		level = MAX(level, CONFIG_LOG_OVERRIDE_LEVEL);
		LOG_FILTER_SLOT_SET(filters,
				    LOG_FILTER_AGGR_SLOT_IDX,
				    level);
	}
}

uint32_t log_src_cnt_get(uint32_t domain_id)
{
	return z_log_sources_count();
}

/** @brief Get name of the log source.
 *
 * @param source_id Source ID.
 * @return Name.
 */
static inline const char *log_name_get(uint32_t source_id)
{
	return __log_const_start[source_id].name;
}

const char *log_source_name_get(uint32_t domain_id, uint32_t src_id)
{
	return src_id < z_log_sources_count() ? log_name_get(src_id) : NULL;
}

static uint32_t max_filter_get(uint32_t filters)
{
	uint32_t max_filter = LOG_LEVEL_NONE;
	int first_slot = LOG_FILTER_FIRST_BACKEND_SLOT_IDX;
	int i;

	for (i = first_slot; i < LOG_FILTERS_NUM_OF_SLOTS; i++) {
		uint32_t tmp_filter = LOG_FILTER_SLOT_GET(&filters, i);

		if (tmp_filter > max_filter) {
			max_filter = tmp_filter;
		}
	}

	return max_filter;
}

uint32_t z_impl_log_filter_set(struct log_backend const *const backend,
			       uint32_t domain_id, int16_t source_id,
			       uint32_t level)
{
	__ASSERT_NO_MSG(source_id < (int16_t)z_log_sources_count());

	if (IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING)) {
		uint32_t new_aggr_filter;

		uint32_t *filters = z_log_dynamic_filters_get(source_id);

		if (backend == NULL) {
			struct log_backend const *iter_backend;
			uint32_t max = 0U;
			uint32_t current;

			for (int i = 0; i < log_backend_count_get(); i++) {
				iter_backend = log_backend_get(i);
				current = log_filter_set(iter_backend,
							 domain_id,
							 source_id, level);
				max = MAX(current, max);
			}

			level = max;
		} else {
			uint32_t max = log_filter_get(backend, domain_id,
						      source_id, false);

			level = MIN(level, MAX(max, CONFIG_LOG_OVERRIDE_LEVEL));

			LOG_FILTER_SLOT_SET(filters,
					    log_backend_id_get(backend),
					    level);

			/* Once current backend filter is updated recalculate
			 * aggregated maximal level
			 */
			new_aggr_filter = max_filter_get(*filters);

			LOG_FILTER_SLOT_SET(filters,
					    LOG_FILTER_AGGR_SLOT_IDX,
					    new_aggr_filter);
		}
	}

	return level;
}

#ifdef CONFIG_USERSPACE
uint32_t z_vrfy_log_filter_set(struct log_backend const *const backend,
			    uint32_t domain_id,
			    int16_t src_id,
			    uint32_t level)
{
	Z_OOPS(Z_SYSCALL_VERIFY_MSG(backend == NULL,
		"Setting per-backend filters from user mode is not supported"));
	Z_OOPS(Z_SYSCALL_VERIFY_MSG(domain_id == CONFIG_LOG_DOMAIN_ID,
		"Invalid log domain_id"));
	Z_OOPS(Z_SYSCALL_VERIFY_MSG(src_id < (int16_t)z_log_sources_count(),
		"Invalid log source id"));
	Z_OOPS(Z_SYSCALL_VERIFY_MSG(
		(level <= LOG_LEVEL_DBG),
		"Invalid log level"));

	return z_impl_log_filter_set(NULL, domain_id, src_id, level);
}
#include <syscalls/log_filter_set_mrsh.c>
#endif

static void backend_filter_set(struct log_backend const *const backend,
			       uint32_t level)
{
	if (IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING)) {
		for (int i = 0; i < z_log_sources_count(); i++) {
			log_filter_set(backend, CONFIG_LOG_DOMAIN_ID, i, level);
		}
	}
}

const struct log_backend *log_backend_get_by_name(const char *backend_name)
{
	const struct log_backend *ptr = __log_backends_start;

	while (ptr < __log_backends_end) {
		if (strcmp(backend_name, ptr->name) == 0) {
			return ptr;
		}
		ptr++;
	}
	return NULL;
}

void log_backend_enable(struct log_backend const *const backend,
			void *ctx,
			uint32_t level)
{
	/* As first slot in filtering mask is reserved, backend ID has offset.*/
	uint32_t id = LOG_FILTER_FIRST_BACKEND_SLOT_IDX;

	id += backend - log_backend_get(0);

	log_backend_id_set(backend, id);
	backend_filter_set(backend, level);
	log_backend_activate(backend, ctx);

	z_log_notify_backend_enabled();
}

void log_backend_disable(struct log_backend const *const backend)
{
	log_backend_deactivate(backend);
	backend_filter_set(backend, LOG_LEVEL_NONE);
}

uint32_t log_filter_get(struct log_backend const *const backend,
			uint32_t domain_id, int16_t source_id, bool runtime)
{
	__ASSERT_NO_MSG(source_id < (int16_t)z_log_sources_count());

	if (IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) && runtime) {
		if (source_id < 0) {
			return LOG_LEVEL_DBG;
		}

		uint32_t *filters = z_log_dynamic_filters_get(source_id);

		return LOG_FILTER_SLOT_GET(filters,
					   log_backend_id_get(backend));
	}

	return log_compiled_level_get(source_id);
}
