/*
 * Copyright (c) 2017 Linaro Limited
 * Copyright (c) 2018-2019 Foundries.io
 * Copyright (c) 2022 Laird Connectivity
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/*
 * Source material for uCIFI battery object (3411):
 * https://raw.githubusercontent.com/OpenMobileAlliance/lwm2m-registry/prod/3411.xml
 */

#define LOG_MODULE_NAME net_ucifi_battery
#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL

#include <logging/log.h>
LOG_MODULE_REGISTER(LOG_MODULE_NAME);

#include <stdint.h>
#include <init.h>

#include "lwm2m_object.h"
#include "lwm2m_engine.h"
#include "lwm2m_resource_ids.h"
#include "ucifi_battery.h"

#define BATTERY_VERSION_MAJOR 1
#define BATTERY_VERSION_MINOR 0

#define MAX_INSTANCE_COUNT CONFIG_LWM2M_UCIFI_BATTERY_INSTANCE_COUNT

#define BATTERY_MAX_ID 12
#define RESOURCE_INSTANCE_COUNT (BATTERY_MAX_ID)

/* resource state variables */
static uint8_t battery_level[MAX_INSTANCE_COUNT];
static uint32_t supply_loss_counter[MAX_INSTANCE_COUNT];

static struct lwm2m_engine_obj battery;
static struct lwm2m_engine_obj_field fields[] = {
	OBJ_FIELD_DATA(UCIFI_BATTERY_LEVEL_RID, R, U8),
	OBJ_FIELD_DATA(UCIFI_BATTERY_CAPACITY_RID, R_OPT, FLOAT),
	OBJ_FIELD_DATA(UCIFI_BATTERY_VOLTAGE_RID, R_OPT, FLOAT),
	OBJ_FIELD_DATA(UCIFI_BATTERY_TYPE_RID, RW_OPT, STRING),
	OBJ_FIELD_DATA(UCIFI_BATTERY_LOW_THESHOLD_RID, RW_OPT, U8),
	OBJ_FIELD_DATA(UCIFI_BATTERY_LEVEL_TOO_LOW_RID, R_OPT, BOOL),
	OBJ_FIELD_DATA(UCIFI_BATTERY_SHUTDOWN_RID, RW_OPT, BOOL),
	OBJ_FIELD_DATA(UCIFI_BATTERY_NUM_CYCLES_RID, R_OPT, U32),
	OBJ_FIELD_DATA(UCIFI_BATTERY_SUPPLY_LOSS_RID, R_OPT, BOOL),
	OBJ_FIELD_DATA(UCIFI_BATTERY_SUPPLY_LOSS_COUNTER_RID, R_OPT, U32),
	OBJ_FIELD_EXECUTE_OPT(UCIFI_BATTERY_SUPPLY_LOSS_COUNTER_RESET_RID),
	OBJ_FIELD_DATA(UCIFI_BATTERY_SUPPLY_LOSS_REASON_RID, R_OPT, STRING),
};

static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][BATTERY_MAX_ID];
static struct lwm2m_engine_res_inst res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];

static void clear_supply_loss_counter(uint16_t obj_inst_id, int index)
{
	supply_loss_counter[index] = 0;
	NOTIFY_OBSERVER(UCIFI_OBJECT_BATTERY_ID, obj_inst_id,
			UCIFI_BATTERY_SUPPLY_LOSS_COUNTER_RID);
}

static int supply_loss_counter_reset_cb(uint16_t obj_inst_id, uint8_t *args, uint16_t args_len)
{
	int i;

	LOG_DBG("RESET supply loss counter %d", obj_inst_id);
	for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
		if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
			clear_supply_loss_counter(obj_inst_id, i);
			return 0;
		}
	}

	return -ENOENT;
}

static struct lwm2m_engine_obj_inst *battery_create(uint16_t obj_inst_id)
{
	int index, i = 0, j = 0;

	/* Check that there is no other instance with this ID */
	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
		if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
			LOG_ERR("Can not create instance - "
				"already existing: %u",
				obj_inst_id);
			return NULL;
		}
	}

	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
		if (!inst[index].obj) {
			break;
		}
	}

	if (index >= MAX_INSTANCE_COUNT) {
		LOG_ERR("Can not create instance - no more room: %u", obj_inst_id);
		return NULL;
	}

	/* Set default values */
	battery_level[index] = 0;
	supply_loss_counter[index] = 0;

	(void)memset(res[index], 0, sizeof(res[index][0]) * ARRAY_SIZE(res[index]));
	init_res_instance(res_inst[index], ARRAY_SIZE(res_inst[index]));

	/* initialize instance resource data */
	INIT_OBJ_RES_DATA(UCIFI_BATTERY_LEVEL_RID, res[index], i, res_inst[index], j,
			  &battery_level[index], sizeof(*battery_level));
	INIT_OBJ_RES_OPTDATA(UCIFI_BATTERY_CAPACITY_RID, res[index], i, res_inst[index], j);
	INIT_OBJ_RES_OPTDATA(UCIFI_BATTERY_VOLTAGE_RID, res[index], i, res_inst[index], j);
	INIT_OBJ_RES_OPTDATA(UCIFI_BATTERY_TYPE_RID, res[index], i, res_inst[index], j);
	INIT_OBJ_RES_OPTDATA(UCIFI_BATTERY_LOW_THESHOLD_RID, res[index], i, res_inst[index], j);
	INIT_OBJ_RES_OPTDATA(UCIFI_BATTERY_LEVEL_TOO_LOW_RID, res[index], i, res_inst[index], j);
	INIT_OBJ_RES_OPTDATA(UCIFI_BATTERY_SHUTDOWN_RID, res[index], i, res_inst[index], j);
	INIT_OBJ_RES_OPTDATA(UCIFI_BATTERY_NUM_CYCLES_RID, res[index], i, res_inst[index], j);
	INIT_OBJ_RES_OPTDATA(UCIFI_BATTERY_SUPPLY_LOSS_RID, res[index], i, res_inst[index], j);
	INIT_OBJ_RES_DATA(UCIFI_BATTERY_SUPPLY_LOSS_COUNTER_RID, res[index], i, res_inst[index], j,
			  &supply_loss_counter[index], sizeof(*supply_loss_counter));
	INIT_OBJ_RES_EXECUTE(UCIFI_BATTERY_SUPPLY_LOSS_COUNTER_RESET_RID, res[index], i,
			     supply_loss_counter_reset_cb);
	INIT_OBJ_RES_OPTDATA(UCIFI_BATTERY_SUPPLY_LOSS_REASON_RID, res[index], i, res_inst[index],
			     j);

	inst[index].resources = res[index];
	inst[index].resource_count = i;
	LOG_DBG("Create uCIFI Battery instance: %d", obj_inst_id);
	return &inst[index];
}

static int ucifi_battery_init(const struct device *dev)
{
	battery.obj_id = UCIFI_OBJECT_BATTERY_ID;
	battery.version_major = BATTERY_VERSION_MAJOR;
	battery.version_minor = BATTERY_VERSION_MINOR;
	battery.is_core = false;
	battery.fields = fields;
	battery.field_count = ARRAY_SIZE(fields);
	battery.max_instance_count = MAX_INSTANCE_COUNT;
	battery.create_cb = battery_create;
	lwm2m_register_obj(&battery);

	return 0;
}

SYS_INIT(ucifi_battery_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
