/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2017  Intel Corporation. All rights reserved.
 *
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <inttypes.h>
#include <stdbool.h>
#include <sys/uio.h>
#include <wordexp.h>

#include <glib.h>

#include "src/shared/util.h"
#include "src/shared/shell.h"
#include "mesh/mesh-net.h"
#include "mesh/keys.h"
#include "mesh/net.h"
#include "mesh/node.h"
#include "mesh/prov-db.h"
#include "mesh/util.h"
#include "mesh/config-model.h"

static bool server_msg_recvd(uint16_t src, uint8_t *data,
				uint16_t len, void *user_data)
{
	uint32_t opcode;
	uint8_t msg[32];
	struct mesh_node *node;
	uint16_t primary;
	uint32_t mod_id;
	uint16_t ele_addr;
	uint8_t ele_idx;
	struct mesh_publication pub;
	int m, n;

	if (mesh_opcode_get(data, len, &opcode, &n)) {
		len -= n;
		data += n;
	} else
		return false;

	node = node_get_local_node();

	if (!node)
		return true;

	n = 0;

	switch (opcode & ~OP_UNRELIABLE) {
	default:
		return false;

	case OP_CONFIG_DEFAULT_TTL_SET:
		if (len != 1 || data[0] > TTL_MASK || data[0] == 1)
			return true;

		if (data[0] <= TTL_MASK) {
			node_set_default_ttl(node, data[0]);
			prov_db_node_set_ttl(node, data[0]);
		}

		/* Fall Through */

	case OP_CONFIG_DEFAULT_TTL_GET:
		n = mesh_opcode_set(OP_CONFIG_DEFAULT_TTL_STATUS, msg);
		msg[n++] = node_get_default_ttl(node);
		break;

	case OP_CONFIG_MODEL_PUB_SET:

		if (len != 11 && len != 13)
			return true;

		bt_shell_printf("Set publication\n");

		ele_addr = get_le16(data);
		mod_id = get_le16(data + 9);
		if (len == 14)
			mod_id = (mod_id << 16)  | get_le16(data + 11);
		else
			mod_id |= 0xffff0000;

		pub.u.addr16 = get_le16(data + 2);
		pub.app_idx = get_le16(data + 4);
		pub.ttl = data[6];
		pub.period = data[7];
		m = (data[7] & 0x3f);
		switch (data[7] >> 6) {
		case 0:
			bt_shell_printf("Period: %d ms\n", m * 100);
			break;
		case 2:
			m *= 10;
			/* fall through */
		case 1:
			bt_shell_printf("Period: %d sec\n", m);
			break;
		case 3:
			bt_shell_printf("Period: %d min\n", m * 10);
			break;
		}

		pub.retransmit = data[8];
		bt_shell_printf("Retransmit count: %d\n", data[8] >> 5);
		bt_shell_printf("Retransmit Interval Steps: %d\n",
				data[8] & 0x1f);

		ele_idx = ele_addr - node_get_primary(node);

		if (node_model_pub_set(node, ele_idx, mod_id, &pub)) {
			prov_db_node_set_model_pub(node, ele_idx, mod_id,
				     node_model_pub_get(node, ele_idx, mod_id));
		}
		break;
	}

	if (!n)
		return true;

	primary = node_get_primary(node);
	if (src != primary)
		net_access_layer_send(node_get_default_ttl(node), primary,
					src, APP_IDX_DEV, msg, n);
	else
		node_local_data_handler(primary, src, node_get_iv_index(node),
					node_get_sequence_number(node),
					APP_IDX_DEV, msg, n);
	return true;
}


static struct mesh_model_ops server_cbs = {
	server_msg_recvd,
		NULL,
		NULL,
		NULL
};

bool config_server_init(void)
{
	if (!node_local_model_register(PRIMARY_ELEMENT_IDX,
						CONFIG_SERVER_MODEL_ID,
						&server_cbs, NULL))
		return false;

	return true;
}
