#ifndef MLD_H
#define MLD_H
#if (EASYMESH_VERSION >= 6)

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

#include <libubox/blobmsg.h>
#include <libubox/list.h>
#include <libubus.h>
#include <easy/easy.h>
#include <wifiutils.h>

#include "agent.h"

struct wifi7_radio_capabilities;
struct netif_bk;
struct netif_ap;
struct bsta_mld;
struct sta;

struct netif_mld {
	uint8_t id;
	char ifname[16];
	int channel;
	int bandwidth;
	uint8_t macaddr[6];
	char ssid[33];
	char standard[32];
	char radio_name[16];
	bool enabled;
	bool torndown;
	uint32_t obj_id;

	bool ap_str_enabled;
	bool ap_nstr_enabled;
	bool ap_emlsr_enabled;
	bool ap_emlmr_enabled;

	struct agent *agent;
	struct list_head stamldlist;

	int num_affiliated_ap;
#define MAX_AFFILIATED_AP_LINKS_NUM 14
        uint8_t affiliated_ap[MAX_AFFILIATED_AP_LINKS_NUM][6];

	struct list_head list;
};


struct bsta_mld {
	uint8_t macaddr[6];
	uint8_t bssid[6];
	char ifname[16];

	struct netif_bk bk; /* mld dev */
	struct netif_bk *setup_link;

	bool str_enabled;
	bool nstr_enabled;
	bool emlsr_enabled;
	bool emlmr_enabled;

	int num_affiliated_bsta;
#define MAX_AFFILIATED_BSTA_LINKS_NUM 14
	uint8_t affiliated_bsta[MAX_AFFILIATED_BSTA_LINKS_NUM][6];

	struct list_head list;
};

struct sta_mld {
	uint8_t macaddr[6];
	uint8_t bssid[6];

	bool str_enabled;
	bool nstr_enabled;
	bool emlsr_enabled;
	bool emlmr_enabled;

	int num_affiliated_sta;
#define MAX_AFFILIATED_STA_LINKS_NUM 14
        uint8_t affiliated_sta[MAX_AFFILIATED_STA_LINKS_NUM][6];

	struct list_head list;
};


struct sta_mld *stamld_update(struct agent *a, struct netif_ap *ap,
			      uint8_t *mld_macaddr, uint8_t *mld_bssid,
			      uint8_t mlo_link_id, struct sta *s);

int mld_add_ap(struct agent *a, struct netif_mld *mld,
				uint8_t *macaddr);
int mld_add_sta(struct agent *a, struct sta_mld *mld,
				uint8_t *macaddr);
int mld_add_bsta(struct agent *a, struct bsta_mld *mld,
				uint8_t *macaddr);
int mld_del_sta(struct agent *a, struct sta *s);
int mld_del_bsta(struct agent *a, struct netif_bk *bk);
int mld_del_ap(struct agent *a, struct netif_ap *ap);

int wifi_process_ml_ie(struct agent *a, struct sta_mld *stamld,
                       uint8_t *assocframe, int framelen);

void mld_event_handler(void *agent, struct blob_attr *msg);
int mld_parse_affiliated_ap(struct ubus_request *req, int type,
		struct blob_attr *msg);
void parse_apmld_stats(struct ubus_request *req, int type,
		       struct blob_attr *msg);
void apmld_parse(struct ubus_request *req, int type,
		struct blob_attr *msg);
void mld_parse_affiliated_bsta(struct agent *a, struct bsta_mld *mld,
				 struct netif_bk *bk, int type,
				 struct blob_attr *msg);
void bstamld_parse(struct ubus_request *req, int type,
		struct blob_attr *msg);

struct netif_mld *agent_get_apmld(struct agent *a, uint8_t *macaddr);
struct netif_mld *agent_get_apmld_by_id(struct agent *a, uint8_t id);
struct netif_mld *agent_get_apmld_by_ifname(struct agent *a, const char *ifname);
struct netif_mld *agent_alloc_apmld(struct agent *a, const char *ifname);
void apmld_refresh_stations(struct agent *a, struct netif_mld *mld);

bool mld_contains_ap(struct agent *a, struct netif_mld *mld,
                        uint8_t *macaddr);
bool mld_contains_sta(struct agent *a, struct sta_mld *mld,
                        uint8_t *macaddr);
bool mld_contains_bsta(struct agent *a, struct bsta_mld *mld,
                        uint8_t *macaddr);

struct sta_mld *agent_get_stamld(struct agent *a, uint8_t *macaddr);
struct sta_mld *agent_alloc_stamld(struct agent *a, struct netif_mld *mld,
                                uint8_t *macaddr);
struct bsta_mld *agent_alloc_bstamld(struct agent *a, const char *ifname);
struct bsta_mld *agent_init_bstamld(struct agent *a, char *ifname,
                                struct wifi7_radio_capabilities *caps);

void stamld_clean(struct agent *a, struct sta_mld *mld);
void stamld_free(struct agent *a, struct sta_mld *mld);
void bstamld_clean(struct agent *a, struct bsta_mld *mld);
void agent_clear_bsta_mld(struct agent *a);
void apmld_clean(struct agent *a, struct netif_mld *mld);
void apmld_free(struct agent *a, struct netif_mld *mld);
void apmld_free_all(struct agent *a);
void clear_apmldlist(struct agent *a);
int bstamld_teardown_band(struct agent *a, enum wifi_band band);

bool is_affiliated_ap(struct agent *a, uint8_t *bssid);
bool agent_radio_support_ap_mlo(struct wifi7_radio_capabilities *wifi7_caps);
bool agent_radio_support_bsta_mlo(struct wifi7_radio_capabilities *wifi7_caps);

void mld_set_config_id(char *ifname, uint8_t mld_id);
#endif
#endif
