/*
 * Copyright (c) 2020 PHYTEC Messtechnik GmbH
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include "test_modbus.h"

#include <logging/log.h>
LOG_MODULE_REGISTER(mbs_test, LOG_LEVEL_INF);

const static uint16_t fp_offset = MB_TEST_FP_OFFSET;
static uint16_t coils;
static uint16_t holding_reg[8];
static float holding_fp[4];

uint8_t server_iface;

uint8_t test_get_server_iface(void)
{
	return server_iface;
}

static int coil_rd(uint16_t addr, bool *state)
{
	if (addr >= (sizeof(coils) * 8)) {
		return -ENOTSUP;
	}

	if (coils & BIT(addr)) {
		*state = true;
	} else {
		*state = false;
	}

	LOG_DBG("Coil read, addr %u, %d", addr, (int)*state);

	return 0;
}

static int coil_wr(uint16_t addr, bool state)
{
	if (addr >= (sizeof(coils) * 8)) {
		return -ENOTSUP;
	}

	if (state == true) {
		coils |= BIT(addr);
	} else {
		coils &= ~BIT(addr);
	}

	LOG_DBG("Coil write, addr %u, %d", addr, (int)state);

	return 0;
}

static int discrete_input_rd(uint16_t addr, bool *state)
{
	if (addr >= (sizeof(coils) * 8)) {
		return -ENOTSUP;
	}

	if (coils & BIT(addr)) {
		*state = true;
	} else {
		*state = false;
	}

	LOG_DBG("Discrete input read, addr %u, %d", addr, (int)*state);

	return 0;
}

static int input_reg_rd(uint16_t addr, uint16_t *reg)
{
	if (addr >= ARRAY_SIZE(holding_reg)) {
		return -ENOTSUP;
	}

	*reg = holding_reg[addr];

	LOG_DBG("Input register read, addr %u, 0x%04x", addr, *reg);

	return 0;
}

static int input_reg_rd_fp(uint16_t addr, float *reg)
{
	if ((addr < fp_offset) ||
	    (addr >= (ARRAY_SIZE(holding_fp) + fp_offset))) {
		return -ENOTSUP;
	}

	*reg = holding_fp[addr - fp_offset];

	LOG_DBG("FP input register read, addr %u", addr);

	return 0;
}

static int holding_reg_rd(uint16_t addr, uint16_t *reg)
{
	if (addr >= ARRAY_SIZE(holding_reg)) {
		return -ENOTSUP;
	}

	*reg = holding_reg[addr];

	LOG_DBG("Holding register read, addr %u", addr);

	return 0;
}

static int holding_reg_wr(uint16_t addr, uint16_t reg)
{
	if (addr >= ARRAY_SIZE(holding_reg)) {
		return -ENOTSUP;
	}

	holding_reg[addr] = reg;

	LOG_DBG("Holding register write, addr %u", addr);

	return 0;
}

static int holding_reg_rd_fp(uint16_t addr, float *reg)
{
	if ((addr < fp_offset) ||
	    (addr >= (ARRAY_SIZE(holding_fp) + fp_offset))) {
		return -ENOTSUP;
	}

	*reg = holding_fp[addr - fp_offset];

	LOG_DBG("FP holding register read, addr %u", addr);

	return 0;
}

static int holding_reg_wr_fp(uint16_t addr, float reg)
{
	if ((addr < fp_offset) ||
	    (addr >= (ARRAY_SIZE(holding_fp) + fp_offset))) {
		return -ENOTSUP;
	}

	holding_fp[addr - fp_offset] = reg;

	LOG_DBG("FP holding register write, addr %u", addr);

	return 0;
}

static struct modbus_user_callbacks mbs_cbs = {
	/** Coil read/write callback */
	.coil_rd = coil_rd,
	.coil_wr = coil_wr,
	/* Discrete Input read callback */
	.discrete_input_rd = discrete_input_rd,
	/* Input Register read callback */
	.input_reg_rd = input_reg_rd,
	/* Floating Point Input Register read callback */
	.input_reg_rd_fp = input_reg_rd_fp,
	/* Holding Register read/write callback */
	.holding_reg_rd = holding_reg_rd,
	.holding_reg_wr = holding_reg_wr,
	/* Floating Point Holding Register read/write callback */
	.holding_reg_rd_fp = holding_reg_rd_fp,
	.holding_reg_wr_fp = holding_reg_wr_fp,
};

static struct modbus_iface_param server_param = {
	.mode = MODBUS_MODE_RTU,
	.server = {
		.user_cb = &mbs_cbs,
		.unit_id = MB_TEST_NODE_ADDR,
	},
	.serial = {
		.baud = MB_TEST_BAUDRATE_LOW,
		.parity = UART_CFG_PARITY_ODD,
	},
};

void test_server_setup_low_odd(void)
{
	int err;
	const char iface_name[] = {DT_PROP_OR(DT_INST(1, zephyr_modbus_serial),
					      label, "")};

	server_iface = modbus_iface_get_by_name(iface_name);
	server_param.mode = MODBUS_MODE_RTU;
	server_param.serial.baud = MB_TEST_BAUDRATE_LOW;
	server_param.serial.parity = UART_CFG_PARITY_ODD;

	if (IS_ENABLED(CONFIG_MODBUS_SERVER)) {
		err = modbus_init_server(server_iface, server_param);
		zassert_equal(err, 0, "Failed to configure RTU server");
	} else {
		ztest_test_skip();
	}
}

void test_server_setup_low_none(void)
{
	int err;
	const char iface_name[] = {DT_PROP_OR(DT_INST(1, zephyr_modbus_serial),
					      label, "")};

	server_iface = modbus_iface_get_by_name(iface_name);
	server_param.mode = MODBUS_MODE_RTU;
	server_param.serial.baud = MB_TEST_BAUDRATE_LOW;
	server_param.serial.parity = UART_CFG_PARITY_NONE;

	if (IS_ENABLED(CONFIG_MODBUS_SERVER)) {
		err = modbus_init_server(server_iface, server_param);
		zassert_equal(err, 0, "Failed to configure RTU server");
	} else {
		ztest_test_skip();
	}
}

void test_server_setup_high_even(void)
{
	int err;
	const char iface_name[] = {DT_PROP_OR(DT_INST(1, zephyr_modbus_serial),
					      label, "")};

	server_iface = modbus_iface_get_by_name(iface_name);
	server_param.mode = MODBUS_MODE_RTU;
	server_param.serial.baud = MB_TEST_BAUDRATE_HIGH;
	server_param.serial.parity = UART_CFG_PARITY_EVEN;

	if (IS_ENABLED(CONFIG_MODBUS_SERVER)) {
		err = modbus_init_server(server_iface, server_param);
		zassert_equal(err, 0, "Failed to configure RTU server");
	} else {
		ztest_test_skip();
	}
}

void test_server_setup_ascii(void)
{
	int err;
	const char iface_name[] = {DT_PROP_OR(DT_INST(1, zephyr_modbus_serial),
					      label, "")};

	server_iface = modbus_iface_get_by_name(iface_name);
	server_param.mode = MODBUS_MODE_ASCII;
	server_param.serial.baud = MB_TEST_BAUDRATE_HIGH;
	server_param.serial.parity = UART_CFG_PARITY_EVEN;

	if (IS_ENABLED(CONFIG_MODBUS_SERVER)) {
		err = modbus_init_server(server_iface, server_param);
		zassert_equal(err, 0, "Failed to configure RTU server");
	} else {
		ztest_test_skip();
	}
}

void test_server_setup_raw(void)
{
	char iface_name[] = "RAW_1";
	int err;

	server_iface = modbus_iface_get_by_name(iface_name);
	server_param.mode = MODBUS_MODE_RAW;
	server_param.raw_tx_cb = server_raw_cb;

	if (IS_ENABLED(CONFIG_MODBUS_SERVER)) {
		err = modbus_init_server(server_iface, server_param);
		zassert_equal(err, 0, "Failed to configure RAW server");
	} else {
		ztest_test_skip();
	}
}

void test_server_disable(void)
{
	int err;

	if (IS_ENABLED(CONFIG_MODBUS_SERVER)) {
		err = modbus_disable(server_iface);
		zassert_equal(err, 0, "Failed to disable RTU server");
	} else {
		ztest_test_skip();
	}
}
