/*
 * stomp_dm.c - Library for STOMP datamodel
 *
 * Copyright (C) 2024, IOPSYS Software Solutions AB.
 *
 * Author Suvendhu Hansa <suvendhu.hansa@iopsys.eu>
 *
 * See LICENSE file for license related information.
 *
 */

#ifndef DISABLE_STOMP
#include "stomp_dm.h"

/*************************************************************
* ENTRY METHOD
**************************************************************/
static int browseSTOMPConnectionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	char cmd[MAX_CMD_LEN] = {0};
	const char *dm_path = "Device.STOMP.Connection.";
	json_object *con_ob = NULL;

	LIST_HEAD(result_list);
	snprintf(cmd, sizeof(cmd), "%s %s | grep \"%s\" | grep -v CMD_", PROG_CMD_GET, dm_path, dm_path);
	exec_cmd(cmd, &result_list);

	con_ob = json_object_new_object();
	if (con_ob == NULL) {
		delete_cmd_result(&result_list);
		return 0;
	}

	convert_list_to_json(con_ob, &result_list);
	delete_cmd_result(&result_list);

	json_object *obj = dmjson_get_obj(con_ob, 3, "Device", "STOMP", "Connection");

	if (obj && json_object_is_type(obj, json_type_array)) {
		int idx = 0;
		int con_count = json_object_array_length(obj);

		for (idx = 0; idx < con_count; idx++) {
			json_object *curr = json_object_array_get_idx(obj, idx);
			if (curr == NULL) {
				continue;
			}

			char path[MAX_PATH_LEN] = {0};
			snprintf(path, sizeof(path), "Device.STOMP.Connection.%d", idx+1);

			struct dm_data data = {0};
			data.json_object = curr;
			data.additional_data = (void *)dmstrdup(path);

			char *inst = handle_instance_without_section(dmctx, parent_node, idx+1);
			if (DM_LINK_INST_OBJ(dmctx, parent_node, &data, inst) == DM_STOP)
				break;
		}
	}

	if (con_ob != NULL) {
		json_object_put(con_ob);
		con_ob = NULL;
	}

	return 0;
}

/*************************************************************
* ADD & DEL OBJ
**************************************************************/
static int addObjSTOMPConnection(char *refparam, struct dmctx *ctx, void *data, char **instance)
{
	char param_path[MAX_PATH_LEN] = {0};

	snprintf(param_path, sizeof(param_path), "Device.STOMP.Connection.");
	return get_instance_number(param_path, instance);
}

static int delObjSTOMPConnection(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
{
	char param_path[MAX_PATH_LEN] = {0};
	struct dm_data *p = (struct dm_data *)data;

	switch (del_action) {
		case DEL_INST:
			snprintf(param_path, sizeof(param_path), "%s.", (char *)p->additional_data);
			break;
		case DEL_ALL:
			snprintf(param_path, sizeof(param_path), "Device.STOMP.Connection.*.");
			break;
	}

	return deletion_succeed(param_path);
}

/*************************************************************
* GET & SET PARAM
**************************************************************/
static int get_STOMP_ConnectionNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char cmd[MAX_CMD_LEN] = {0};
	const char *dm_path = "Device.STOMP.ConnectionNumberOfEntries";

	LIST_HEAD(result_list);
	snprintf(cmd, sizeof(cmd), "%s %s | grep \"%s =>\"", PROG_CMD_GET, dm_path, dm_path);
	exec_cmd(cmd, &result_list);

	collect_value(dm_path, &result_list, value);
	delete_cmd_result(&result_list);

	return 0;
}

static int get_STOMPConnection_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *ob_data = (struct dm_data *)data;

	*value = dmjson_get_value(ob_data->json_object, 1, "Alias");
	return 0;
}

static int set_STOMPConnection_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char param_path[MAX_PATH_LEN] = {0};
	int ret = FAULT_9002;

	struct dm_data *ob_data = (struct dm_data *)data;
	char *dm_path = (char *)ob_data->additional_data;

	if (DM_STRLEN(dm_path) == 0) {
		return ret;
	}

	switch (action) {
	case VALUECHECK:
		if (bbfdm_validate_string(ctx, value, -1, 64, NULL, NULL)) {
			ret = FAULT_9007;
			break;
		}

		ret = 0;
		break;
	case VALUESET:
		snprintf(param_path, sizeof(param_path), "%s.Alias", dm_path);
		ret = set_succeed(param_path, value);
		break;
	}

	return ret;
}

static int get_STOMPConnection_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *ob_data = (struct dm_data *)data;

	*value = dmjson_get_value(ob_data->json_object, 1, "Enable");
	return 0;
}

static int set_STOMPConnection_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char param_path[MAX_PATH_LEN] = {0};
	int ret = FAULT_9002;

	struct dm_data *ob_data = (struct dm_data *)data;
	char *dm_path = (char *)ob_data->additional_data;

	if (DM_STRLEN(dm_path) == 0) {
		return ret;
	}

	switch (action) {
	case VALUECHECK:
		if (bbfdm_validate_boolean(ctx, value)) {
			ret = FAULT_9007;
			break;
		}

		ret = 0;
		break;
	case VALUESET:
		snprintf(param_path, sizeof(param_path), "%s.Enable", dm_path);
		ret = set_succeed(param_path, value);
		break;
	}

	return ret;
}

static int get_STOMPConnection_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *ob_data = (struct dm_data *)data;

	*value = dmjson_get_value(ob_data->json_object, 1, "Status");
	return 0;
}

static int get_STOMPConnection_LastChangeDate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *ob_data = (struct dm_data *)data;

	*value = dmjson_get_value(ob_data->json_object, 1, "LastChangeDate");
	return 0;
}

static int get_STOMPConnection_Host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *ob_data = (struct dm_data *)data;

	*value = dmjson_get_value(ob_data->json_object, 1, "Host");
	return 0;
}

static int set_STOMPConnection_Host(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char param_path[MAX_PATH_LEN] = {0};
	int ret = FAULT_9002;

	struct dm_data *ob_data = (struct dm_data *)data;
	char *dm_path = (char *)ob_data->additional_data;

	if (DM_STRLEN(dm_path) == 0) {
		return ret;
	}

	switch (action) {
	case VALUECHECK:
		if (bbfdm_validate_string(ctx, value, -1, 256, NULL, NULL)) {
			ret = FAULT_9007;
			break;
		}

		ret = 0;
		break;
	case VALUESET:
		snprintf(param_path, sizeof(param_path), "%s.Host", dm_path);
		ret = set_succeed(param_path, value);
		break;
	}

	return ret;
}

static int get_STOMPConnection_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *ob_data = (struct dm_data *)data;

	*value = dmjson_get_value(ob_data->json_object, 1, "Port");
	return 0;
}

static int set_STOMPConnection_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char param_path[MAX_PATH_LEN] = {0};
	int ret = FAULT_9002;

	struct dm_data *ob_data = (struct dm_data *)data;
	char *dm_path = (char *)ob_data->additional_data;

	if (DM_STRLEN(dm_path) == 0) {
		return ret;
	}

	switch (action) {
	case VALUECHECK:
		if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1","65535"}}, 1)) {
			ret = FAULT_9007;
			break;
		}

		ret = 0;
		break;
	case VALUESET:
		snprintf(param_path, sizeof(param_path), "%s.Port", dm_path);
		ret = set_succeed(param_path, value);
		break;
	}

	return ret;
}

static int get_STOMPConnection_Username(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *ob_data = (struct dm_data *)data;

	*value = dmjson_get_value(ob_data->json_object, 1, "Username");
	return 0;
}

static int set_STOMPConnection_Username(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char param_path[MAX_PATH_LEN] = {0};
	int ret = FAULT_9002;

	struct dm_data *ob_data = (struct dm_data *)data;
	char *dm_path = (char *)ob_data->additional_data;

	if (DM_STRLEN(dm_path) == 0) {
		return ret;
	}

	switch (action) {
	case VALUECHECK:
		if (bbfdm_validate_string(ctx, value, -1, 256, NULL, NULL)) {
			ret = FAULT_9007;
			break;
		}

		ret = 0;
		break;
	case VALUESET:
		snprintf(param_path, sizeof(param_path), "%s.Username", dm_path);
		ret = set_succeed(param_path, value);
		break;
	}

	return ret;
}

static int get_STOMPConnection_Password(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *ob_data = (struct dm_data *)data;

	*value = dmjson_get_value(ob_data->json_object, 1, "Password");
	return 0;
}

static int set_STOMPConnection_Password(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char param_path[MAX_PATH_LEN] = {0};
	int ret = FAULT_9002;

	struct dm_data *ob_data = (struct dm_data *)data;
	char *dm_path = (char *)ob_data->additional_data;

	if (DM_STRLEN(dm_path) == 0) {
		return ret;
	}

	switch (action) {
	case VALUECHECK:
		if (bbfdm_validate_string(ctx, value, -1, 256, NULL, NULL)) {
			ret = FAULT_9007;
			break;
		}

		ret = 0;
		break;
	case VALUESET:
		snprintf(param_path, sizeof(param_path), "%s.Password", dm_path);
		ret = set_succeed(param_path, value);
		break;
	}

	return ret;
}

static int get_STOMPConnection_VirtualHost(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *ob_data = (struct dm_data *)data;

	*value = dmjson_get_value(ob_data->json_object, 1, "VirtualHost");
	return 0;
}

static int set_STOMPConnection_VirtualHost(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char param_path[MAX_PATH_LEN] = {0};
	int ret = FAULT_9002;

	struct dm_data *ob_data = (struct dm_data *)data;
	char *dm_path = (char *)ob_data->additional_data;

	if (DM_STRLEN(dm_path) == 0) {
		return ret;
	}

	switch (action) {
	case VALUECHECK:
		if (bbfdm_validate_string(ctx, value, -1, 256, NULL, NULL)) {
			ret = FAULT_9007;
			break;
		}

		ret = 0;
		break;
	case VALUESET:
		snprintf(param_path, sizeof(param_path), "%s.VirtualHost", dm_path);
		ret = set_succeed(param_path, value);
		break;
	}

	return ret;
}

static int get_STOMPConnection_EnableHeartbeats(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *ob_data = (struct dm_data *)data;

	*value = dmjson_get_value(ob_data->json_object, 1, "EnableHeartbeats");
	return 0;
}

static int set_STOMPConnection_EnableHeartbeats(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char param_path[MAX_PATH_LEN] = {0};
	int ret = FAULT_9002;

	struct dm_data *ob_data = (struct dm_data *)data;
	char *dm_path = (char *)ob_data->additional_data;

	if (DM_STRLEN(dm_path) == 0) {
		return ret;
	}

	switch (action) {
	case VALUECHECK:
		if (bbfdm_validate_boolean(ctx, value)) {
			ret = FAULT_9007;
			break;
		}

		ret = 0;
		break;
	case VALUESET:
		snprintf(param_path, sizeof(param_path), "%s.EnableHeartbeats", dm_path);
		ret = set_succeed(param_path, value);
		break;
	}

	return ret;
}

static int get_STOMPConnection_OutgoingHeartbeat(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *ob_data = (struct dm_data *)data;

	*value = dmjson_get_value(ob_data->json_object, 1, "OutgoingHeartbeat");
	return 0;
}

static int set_STOMPConnection_OutgoingHeartbeat(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char param_path[MAX_PATH_LEN] = {0};
	int ret = FAULT_9002;

	struct dm_data *ob_data = (struct dm_data *)data;
	char *dm_path = (char *)ob_data->additional_data;

	if (DM_STRLEN(dm_path) == 0) {
		return ret;
	}

	switch (action) {
	case VALUECHECK:
		if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{NULL,NULL}}, 1)) {
			ret = FAULT_9007;
			break;
		}

		ret = 0;
		break;
	case VALUESET:
		snprintf(param_path, sizeof(param_path), "%s.OutgoingHeartbeat", dm_path);
		ret = set_succeed(param_path, value);
		break;
	}

	return ret;
}

static int get_STOMPConnection_IncomingHeartbeat(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *ob_data = (struct dm_data *)data;

	*value = dmjson_get_value(ob_data->json_object, 1, "IncomingHeartbeat");
	return 0;
}

static int set_STOMPConnection_IncomingHeartbeat(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char param_path[MAX_PATH_LEN] = {0};
	int ret = FAULT_9002;

	struct dm_data *ob_data = (struct dm_data *)data;
	char *dm_path = (char *)ob_data->additional_data;

	if (DM_STRLEN(dm_path) == 0) {
		return ret;
	}

	switch (action) {
	case VALUECHECK:
		if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{NULL,NULL}}, 1)) {
			ret = FAULT_9007;
			break;
		}

		ret = 0;
		break;
	case VALUESET:
		snprintf(param_path, sizeof(param_path), "%s.IncomingHeartbeat", dm_path);
		ret = set_succeed(param_path, value);
		break;
	}

	return ret;
}

static int get_STOMPConnection_ServerRetryInitialInterval(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *ob_data = (struct dm_data *)data;

	*value = dmjson_get_value(ob_data->json_object, 1, "ServerRetryInitialInterval");
	return 0;
}

static int set_STOMPConnection_ServerRetryInitialInterval(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char param_path[MAX_PATH_LEN] = {0};
	int ret = FAULT_9002;

	struct dm_data *ob_data = (struct dm_data *)data;
	char *dm_path = (char *)ob_data->additional_data;

	if (DM_STRLEN(dm_path) == 0) {
		return ret;
	}

	switch (action) {
	case VALUECHECK:
		if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1","65535"}}, 1)) {
			ret = FAULT_9007;
			break;
		}

		ret = 0;
		break;
	case VALUESET:
		snprintf(param_path, sizeof(param_path), "%s.ServerRetryInitialInterval", dm_path);
		ret = set_succeed(param_path, value);
		break;
	}

	return ret;
}

static int get_STOMPConnection_ServerRetryIntervalMultiplier(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *ob_data = (struct dm_data *)data;

	*value = dmjson_get_value(ob_data->json_object, 1, "ServerRetryIntervalMultiplier");
	return 0;
}

static int set_STOMPConnection_ServerRetryIntervalMultiplier(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char param_path[MAX_PATH_LEN] = {0};
	int ret = FAULT_9002;

	struct dm_data *ob_data = (struct dm_data *)data;
	char *dm_path = (char *)ob_data->additional_data;

	if (DM_STRLEN(dm_path) == 0) {
		return ret;
	}

	switch (action) {
	case VALUECHECK:
		if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1000","65535"}}, 1)) {
			ret = FAULT_9007;
			break;
		}

		ret = 0;
		break;
	case VALUESET:
		snprintf(param_path, sizeof(param_path), "%s.ServerRetryIntervalMultiplier", dm_path);
		ret = set_succeed(param_path, value);
		break;
	}

	return ret;
}

static int get_STOMPConnection_ServerRetryMaxInterval(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *ob_data = (struct dm_data *)data;

	*value = dmjson_get_value(ob_data->json_object, 1, "ServerRetryMaxInterval");
	return 0;
}

static int set_STOMPConnection_ServerRetryMaxInterval(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char param_path[MAX_PATH_LEN] = {0};
	int ret = FAULT_9002;

	struct dm_data *ob_data = (struct dm_data *)data;
	char *dm_path = (char *)ob_data->additional_data;

	if (DM_STRLEN(dm_path) == 0) {
		return ret;
	}

	switch (action) {
	case VALUECHECK:
		if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1",NULL}}, 1)) {
			ret = FAULT_9007;
			break;
		}

		ret = 0;
		break;
	case VALUESET:
		snprintf(param_path, sizeof(param_path), "%s.ServerRetryMaxInterval", dm_path);
		ret = set_succeed(param_path, value);
		break;
	}

	return ret;
}

static int get_STOMPConnection_EnableEncryption(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct dm_data *ob_data = (struct dm_data *)data;

	*value = dmjson_get_value(ob_data->json_object, 1, "EnableEncryption");
	return 0;
}

static int set_STOMPConnection_EnableEncryption(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char param_path[MAX_PATH_LEN] = {0};
	int ret = FAULT_9002;

	struct dm_data *ob_data = (struct dm_data *)data;
	char *dm_path = (char *)ob_data->additional_data;

	if (DM_STRLEN(dm_path) == 0) {
		return ret;
	}

	switch (action) {
	case VALUECHECK:
		if (bbfdm_validate_boolean(ctx, value)) {
			ret = FAULT_9007;
			break;
		}

		ret = 0;
		break;
	case VALUESET:
		snprintf(param_path, sizeof(param_path), "%s.EnableEncryption", dm_path);
		ret = set_succeed(param_path, value);
		break;
	}

	return ret;
}

/**********************************************************************************************************************************
*                                            OBJ & PARAM DEFINITION
***********************************************************************************************************************************/
/* *** Device.STOMP. *** */
DMOBJ tSTOMPObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys */
{"Connection", &DMWRITE, addObjSTOMPConnection, delObjSTOMPConnection, NULL, browseSTOMPConnectionInst, NULL, NULL, NULL, tSTOMPConnectionParams, NULL, BBFDM_CWMP, NULL},
{0}
};

DMLEAF tSTOMPParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"ConnectionNumberOfEntries", &DMREAD, DMT_UNINT, get_STOMP_ConnectionNumberOfEntries, NULL, BBFDM_CWMP},
{0}
};

/* *** Device.STOMP.Connection.{i}. *** */
DMLEAF tSTOMPConnectionParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"Alias", &DMWRITE, DMT_STRING, get_STOMPConnection_Alias, set_STOMPConnection_Alias, BBFDM_CWMP},
{"Enable", &DMWRITE, DMT_BOOL, get_STOMPConnection_Enable, set_STOMPConnection_Enable, BBFDM_CWMP},
{"Status", &DMREAD, DMT_STRING, get_STOMPConnection_Status, NULL, BBFDM_CWMP},
{"LastChangeDate", &DMREAD, DMT_TIME, get_STOMPConnection_LastChangeDate, NULL, BBFDM_CWMP},
{"Host", &DMWRITE, DMT_STRING, get_STOMPConnection_Host, set_STOMPConnection_Host, BBFDM_CWMP},
{"Port", &DMWRITE, DMT_UNINT, get_STOMPConnection_Port, set_STOMPConnection_Port, BBFDM_CWMP},
{"Username", &DMWRITE, DMT_STRING, get_STOMPConnection_Username, set_STOMPConnection_Username, BBFDM_CWMP},
{"Password", &DMWRITE, DMT_STRING, get_STOMPConnection_Password, set_STOMPConnection_Password, BBFDM_CWMP},
{"VirtualHost", &DMWRITE, DMT_STRING, get_STOMPConnection_VirtualHost, set_STOMPConnection_VirtualHost, BBFDM_CWMP},
{"EnableHeartbeats", &DMWRITE, DMT_BOOL, get_STOMPConnection_EnableHeartbeats, set_STOMPConnection_EnableHeartbeats, BBFDM_CWMP},
{"OutgoingHeartbeat", &DMWRITE, DMT_UNINT, get_STOMPConnection_OutgoingHeartbeat, set_STOMPConnection_OutgoingHeartbeat, BBFDM_CWMP},
{"IncomingHeartbeat", &DMWRITE, DMT_UNINT, get_STOMPConnection_IncomingHeartbeat, set_STOMPConnection_IncomingHeartbeat, BBFDM_CWMP},
{"ServerRetryInitialInterval", &DMWRITE, DMT_UNINT, get_STOMPConnection_ServerRetryInitialInterval, set_STOMPConnection_ServerRetryInitialInterval, BBFDM_CWMP},
{"ServerRetryIntervalMultiplier", &DMWRITE, DMT_UNINT, get_STOMPConnection_ServerRetryIntervalMultiplier, set_STOMPConnection_ServerRetryIntervalMultiplier, BBFDM_CWMP},
{"ServerRetryMaxInterval", &DMWRITE, DMT_UNINT, get_STOMPConnection_ServerRetryMaxInterval, set_STOMPConnection_ServerRetryMaxInterval, BBFDM_CWMP},
{"EnableEncryption", &DMWRITE, DMT_BOOL, get_STOMPConnection_EnableEncryption, set_STOMPConnection_EnableEncryption, BBFDM_CWMP},
{0}
};
#endif
