#include "backhaul_topology_dbg.h"
#include "backhaul_topology.h"
#include "debug.h"
#include "utils.h"

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

#define BH_TOPO_PREFIX "BH:"

static const char *get_prefix(enum dbg_bh_topo_indent_lvl indent_level)
{
	switch (indent_level) {
	case INDENT_LVL_0: return BH_TOPO_PREFIX;
	case INDENT_LVL_1: return BH_TOPO_PREFIX"  ";
	case INDENT_LVL_2: return BH_TOPO_PREFIX"    ";
	case INDENT_LVL_3: return BH_TOPO_PREFIX"      ";
	default:           return BH_TOPO_PREFIX"        ";
	}
}


void dbg_dump_bh_topo_backhaul_info(const struct backhaul_info *bh_info,
				    enum dbg_bh_topo_indent_lvl indent_lvl)
{
	const char *pref = get_prefix(indent_lvl);

	dbg("%s backhaul_info:\n", pref);

	if (bh_info->level_in_tree == UNKNOWN_TREE_LEVEL) {
		dbg("%s .level_in_tree: %s\n", pref, "UNKNOWN_TREE_LEVEL");
	} else {
		dbg("%s .level_in_tree: %d\n", pref, bh_info->level_in_tree);
		dbg("%s .wifi_hops_from_root: %d\n", pref, bh_info->wifi_hops_from_root);
	}

	if (bh_info->parent_in_tree) {
		dbg("%s .parent_in_tree: " MACFMT "\n", pref,
		    MAC2STR(bh_info->parent_in_tree->al_macaddr));
	}

	if (bh_info->parent_iface) {
		dbg("%s .parent_iface: " MACFMT "\n", pref,
		    MAC2STR(bh_info->parent_iface->macaddr));
	}

	if (bh_info->own_iface) {
		dbg("%s .own_iface: " MACFMT "\n", pref,
		    MAC2STR(bh_info->own_iface->macaddr));
	}
}

void dbg_dump_bh_topo_local_iface(const struct local_iface *local_iface,
				  enum dbg_bh_topo_indent_lvl indent_lvl)
{
	const char *pref = get_prefix(indent_lvl);
	int i;

	dbg("%s local_iface:\n", pref);
	dbg("%s .macaddr: " MACFMT "\n", pref, MAC2STR(local_iface->macaddr));
	dbg("%s .media_type: %s\n", pref,
	    i1905_media_type_to_str(local_iface->media_type));
	dbg("%s .number_of_neighbors: %u\n", pref, local_iface->number_of_neighbors);

	for (i = 0; i < local_iface->number_of_neighbors; ++i) {
		dbg("%s .neigh_al_mac[%d]: " MACFMT "\n",
			pref, i, MAC2STR(&local_iface->neighbors_al_macs[i][0]));
	}
}

void dbg_dump_bh_topo_dev(const struct bh_topology_dev *bh_topo_dev,
			  enum dbg_bh_topo_indent_lvl indent_lvl)
{
	const char *pref = get_prefix(indent_lvl);
	int i;

	dbg("%s bh_topology_dev:\n", pref);
	dbg("%s .last_topo_response: %u\n", pref, timestamp_elapsed_sec(&bh_topo_dev->last_topo_response));
	dbg("%s .al_macaddr: " MACFMT "\n", pref, MAC2STR(bh_topo_dev->al_macaddr));
	dbg("%s .number_of_interfaces: %d\n", pref, bh_topo_dev->number_of_interfaces);
	dbg("%s .num_of_ifaces_with_neighbors: %d\n", pref, bh_topo_dev->num_of_ifaces_with_neighbors);

	for (i = 0; i < bh_topo_dev->number_of_interfaces; ++i) {
		dbg("%s .iface[%d]:\n", pref, i);
		dbg_dump_bh_topo_local_iface(&bh_topo_dev->ifaces[i], indent_lvl + 1);
	}

	dbg("%s .bh_info:\n", pref);
	dbg_dump_bh_topo_backhaul_info(&bh_topo_dev->bh_info, indent_lvl + 1);

}

void dbg_dump_bh_topo_devs(const struct list_head *bh_topo_dev_list,
			   enum dbg_bh_topo_indent_lvl indent_lvl)
{
	const char *pref = get_prefix(indent_lvl);
	const struct bh_topology_dev *bh_topo_dev = NULL;
	int i = 0;

	dbg("%s =============== %s ===============\n", pref, __func__);

	list_for_each_entry(bh_topo_dev, bh_topo_dev_list, list_element) {
		dbg("%s bh_topo_dev[%d]:\n", pref, i++);
		dbg_dump_bh_topo_dev(bh_topo_dev, ++indent_lvl);

	}

	dbg("%s ============ END %s ==============\n", pref, __func__);
}

void dbg_dump_bh_topo_link(const struct bh_topology_dev *bh_topo_dev,
			   enum dbg_bh_topo_indent_lvl indent_lvl)
{
	const char *pref = get_prefix(indent_lvl);
	const struct bh_topology_dev *parent_dev =
		bh_topo_dev->bh_info.parent_in_tree;
	const struct local_iface *parent_iface =
		bh_topo_dev->bh_info.parent_iface;
	const struct local_iface *own_iface =
		bh_topo_dev->bh_info.own_iface;

	if (bh_topo_dev->bh_info.level_in_tree == UNKNOWN_TREE_LEVEL) {
		dbg("%s child level: %s\n", pref, "UNKNOWN_TREE_LEVEL");
	} else {
		dbg("%s child level: %d\n", pref, bh_topo_dev->bh_info.level_in_tree);
	}

	dbg("%s child wifi_hops_from_root: %d\n", pref, bh_topo_dev->bh_info.wifi_hops_from_root);
	dbg("%s child almac: " MACFMT "\n", pref, MAC2STR(bh_topo_dev->al_macaddr));

	if (own_iface) {
		dbg("%s child iface: " MACFMT "\n", pref, MAC2STR(own_iface->macaddr));
	}

	if (parent_dev) {
		dbg("%s parent level: %d\n", pref, parent_dev->bh_info.level_in_tree);
		dbg("%s parent almac: " MACFMT "\n", pref, MAC2STR(parent_dev->al_macaddr));
	}

	if (parent_iface) {
		dbg("%s parent iface: " MACFMT "\n", pref, MAC2STR(parent_iface->macaddr));
		dbg("%s media: %s\n", pref, i1905_media_type_to_str(parent_iface->media_type));
	}
}

