#ifndef UTILS_H
#define UTILS_H

#include <libubox/list.h>
#include <sys/time.h>
#include <stdint.h>

const char *i1905_media_type_to_str(uint16_t media_type);

char *get_date(time_t *t, char *tbuf);

/** If t is NULL, get current time and return as null terminated string
 *  e.g.: "2019-02-11T06:42:31-08:00"
 *  If t is not NULL, covert t to formatted string.
 *
 *  Returns timestamp_str.
 */
char *get_timestamp(const time_t *t, char *timestamp_str, size_t size);
void do_daemonize(const char *pidfile);

int getcurrtime(struct timeval *out);
int timeradd_msecs(struct timeval *a, unsigned long msecs, struct timeval *res);

size_t list_count(const struct list_head *list);

uint8_t rssi_to_rcpi(int rssi);

#ifndef list_flush
#define list_flush(head, type, member)					\
do {									\
	type *__p, *__tmp;						\
									\
	if (!list_empty(head))						\
		list_for_each_entry_safe(__p, __tmp, head, member) {	\
			list_del(&__p->member);				\
			free(__p);					\
		}							\
} while (0)
#endif


typedef void (*ffn_type)(void *priv, void *list_entry);

#define list_limit_maxnum(priv, head, type, member, maxnum, ffn)	\
do {									\
	struct list_head *h = NULL, *t;					\
	ffn_type _ffn = ffn;						\
	int cnt = 0;							\
	list_for_each_prev_safe(h, t, head) {				\
		if (++cnt > maxnum) {					\
			list_del(h);					\
			cnt--;						\
			_ffn ? _ffn(priv, list_entry(h, type, member)) :\
			      free(list_entry(h, type, member));	\
		}							\
	}								\
} while (0)

typedef int (*cfn_type)(void *priv, void *list_entry, uint32_t ageout);

#define list_limit_maxage(priv, head, type, member, maxage, cfn, ffn)	\
do {									\
	type *e = NULL, *e_tmp;						\
	ffn_type _ffn = ffn;						\
	cfn_type _cfn = cfn;						\
	list_for_each_entry_safe(e, e_tmp, head, member) {		\
		if (_cfn && _cfn(priv, e, maxage)) {			\
			list_del(&e->member);				\
			_ffn ? _ffn(priv, e) : free(e);			\
		}							\
	}								\
} while (0)


#ifndef BIT
#define BIT(n)	(1 << (n))
#endif

#define blobmsg_add_macaddr(b, f, v)	\
do {					\
	char _vstr[18] = {0};		\
	hwaddr_ntoa(v, _vstr);		\
	blobmsg_add_string(b, f, _vstr);\
} while (0)

#endif /* UTILS_H */
