/*
 * Copyright (c) 2021 Nordic Semiconductor
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include "mock_backend.h"
#include <ztest.h>
#include <zephyr/logging/log_core.h>

void mock_log_backend_reset(const struct log_backend *backend)
{
	struct mock_log_backend *mock = backend->cb->ctx;

	mock->msg_rec_idx = 0;
	mock->msg_proc_idx = 0;
	mock->do_check = true;
	mock->exp_drop_cnt = 0;
	mock->drop_cnt = 0;
	mock->panic = false;
}

void mock_log_backend_check_enable(const struct log_backend *backend)
{
	struct mock_log_backend *mock = backend->cb->ctx;

	mock->do_check = true;
}

void mock_log_backend_check_disable(const struct log_backend *backend)
{
	struct mock_log_backend *mock = backend->cb->ctx;

	mock->do_check = false;
}

void mock_log_backend_dummy_record(const struct log_backend *backend, int cnt)
{
	struct mock_log_backend *mock = backend->cb->ctx;

	for (int i = 0; i < cnt; i++) {
		mock->exp_msgs[mock->msg_rec_idx + i].check = false;
	}

	mock->msg_rec_idx += cnt;
}

void mock_log_backend_drop_record(const struct log_backend *backend, int cnt)
{
	struct mock_log_backend *mock = backend->cb->ctx;

	mock->exp_drop_cnt = cnt;
}

void mock_log_backend_generic_record(const struct log_backend *backend,
				     uint16_t source_id,
				     uint16_t domain_id,
				     uint8_t level,
				     log_timestamp_t timestamp,
				     const char *str,
				     uint8_t *data,
				     uint32_t data_len)
{
	if (backend->cb == NULL) {
		return;
	}

	if (IS_ENABLED(CONFIG_LOG_FRONTEND_ONLY) && timestamp != (log_timestamp_t)UINT32_MAX) {
		return;
	}

	struct mock_log_backend *mock = backend->cb->ctx;
	struct mock_log_backend_msg *exp = &mock->exp_msgs[mock->msg_rec_idx];

	exp->check = true;
	exp->timestamp = timestamp;
	exp->source_id = source_id;
	exp->domain_id = domain_id;
	exp->level = level;

	int len = strlen(str);

	__ASSERT_NO_MSG(len < sizeof(exp->str));

	memcpy(exp->str, str, len);
	exp->str[len] = 0;

	if (data_len <= sizeof(exp->data)) {
		memcpy(exp->data, data, data_len);
	}
	exp->data_len = data_len;

	mock->msg_rec_idx++;
}

void mock_log_backend_validate(const struct log_backend *backend, bool panic)
{
	struct mock_log_backend *mock = backend->cb->ctx;

	zassert_equal(mock->exp_drop_cnt, mock->drop_cnt,
		      "Got: %u, Expected: %u", mock->drop_cnt, mock->exp_drop_cnt);
	zassert_equal(mock->msg_rec_idx, mock->msg_proc_idx,
			"%p Recored:%d, Got: %d", mock, mock->msg_rec_idx, mock->msg_proc_idx);
	zassert_equal(mock->panic, panic, NULL);
}

struct test_str {
	char *str;
	int cnt;
};

static int out(int c, void *ctx)
{
	struct test_str *s = ctx;

	s->str[s->cnt++] = (char)c;

	return c;
}

static void process(const struct log_backend *const backend,
		union log_msg_generic *msg)
{
	struct mock_log_backend *mock = backend->cb->ctx;
	struct mock_log_backend_msg *exp = &mock->exp_msgs[mock->msg_proc_idx];

	if (!mock->do_check) {
		return;
	}

	mock->msg_proc_idx++;

	if (!exp->check) {
		return;
	}

	zassert_equal(msg->log.hdr.timestamp, exp->timestamp,
#if CONFIG_LOG_TIMESTAMP_64BIT
		      "Got: %llu, expected: %llu",
#else
		      "Got: %u, expected: %u",
#endif
		      msg->log.hdr.timestamp, exp->timestamp);
	zassert_equal(msg->log.hdr.desc.level, exp->level, NULL);
	zassert_equal(msg->log.hdr.desc.domain, exp->domain_id, NULL);

	uint32_t source_id;
	const void *source = msg->log.hdr.source;

	if (source == NULL) {
		source_id = 0;
	} else {
		source_id = IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) ?
		    log_dynamic_source_id((struct log_source_dynamic_data *)source) :
		    log_const_source_id((const struct log_source_const_data *)source);
	}

	zassert_equal(source_id, exp->source_id, "source_id:%p (exp: %d)",
		      source_id, exp->source_id);

	size_t len;
	uint8_t *data;

	data = log_msg_get_data(&msg->log, &len);
	zassert_equal(exp->data_len, len, NULL);
	if (exp->data_len <= sizeof(exp->data)) {
		zassert_equal(memcmp(data, exp->data, len), 0, NULL);
	}

	char str[128];
	struct test_str s = { .str = str };

	data = log_msg_get_package(&msg->log, &len);
	len = cbpprintf(out, &s, data);
	if (len > 0) {
		str[len] = '\0';
	}

	zassert_equal(strcmp(str, exp->str), 0, "Got \"%s\", Expected:\"%s\"",
			str, exp->str);
}

static void mock_init(struct log_backend const *const backend)
{

}

static void panic(struct log_backend const *const backend)
{
	struct mock_log_backend *mock = backend->cb->ctx;

	mock->panic = true;
}

static void dropped(const struct log_backend *const backend, uint32_t cnt)
{
	struct mock_log_backend *mock = backend->cb->ctx;

	mock->drop_cnt += cnt;
}


const struct log_backend_api mock_log_backend_api = {
	.process = process,
	.panic = panic,
	.init = mock_init,
	.dropped = IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE) ? NULL : dropped,
};
