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

#include <zephyr/bluetooth/mesh.h>
#include "dfu.h"
#include "blob.h"
#include "access.h"

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

#define UPDATE_IDX_NONE 0xff

BUILD_ASSERT((DFU_UPDATE_START_MSG_MAXLEN + BT_MESH_MODEL_OP_LEN(BT_MESH_DFU_OP_UPDATE_START) +
	      BT_MESH_MIC_SHORT) <= BT_MESH_RX_SDU_MAX,
	     "The Firmware Update Start message does not fit into the maximum incoming SDU size.");

BUILD_ASSERT((DFU_UPDATE_INFO_STATUS_MSG_MINLEN +
	      BT_MESH_MODEL_OP_LEN(BT_MESH_DFU_OP_UPDATE_INFO_STATUS) + BT_MESH_MIC_SHORT)
	     <= BT_MESH_TX_SDU_MAX,
	     "The Firmware Update Info Status message does not fit into the maximum outgoing SDU "
	     "size.");

static void store_state(struct bt_mesh_dfu_srv *srv)
{
	bt_mesh_model_data_store(srv->mod, false, NULL, &srv->update,
				 sizeof(srv->update));
}

static void erase_state(struct bt_mesh_dfu_srv *srv)
{
	bt_mesh_model_data_store(srv->mod, false, NULL, NULL, 0);
}

static void xfer_failed(struct bt_mesh_dfu_srv *srv)
{
	if (!bt_mesh_dfu_srv_is_busy(srv) ||
	    srv->update.idx >= srv->img_count) {
		return;
	}

	erase_state(srv);

	if (srv->cb->end) {
		srv->cb->end(srv, &srv->imgs[srv->update.idx], false);
	}
}

static enum bt_mesh_dfu_status metadata_check(struct bt_mesh_dfu_srv *srv,
					      uint8_t idx,
					      struct net_buf_simple *buf,
					      enum bt_mesh_dfu_effect *effect)
{
	*effect = BT_MESH_DFU_EFFECT_NONE;

	if (idx >= srv->img_count) {
		return BT_MESH_DFU_ERR_FW_IDX;
	}

	if (!srv->cb->check) {
		return BT_MESH_DFU_SUCCESS;
	}

	if (srv->cb->check(srv, &srv->imgs[idx], buf, effect)) {
		*effect = BT_MESH_DFU_EFFECT_NONE;
		return BT_MESH_DFU_ERR_METADATA;
	}

	return BT_MESH_DFU_SUCCESS;
}

static void apply_rsp_sent(int err, void *cb_params)
{
	struct bt_mesh_dfu_srv *srv = cb_params;

	if (err) {
		LOG_WRN("Apply response failed, wait for retry");
		return;
	}

	LOG_DBG("");

	if (!srv->cb->apply || srv->update.idx == UPDATE_IDX_NONE) {
		srv->update.phase = BT_MESH_DFU_PHASE_IDLE;
		store_state(srv);
		return;
	}

	err = srv->cb->apply(srv, &srv->imgs[srv->update.idx]);
	if (err) {
		srv->update.phase = BT_MESH_DFU_PHASE_IDLE;
	}

	store_state(srv);
}

static void apply_rsp_sending(uint16_t duration, int err, void *cb_params)
{
	if (err) {
		apply_rsp_sent(err, cb_params);
	}
}

static void verify(struct bt_mesh_dfu_srv *srv)
{
	srv->update.phase = BT_MESH_DFU_PHASE_VERIFY;

	if (srv->update.idx >= srv->img_count) {
		bt_mesh_dfu_srv_rejected(srv);
		return;
	}

	if (!srv->cb->end) {
		bt_mesh_dfu_srv_verified(srv);
		return;
	}

	srv->cb->end(srv, &srv->imgs[srv->update.idx], true);
	if (srv->update.phase == BT_MESH_DFU_PHASE_VERIFY) {
		store_state(srv);
	}
}

static int handle_info_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
			   struct net_buf_simple *buf)
{
	struct bt_mesh_dfu_srv *srv = mod->user_data;
	uint8_t idx, limit;

	if (srv->update.phase == BT_MESH_DFU_PHASE_APPLYING) {
		LOG_INF("Still applying, not responding");
		return -EBUSY;
	}

	idx = net_buf_simple_pull_u8(buf);
	limit = net_buf_simple_pull_u8(buf);

	LOG_DBG("from %u (limit: %u)", idx, limit);

	NET_BUF_SIMPLE_DEFINE(rsp, BT_MESH_TX_SDU_MAX);
	bt_mesh_model_msg_init(&rsp, BT_MESH_DFU_OP_UPDATE_INFO_STATUS);
	net_buf_simple_add_u8(&rsp, srv->img_count);
	net_buf_simple_add_u8(&rsp, idx);

	for (; idx < srv->img_count && limit > 0; ++idx) {
		uint32_t entry_len;

		if (!srv->imgs[idx].fwid) {
			continue;
		}

		entry_len = 2 + srv->imgs[idx].fwid_len;
		if (srv->imgs[idx].uri) {
			entry_len += strlen(srv->imgs[idx].uri);
		}

		if (net_buf_simple_tailroom(&rsp) + BT_MESH_MIC_SHORT < entry_len) {
			break;
		}

		net_buf_simple_add_u8(&rsp, srv->imgs[idx].fwid_len);
		net_buf_simple_add_mem(&rsp, srv->imgs[idx].fwid,
				       srv->imgs[idx].fwid_len);

		if (srv->imgs[idx].uri) {
			size_t len = strlen(srv->imgs[idx].uri);

			net_buf_simple_add_u8(&rsp, len);
			net_buf_simple_add_mem(&rsp, srv->imgs[idx].uri, len);
		} else {
			net_buf_simple_add_u8(&rsp, 0);
		}

		limit--;
	}

	if (srv->update.phase != BT_MESH_DFU_PHASE_IDLE) {
		ctx->send_ttl = srv->update.ttl;
	}

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

	return 0;
}

static int handle_metadata_check(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
				 struct net_buf_simple *buf)
{
	struct bt_mesh_dfu_srv *srv = mod->user_data;
	enum bt_mesh_dfu_status status;
	enum bt_mesh_dfu_effect effect;
	uint8_t idx;

	BT_MESH_MODEL_BUF_DEFINE(rsp, BT_MESH_DFU_OP_UPDATE_METADATA_STATUS, 2);
	bt_mesh_model_msg_init(&rsp, BT_MESH_DFU_OP_UPDATE_METADATA_STATUS);

	idx = net_buf_simple_pull_u8(buf);
	status = metadata_check(srv, idx, buf, &effect);

	LOG_DBG("%u", idx);

	net_buf_simple_add_u8(&rsp, (status & BIT_MASK(3)) | (effect << 3));
	net_buf_simple_add_u8(&rsp, idx);

	if (srv->update.phase != BT_MESH_DFU_PHASE_IDLE) {
		ctx->send_ttl = srv->update.ttl;
	}

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

	return 0;
}

static void update_status_rsp(struct bt_mesh_dfu_srv *srv,
			      struct bt_mesh_msg_ctx *ctx,
			      enum bt_mesh_dfu_status status,
			      const struct bt_mesh_send_cb *send_cb)
{
	BT_MESH_MODEL_BUF_DEFINE(buf, BT_MESH_DFU_OP_UPDATE_STATUS, 14);
	bt_mesh_model_msg_init(&buf, BT_MESH_DFU_OP_UPDATE_STATUS);

	net_buf_simple_add_u8(&buf, ((status & BIT_MASK(3)) |
				     (srv->update.phase << 5)));

	if (srv->update.phase != BT_MESH_DFU_PHASE_IDLE) {
		net_buf_simple_add_u8(&buf, srv->update.ttl);
		net_buf_simple_add_u8(&buf, srv->update.effect);
		net_buf_simple_add_le16(&buf, srv->update.timeout_base);
		net_buf_simple_add_le64(&buf, srv->blob.state.xfer.id);
		net_buf_simple_add_u8(&buf, srv->update.idx);

		ctx->send_ttl = srv->update.ttl;
	}

	bt_mesh_model_send(srv->mod, ctx, &buf, send_cb, srv);
}

static int handle_get(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
		      struct net_buf_simple *buf)
{
	struct bt_mesh_dfu_srv *srv = mod->user_data;

	LOG_DBG("");

	update_status_rsp(srv, ctx, BT_MESH_DFU_SUCCESS, NULL);

	return 0;
}

static inline bool is_active_update(struct bt_mesh_dfu_srv *srv, uint8_t idx,
				    uint16_t timeout_base,
				    const uint64_t *blob_id, uint8_t ttl,
				    uint16_t meta_checksum)
{
	return (srv->update.idx != idx || srv->blob.state.xfer.id != *blob_id ||
		srv->update.ttl != ttl ||
		srv->update.timeout_base != timeout_base ||
		srv->update.meta != meta_checksum);
}

static int handle_start(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
			struct net_buf_simple *buf)
{
	struct bt_mesh_dfu_srv *srv = mod->user_data;
	const struct bt_mesh_blob_io *io;
	uint16_t timeout_base, meta_checksum;
	enum bt_mesh_dfu_status status;
	uint8_t ttl, idx;
	uint64_t blob_id;
	int err;
	struct net_buf_simple_state buf_state;

	ttl = net_buf_simple_pull_u8(buf);
	timeout_base = net_buf_simple_pull_le16(buf);
	blob_id = net_buf_simple_pull_le64(buf);
	idx = net_buf_simple_pull_u8(buf);
	meta_checksum = dfu_metadata_checksum(buf);

	LOG_DBG("%u ttl: %u extra time: %u", idx, ttl, timeout_base);

	if ((!buf->len || meta_checksum == srv->update.meta) &&
	    srv->update.phase == BT_MESH_DFU_PHASE_TRANSFER_ERR &&
	    srv->update.ttl == ttl &&
	    srv->update.timeout_base == timeout_base &&
	    srv->update.idx == idx &&
	    srv->blob.state.xfer.id == blob_id) {
		srv->update.phase = BT_MESH_DFU_PHASE_TRANSFER_ACTIVE;
		status = BT_MESH_DFU_SUCCESS;
		store_state(srv);
		/* blob srv will resume the transfer. */
		LOG_DBG("Resuming transfer");
		goto rsp;
	}

	if (bt_mesh_dfu_srv_is_busy(srv)) {
		if (is_active_update(srv, idx, timeout_base, &blob_id, ttl,
				     meta_checksum)) {
			status = BT_MESH_DFU_ERR_WRONG_PHASE;
		} else {
			status = BT_MESH_DFU_SUCCESS;
		}

		srv->update.ttl = ttl;
		srv->blob.state.xfer.id = blob_id;
		LOG_WRN("Busy. Phase: %u", srv->update.phase);
		goto rsp;
	}

	net_buf_simple_save(buf, &buf_state);
	status = metadata_check(srv, idx, buf,
				(enum bt_mesh_dfu_effect *)&srv->update.effect);
	net_buf_simple_restore(buf, &buf_state);
	if (status != BT_MESH_DFU_SUCCESS) {
		goto rsp;
	}

	srv->update.ttl = ttl;
	srv->update.timeout_base = timeout_base;
	srv->update.meta = meta_checksum;

	io = NULL;
	err = srv->cb->start(srv, &srv->imgs[idx], buf, &io);
	if (err == -EALREADY || (!err && bt_mesh_has_addr(ctx->addr))) {
		/* This image has already been received or this is a
		 * self-update. Skip the transfer phase and proceed to
		 * verifying update.
		 */
		status = BT_MESH_DFU_SUCCESS;
		srv->update.idx = idx;
		srv->blob.state.xfer.id = blob_id;
		srv->update.phase = BT_MESH_DFU_PHASE_VERIFY;
		update_status_rsp(srv, ctx, status, NULL);
		verify(srv);
		return 0;
	}

	if (err == -ENOMEM) {
		status = BT_MESH_DFU_ERR_RESOURCES;
		goto rsp;
	}

	if (err == -EBUSY) {
		status = BT_MESH_DFU_ERR_TEMPORARILY_UNAVAILABLE;
		goto rsp;
	}

	if (err || !io || !io->wr) {
		status = BT_MESH_DFU_ERR_INTERNAL;
		goto rsp;
	}

	err = bt_mesh_blob_srv_recv(&srv->blob, blob_id, io,
				    ttl, timeout_base);
	if (err) {
		status = BT_MESH_DFU_ERR_BLOB_XFER_BUSY;
		goto rsp;
	}

	srv->update.idx = idx;
	srv->update.phase = BT_MESH_DFU_PHASE_TRANSFER_ACTIVE;
	status = BT_MESH_DFU_SUCCESS;
	store_state(srv);

rsp:
	update_status_rsp(srv, ctx, status, NULL);

	return 0;
}

static int handle_cancel(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
			 struct net_buf_simple *buf)
{
	struct bt_mesh_dfu_srv *srv = mod->user_data;

	if (srv->update.idx == UPDATE_IDX_NONE) {
		goto rsp;
	}

	LOG_DBG("");

	bt_mesh_blob_srv_cancel(&srv->blob);
	srv->update.phase = BT_MESH_DFU_PHASE_IDLE;
	xfer_failed(srv);

rsp:
	update_status_rsp(srv, ctx, BT_MESH_DFU_SUCCESS, NULL);

	return 0;
}

static int handle_apply(struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
			struct net_buf_simple *buf)
{
	struct bt_mesh_dfu_srv *srv = mod->user_data;
	static const struct bt_mesh_send_cb send_cb = {
		.start = apply_rsp_sending,
		.end = apply_rsp_sent,
	};

	LOG_DBG("");

	if (srv->update.phase == BT_MESH_DFU_PHASE_APPLYING) {
		update_status_rsp(srv, ctx, BT_MESH_DFU_SUCCESS, NULL);
		return 0;
	}

	if (srv->update.phase != BT_MESH_DFU_PHASE_VERIFY_OK) {
		LOG_WRN("Apply: Invalid phase %u", srv->update.phase);
		update_status_rsp(srv, ctx, BT_MESH_DFU_ERR_WRONG_PHASE, NULL);
		return 0;
	}

	/* Postponing the apply callback until the response has been sent, in
	 * case it triggers a reboot:
	 */
	srv->update.phase = BT_MESH_DFU_PHASE_APPLYING;
	store_state(srv);

	update_status_rsp(srv, ctx, BT_MESH_DFU_SUCCESS, &send_cb);

	return 0;
}

const struct bt_mesh_model_op _bt_mesh_dfu_srv_op[] = {
	{ BT_MESH_DFU_OP_UPDATE_INFO_GET, BT_MESH_LEN_EXACT(2), handle_info_get },
	{ BT_MESH_DFU_OP_UPDATE_METADATA_CHECK, BT_MESH_LEN_MIN(1), handle_metadata_check },
	{ BT_MESH_DFU_OP_UPDATE_GET, BT_MESH_LEN_EXACT(0), handle_get },
	{ BT_MESH_DFU_OP_UPDATE_START, BT_MESH_LEN_MIN(12), handle_start },
	{ BT_MESH_DFU_OP_UPDATE_CANCEL, BT_MESH_LEN_EXACT(0), handle_cancel },
	{ BT_MESH_DFU_OP_UPDATE_APPLY, BT_MESH_LEN_EXACT(0), handle_apply },
	BT_MESH_MODEL_OP_END,
};

static int dfu_srv_init(struct bt_mesh_model *mod)
{
	struct bt_mesh_dfu_srv *srv = mod->user_data;

	srv->mod = mod;
	srv->update.idx = UPDATE_IDX_NONE;

	if (!srv->cb || !srv->cb->start || !srv->imgs || srv->img_count == 0 ||
	    srv->img_count == UPDATE_IDX_NONE) {
		LOG_ERR("Invalid DFU Server initialization");
		return -EINVAL;
	}

	if (IS_ENABLED(CONFIG_BT_MESH_MODEL_EXTENSIONS)) {
		bt_mesh_model_extend(mod, srv->blob.mod);
	}

	return 0;
}

static int dfu_srv_settings_set(struct bt_mesh_model *mod, const char *name,
				size_t len_rd, settings_read_cb read_cb,
				void *cb_arg)
{
	struct bt_mesh_dfu_srv *srv = mod->user_data;
	ssize_t len;

	if (len_rd < sizeof(srv->update)) {
		return -EINVAL;
	}

	len = read_cb(cb_arg, &srv->update, sizeof(srv->update));
	if (len < 0) {
		return len;
	}

	LOG_DBG("Recovered transfer (phase: %u, idx: %u)", srv->update.phase,
		srv->update.idx);
	if (srv->update.phase == BT_MESH_DFU_PHASE_TRANSFER_ACTIVE) {
		LOG_DBG("Settings recovered mid-transfer, setting transfer error");
		srv->update.phase = BT_MESH_DFU_PHASE_TRANSFER_ERR;
	} else if (srv->update.phase == BT_MESH_DFU_PHASE_VERIFY_OK) {
		LOG_DBG("Settings recovered before application, setting verification fail");
		srv->update.phase = BT_MESH_DFU_PHASE_VERIFY_FAIL;
	}

	return 0;
}

static void dfu_srv_reset(struct bt_mesh_model *mod)
{
	struct bt_mesh_dfu_srv *srv = mod->user_data;

	srv->update.phase = BT_MESH_DFU_PHASE_IDLE;
	erase_state(srv);
}

const struct bt_mesh_model_cb _bt_mesh_dfu_srv_cb = {
	.init = dfu_srv_init,
	.settings_set = dfu_srv_settings_set,
	.reset = dfu_srv_reset,
};

static void blob_suspended(struct bt_mesh_blob_srv *b)
{
	struct bt_mesh_dfu_srv *srv = CONTAINER_OF(b, struct bt_mesh_dfu_srv, blob);

	srv->update.phase = BT_MESH_DFU_PHASE_TRANSFER_ERR;
	store_state(srv);
}

static void blob_end(struct bt_mesh_blob_srv *b, uint64_t id, bool success)
{
	struct bt_mesh_dfu_srv *srv =
		CONTAINER_OF(b, struct bt_mesh_dfu_srv, blob);

	LOG_DBG("success: %u", success);

	if (!success) {
		srv->update.phase = BT_MESH_DFU_PHASE_TRANSFER_ERR;
		xfer_failed(srv);
		return;
	}

	verify(srv);
}

static int blob_recover(struct bt_mesh_blob_srv *b,
			struct bt_mesh_blob_xfer *xfer,
			const struct bt_mesh_blob_io **io)
{
	struct bt_mesh_dfu_srv *srv =
		CONTAINER_OF(b, struct bt_mesh_dfu_srv, blob);

	if (!srv->cb->recover ||
	    srv->update.phase != BT_MESH_DFU_PHASE_TRANSFER_ERR ||
	    srv->update.idx >= srv->img_count) {
		return -ENOTSUP;
	}

	return srv->cb->recover(srv, &srv->imgs[srv->update.idx], io);
}

const struct bt_mesh_blob_srv_cb _bt_mesh_dfu_srv_blob_cb = {
	.suspended = blob_suspended,
	.end = blob_end,
	.recover = blob_recover,
};

void bt_mesh_dfu_srv_verified(struct bt_mesh_dfu_srv *srv)
{
	if (srv->update.phase != BT_MESH_DFU_PHASE_VERIFY) {
		LOG_WRN("Wrong state");
		return;
	}

	LOG_DBG("");

	srv->update.phase = BT_MESH_DFU_PHASE_VERIFY_OK;
	store_state(srv);
}

void bt_mesh_dfu_srv_rejected(struct bt_mesh_dfu_srv *srv)
{
	if (srv->update.phase != BT_MESH_DFU_PHASE_VERIFY) {
		LOG_WRN("Wrong state");
		return;
	}

	LOG_DBG("");

	srv->update.phase = BT_MESH_DFU_PHASE_VERIFY_FAIL;
	store_state(srv);
}

void bt_mesh_dfu_srv_cancel(struct bt_mesh_dfu_srv *srv)
{
	if (srv->update.phase == BT_MESH_DFU_PHASE_IDLE) {
		LOG_WRN("Wrong state");
		return;
	}

	(void)bt_mesh_blob_srv_cancel(&srv->blob);
}

void bt_mesh_dfu_srv_applied(struct bt_mesh_dfu_srv *srv)
{
	if (srv->update.phase != BT_MESH_DFU_PHASE_APPLYING) {
		LOG_WRN("Wrong state");
		return;
	}

	LOG_DBG("");

	srv->update.phase = BT_MESH_DFU_PHASE_IDLE;
	store_state(srv);
}

bool bt_mesh_dfu_srv_is_busy(const struct bt_mesh_dfu_srv *srv)
{
	return srv->update.phase != BT_MESH_DFU_PHASE_IDLE &&
	       srv->update.phase != BT_MESH_DFU_PHASE_TRANSFER_ERR &&
	       srv->update.phase != BT_MESH_DFU_PHASE_VERIFY_FAIL;
}

uint8_t bt_mesh_dfu_srv_progress(const struct bt_mesh_dfu_srv *srv)
{
	if (!bt_mesh_dfu_srv_is_busy(srv)) {
		return 0U;
	}

	if (srv->update.phase == BT_MESH_DFU_PHASE_TRANSFER_ACTIVE) {
		return bt_mesh_blob_srv_progress(&srv->blob);
	}

	return 100U;
}
