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

#include <zephyr/bluetooth/mesh.h>
#include <zephyr/storage/flash_map.h>
#include <zephyr/drivers/flash.h>
#include <assert.h>
#include "blob.h"
#include "net.h"
#include "transport.h"

#define WRITE_BLOCK_SIZE DT_PROP(DT_INST(0, soc_nv_flash), write_block_size)

#define FLASH_IO(_io) CONTAINER_OF(_io, struct bt_mesh_blob_io_flash, io)

static int test_flash_area(uint8_t area_id)
{
	const struct flash_area *area;
	uint8_t align;
	int err;

	err = flash_area_open(area_id, &area);
	if (err) {
		return err;
	}

	align = flash_area_align(area);
	flash_area_close(area);

	if (align > WRITE_BLOCK_SIZE) {
		return -EINVAL;
	}

	return 0;
}

static int io_open(const struct bt_mesh_blob_io *io,
		   const struct bt_mesh_blob_xfer *xfer,
		   enum bt_mesh_blob_io_mode mode)
{
	struct bt_mesh_blob_io_flash *flash = FLASH_IO(io);

	flash->mode = mode;

	return flash_area_open(flash->area_id, &flash->area);
}

static void io_close(const struct bt_mesh_blob_io *io,
		     const struct bt_mesh_blob_xfer *xfer)
{
	struct bt_mesh_blob_io_flash *flash = FLASH_IO(io);

	flash_area_close(flash->area);
}

static int block_start(const struct bt_mesh_blob_io *io,
		       const struct bt_mesh_blob_xfer *xfer,
		       const struct bt_mesh_blob_block *block)
{
	struct bt_mesh_blob_io_flash *flash = FLASH_IO(io);
	size_t erase_size;

	if (flash->mode == BT_MESH_BLOB_READ) {
		return 0;
	}

#if defined(CONFIG_FLASH_PAGE_LAYOUT)
	struct flash_pages_info page;
	const struct device *flash_dev;
	int err;

	flash_dev = flash_area_get_device(flash->area);
	if (!flash_dev) {
		return -ENODEV;
	}

	err = flash_get_page_info_by_offs(flash_dev,
					  flash->offset + block->offset, &page);
	if (err) {
		return err;
	}

	erase_size = page.size * DIV_ROUND_UP(block->size, page.size);
#else
	erase_size = block->size;
#endif

	return flash_area_erase(flash->area, flash->offset + block->offset,
				erase_size);
}

static int rd_chunk(const struct bt_mesh_blob_io *io,
		    const struct bt_mesh_blob_xfer *xfer,
		    const struct bt_mesh_blob_block *block,
		    const struct bt_mesh_blob_chunk *chunk)
{
	struct bt_mesh_blob_io_flash *flash = FLASH_IO(io);

	return flash_area_read(flash->area,
			       flash->offset + block->offset + chunk->offset,
			       chunk->data, chunk->size);
}

static int wr_chunk(const struct bt_mesh_blob_io *io,
		    const struct bt_mesh_blob_xfer *xfer,
		    const struct bt_mesh_blob_block *block,
		    const struct bt_mesh_blob_chunk *chunk)
{
	struct bt_mesh_blob_io_flash *flash = FLASH_IO(io);

	if (IS_ENABLED(CONFIG_SOC_FLASH_NRF_RRAM)) {
		return flash_area_write(flash->area,
					flash->offset + block->offset + chunk->offset,
					chunk->data, chunk->size);
	}

	uint8_t buf[ROUND_UP(BLOB_CHUNK_SIZE_MAX(BT_MESH_RX_SDU_MAX),
			  WRITE_BLOCK_SIZE)];
	off_t area_offset = flash->offset + block->offset + chunk->offset;
	int i = 0;

	/* Write block align the chunk data */
	memset(&buf[i], 0xff, area_offset % WRITE_BLOCK_SIZE);
	i += area_offset % WRITE_BLOCK_SIZE;

	memcpy(&buf[i], chunk->data, chunk->size);
	i += chunk->size;

	memset(&buf[i], 0xff, ROUND_UP(i, WRITE_BLOCK_SIZE) - i);
	i = ROUND_UP(i, WRITE_BLOCK_SIZE);

	return flash_area_write(flash->area,
				ROUND_DOWN(area_offset, WRITE_BLOCK_SIZE),
				buf, i);
}

int bt_mesh_blob_io_flash_init(struct bt_mesh_blob_io_flash *flash,
			       uint8_t area_id, off_t offset)
{
	int err;

	err = test_flash_area(area_id);
	if (err) {
		return err;
	}

	flash->area_id = area_id;
	flash->offset = offset;
	flash->io.open = io_open;
	flash->io.close = io_close;
	flash->io.block_start = block_start;
	flash->io.block_end = NULL;
	flash->io.rd = rd_chunk;
	flash->io.wr = wr_chunk;

	return 0;
}
