/*
 * Copyright (c) 2020 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include <zephyr/bluetooth/mesh.h>
#include "net.h"
#include <zephyr/bluetooth/conn.h>
#include "proxy.h"
#include "foundation.h"
#include "beacon.h"
#include "cfg.h"
#include "settings.h"

#define LOG_LEVEL CONFIG_BT_MESH_MODEL_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(bt_mesh_priv_beacon_srv);

static const struct bt_mesh_model *priv_beacon_srv;

/* Private Beacon configuration server model states */
struct {
	uint8_t state;
	uint8_t interval;
	uint8_t proxy_state;
} priv_beacon_state;

static int priv_beacon_store(bool delete)
{
	if (!IS_ENABLED(CONFIG_BT_SETTINGS)) {
		return 0;
	}

	const void *data = delete ? NULL : &priv_beacon_state;
	size_t len = delete ? 0 : sizeof(priv_beacon_state);

	return bt_mesh_model_data_store(priv_beacon_srv, false, "pb", data, len);
}

static int beacon_status_rsp(const struct bt_mesh_model *mod,
			      struct bt_mesh_msg_ctx *ctx)
{
	BT_MESH_MODEL_BUF_DEFINE(buf, OP_PRIV_BEACON_STATUS, 2);
	bt_mesh_model_msg_init(&buf, OP_PRIV_BEACON_STATUS);

	net_buf_simple_add_u8(&buf, bt_mesh_priv_beacon_get());
	net_buf_simple_add_u8(&buf, bt_mesh_priv_beacon_update_interval_get());

	bt_mesh_model_send(mod, ctx, &buf, NULL, NULL);

	return 0;
}

static int handle_beacon_get(const struct bt_mesh_model *mod,
			     struct bt_mesh_msg_ctx *ctx,
			     struct net_buf_simple *buf)
{
	LOG_DBG("");

	beacon_status_rsp(mod, ctx);

	return 0;
}

static int handle_beacon_set(const struct bt_mesh_model *mod,
			     struct bt_mesh_msg_ctx *ctx,
			     struct net_buf_simple *buf)
{
	uint8_t beacon;

	if (buf->len > 2U) {
		return -EMSGSIZE;
	}

	beacon = net_buf_simple_pull_u8(buf);
	if (beacon != BT_MESH_BEACON_DISABLED &&
	    beacon != BT_MESH_BEACON_ENABLED) {
		LOG_WRN("Invalid beacon value %u", beacon);
		return -EINVAL;
	}

	if (buf->len == 1U) {
		bt_mesh_priv_beacon_update_interval_set(net_buf_simple_pull_u8(buf));
	}

	(void)bt_mesh_priv_beacon_set(beacon);
	beacon_status_rsp(mod, ctx);

	return 0;
}

static void gatt_proxy_status_rsp(const struct bt_mesh_model *mod,
				  struct bt_mesh_msg_ctx *ctx)
{
	BT_MESH_MODEL_BUF_DEFINE(buf, OP_PRIV_GATT_PROXY_STATUS, 1);
	bt_mesh_model_msg_init(&buf, OP_PRIV_GATT_PROXY_STATUS);

	net_buf_simple_add_u8(&buf, bt_mesh_priv_gatt_proxy_get());

	bt_mesh_model_send(mod, ctx, &buf, NULL, NULL);
}

static int handle_gatt_proxy_get(const struct bt_mesh_model *mod,
				 struct bt_mesh_msg_ctx *ctx,
				 struct net_buf_simple *buf)
{
	LOG_DBG("");

	gatt_proxy_status_rsp(mod, ctx);

	return 0;
}

static int handle_gatt_proxy_set(const struct bt_mesh_model *mod,
				 struct bt_mesh_msg_ctx *ctx,
				 struct net_buf_simple *buf)
{
	uint8_t gatt_proxy;

	gatt_proxy = net_buf_simple_pull_u8(buf);
	if (gatt_proxy != BT_MESH_GATT_PROXY_DISABLED &&
	    gatt_proxy != BT_MESH_GATT_PROXY_ENABLED) {
		LOG_WRN("Invalid GATT proxy value %u", gatt_proxy);
		return -EINVAL;
	}

	LOG_DBG("%u", gatt_proxy);

	bt_mesh_priv_gatt_proxy_set(gatt_proxy);

	gatt_proxy_status_rsp(mod, ctx);

	return 0;
}

static void node_id_status_rsp(const struct bt_mesh_model *mod,
			       struct bt_mesh_msg_ctx *ctx, uint8_t status,
			       uint16_t net_idx, uint8_t node_id)
{
	BT_MESH_MODEL_BUF_DEFINE(buf, OP_PRIV_NODE_ID_STATUS, 4);
	bt_mesh_model_msg_init(&buf, OP_PRIV_NODE_ID_STATUS);

	net_buf_simple_add_u8(&buf, status);
	net_buf_simple_add_le16(&buf, net_idx);
	net_buf_simple_add_u8(&buf, node_id);

	bt_mesh_model_send(mod, ctx, &buf, NULL, NULL);
}

static int handle_node_id_get(const struct bt_mesh_model *mod,
			      struct bt_mesh_msg_ctx *ctx,
			      struct net_buf_simple *buf)
{
	uint8_t node_id, status;
	uint16_t net_idx;

	net_idx = net_buf_simple_pull_le16(buf) & 0xfff;

	status = bt_mesh_subnet_priv_node_id_get(net_idx, (enum bt_mesh_feat_state *)&node_id);
	node_id_status_rsp(mod, ctx, status, net_idx, node_id);

	return 0;
}

static int handle_node_id_set(const struct bt_mesh_model *mod,
			      struct bt_mesh_msg_ctx *ctx,
			      struct net_buf_simple *buf)
{
	uint8_t node_id, status;
	uint16_t net_idx;

	net_idx = net_buf_simple_pull_le16(buf) & 0xfff;
	node_id = net_buf_simple_pull_u8(buf);
	if (node_id != BT_MESH_NODE_IDENTITY_RUNNING &&
	    node_id != BT_MESH_NODE_IDENTITY_STOPPED) {
		LOG_ERR("Invalid node ID value 0x%02x", node_id);
		return -EINVAL;
	}

	status = bt_mesh_subnet_priv_node_id_set(net_idx, node_id);
	node_id_status_rsp(mod, ctx, status, net_idx, node_id);

	return 0;
}

const struct bt_mesh_model_op bt_mesh_priv_beacon_srv_op[] = {
	{ OP_PRIV_BEACON_GET, BT_MESH_LEN_EXACT(0), handle_beacon_get },
	{ OP_PRIV_BEACON_SET, BT_MESH_LEN_MIN(1), handle_beacon_set },
	{ OP_PRIV_GATT_PROXY_GET, BT_MESH_LEN_EXACT(0), handle_gatt_proxy_get },
	{ OP_PRIV_GATT_PROXY_SET, BT_MESH_LEN_EXACT(1), handle_gatt_proxy_set },
	{ OP_PRIV_NODE_ID_GET, BT_MESH_LEN_EXACT(2), handle_node_id_get },
	{ OP_PRIV_NODE_ID_SET, BT_MESH_LEN_EXACT(3), handle_node_id_set },
	BT_MESH_MODEL_OP_END
};

static int priv_beacon_srv_init(const struct bt_mesh_model *mod)
{
	if (!bt_mesh_model_in_primary(mod)) {
		LOG_ERR("Priv beacon server not in primary element");
		return -EINVAL;
	}

	priv_beacon_srv = mod;
	mod->keys[0] = BT_MESH_KEY_DEV_LOCAL;

	return 0;
}

static void priv_beacon_srv_reset(const struct bt_mesh_model *model)
{
	(void)memset(&priv_beacon_state, 0, sizeof(priv_beacon_state));
	priv_beacon_store(true);
}

#ifdef CONFIG_BT_SETTINGS
static int priv_beacon_srv_settings_set(const struct bt_mesh_model *model, const char *name,
					size_t len_rd, settings_read_cb read_cb, void *cb_data)
{
	int err;

	if (len_rd == 0) {
		LOG_DBG("Cleared configuration state");
		return 0;
	}

	err = bt_mesh_settings_set(read_cb, cb_data, &priv_beacon_state, sizeof(priv_beacon_state));
	if (err) {
		LOG_ERR("Failed to set Private Beacon state");
		return err;
	}

	bt_mesh_priv_beacon_set(priv_beacon_state.state);
	bt_mesh_priv_beacon_update_interval_set(priv_beacon_state.interval);
	bt_mesh_priv_gatt_proxy_set(priv_beacon_state.proxy_state);
	return 0;
}

static void priv_beacon_srv_pending_store(const struct bt_mesh_model *model)
{
	priv_beacon_state.state = bt_mesh_priv_beacon_get();
	priv_beacon_state.interval = bt_mesh_priv_beacon_update_interval_get();
	priv_beacon_state.proxy_state = bt_mesh_priv_gatt_proxy_get();

	priv_beacon_store(false);
}
#endif

const struct bt_mesh_model_cb bt_mesh_priv_beacon_srv_cb = {
	.init = priv_beacon_srv_init,
	.reset = priv_beacon_srv_reset,
#ifdef CONFIG_BT_SETTINGS
	.settings_set = priv_beacon_srv_settings_set,
	.pending_store = priv_beacon_srv_pending_store,
#endif
};

void bt_mesh_priv_beacon_srv_store_schedule(void)
{
	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
		bt_mesh_model_data_store_schedule(priv_beacon_srv);
	}
}
