
#ifdef DYNBH
#include "dynbh_ubus.h"

#include <libubox/list.h>
#include <easy/easy.h>
#include <linux/if.h>

#include "agent.h"
#include "agent_ubus.h"
#include "dynbh.h"
#include "../utils/debug.h"
#include "../utils/utils.h"

static void i1905_modif(struct agent *a, struct ethport *port, bool add)
{
	const char *fn = (add ? "add_interface" : "del_interface");
	uint32_t uobj_id = WIFI_OBJECT_INVALID;
	struct blob_buf bb = {0};
	char objname[32];
	int ret;

	snprintf(objname, sizeof(objname), "ieee1905.al.%s", port->ifname);
	uobj_id = ubus_get_object(a->ubus_ctx, objname);
	if ((uobj_id == WIFI_OBJECT_INVALID && !add) ||
	    (uobj_id != WIFI_OBJECT_INVALID && add)) {
		agnt_trace(LOG_DYNBH, "%s: NO-OP case, objid:%u add:%d objname:%s\n", __func__,
			    uobj_id, add, objname);
		return;
	}

	blob_buf_init(&bb, 0);
	blobmsg_add_string(&bb, "ifname", port->ifname);
	ret = ubus_call_object_args(a->ubus_ctx, a->i1905obj_id, &bb, fn, NULL, NULL);
	if (ret)
		agnt_dbg(LOG_DYNBH, "%s: Failed to get '%s' (ret = %d) name:ieee1905\n", __func__, fn, ret);
	blob_buf_free(&bb);
}

void i1905_addif(struct agent *a, struct ethport *port)
{
	i1905_modif(a, port, true);
}

void i1905_delif(struct agent *a, struct ethport *port)
{
	i1905_modif(a, port, false);
}

const struct blobmsg_policy backhaul_status_params[__BACKHAUL_STATUS_MAX] = {
	[BACKHAUL_STATUS_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_STRING },
};

int dynbhd_status(struct ubus_context *ctx, struct ubus_object *obj,
			struct ubus_request_data *req, const char *method,
			struct blob_attr *msg)
{
	struct agent *a = container_of(obj, struct agent, obj);
	struct dynbh_ctx *c = &a->dbh;
	bool enabled = dynbh_is_enabled(a);
	struct blob_buf bb;
	struct ethport *port = NULL;
	struct wifi_radio_element *radio = NULL;
	struct blob_attr *tb[__BACKHAUL_STATUS_MAX];
	bool show_eth = true;
	bool show_wifi = true;
	void *ar;
	char macstr[18];

	blobmsg_parse(backhaul_status_params, __BACKHAUL_STATUS_MAX, tb, blob_data(msg), blob_len(msg));

	if (tb[BACKHAUL_STATUS_TYPE]) {
		const char *type = blobmsg_get_string(tb[BACKHAUL_STATUS_TYPE]);

		if (type) {
			if (!strncmp(type, "eth", 3))
				show_wifi = false;
			else if (!strncmp(type, "wifi", 4))
				show_eth = false;
		}
	}

	memset(&bb, 0, sizeof(bb));
	blob_buf_init(&bb, 0);

	blobmsg_add_u8(&bb, "enabled", enabled);
	if (!enabled)
		goto out;

	ar = blobmsg_open_array(&bb, "ports");

	if (show_eth) {
		list_for_each_entry(port, &c->ethportlist, list) {
			void *t;

			t = blobmsg_open_table(&bb, "");
			blobmsg_add_string(&bb, "type", "eth");
			blobmsg_add_string(&bb, "ifname", port->ifname);
			blobmsg_add_u8(&bb, "connected", (port->operstate == IF_OPER_UP));
			blobmsg_add_string(&bb, "state", port_state_to_str(port->state));

			blobmsg_close_table(&bb, t);
		}
	}

	if (show_wifi) {
		list_for_each_entry(radio, &a->radiolist, list) {
			struct netif_bk *bk = &radio->bk;
			void *t;

			if (!radio->has_bsta)
				continue;

			t = blobmsg_open_table(&bb, "");
			blobmsg_add_string(&bb, "type", "wifi");
			blobmsg_add_string(&bb, "ifname", bk->ifname);
			blobmsg_add_u8(&bb, "connected", bk->connected);
			hwaddr_ntoa(bk->bssid, macstr);
			blobmsg_add_string(&bb, "bssid", macstr);
			blobmsg_add_u32(&bb, "band", bk->cfg ? band_to_int(bk->cfg->band) : 0);

			blobmsg_close_table(&bb, t);
		}
	}

	blobmsg_close_array(&bb, ar);
out:
	ubus_send_reply(ctx, req, bb.head);
	blob_buf_free(&bb);
	return UBUS_STATUS_OK;
}
#endif

