/*
 * Copyright (c) 2019 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(conn_mgr, CONFIG_NET_CONNECTION_MANAGER_LOG_LEVEL);

#include <zephyr/init.h>
#include <zephyr/kernel.h>
#include <errno.h>
#include <zephyr/net/net_core.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/net_mgmt.h>

#include <conn_mgr.h>

#if IS_ENABLED(CONFIG_NET_TC_THREAD_COOPERATIVE)
#define THREAD_PRIORITY K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1)
#else
#define THREAD_PRIORITY K_PRIO_PREEMPT(7)
#endif

uint16_t iface_states[CONN_MGR_IFACE_MAX];

K_SEM_DEFINE(conn_mgr_lock, 1, K_SEM_MAX_LIMIT);

static enum net_conn_mgr_state conn_mgr_iface_status(int index)
{
	if (iface_states[index] & NET_STATE_IFACE_UP) {
		return NET_CONN_MGR_STATE_CONNECTED;
	}

	return NET_CONN_MGR_STATE_DISCONNECTED;
}

#if defined(CONFIG_NET_IPV6)
static enum net_conn_mgr_state conn_mgr_ipv6_status(int index)
{
	if ((iface_states[index] & CONN_MGR_IPV6_STATUS_MASK) ==
	    CONN_MGR_IPV6_STATUS_MASK) {
		NET_DBG("IPv6 connected on iface index %u", index + 1);
		return NET_CONN_MGR_STATE_CONNECTED;
	}

	return NET_CONN_MGR_STATE_DISCONNECTED;
}
#else
#define conn_mgr_ipv6_status(...) NET_CONN_MGR_STATE_CONNECTED
#endif /* CONFIG_NET_IPV6 */

#if defined(CONFIG_NET_IPV4)
static enum net_conn_mgr_state conn_mgr_ipv4_status(int index)
{
	if ((iface_states[index] & CONN_MGR_IPV4_STATUS_MASK) ==
	    CONN_MGR_IPV4_STATUS_MASK) {
		NET_DBG("IPv4 connected on iface index %u", index + 1);
		return NET_CONN_MGR_STATE_CONNECTED;
	}

	return NET_CONN_MGR_STATE_DISCONNECTED;
}
#else
#define conn_mgr_ipv4_status(...) NET_CONN_MGR_STATE_CONNECTED
#endif /* CONFIG_NET_IPV4 */

static void conn_mgr_notify_status(int index)
{
	struct net_if *iface = net_if_get_by_index(index + 1);

	if (iface == NULL) {
		return;
	}

	if (iface_states[index] & NET_STATE_CONNECTED) {
		NET_DBG("Iface %d (%p) connected",
			net_if_get_by_iface(iface), iface);
		net_mgmt_event_notify(NET_EVENT_L4_CONNECTED, iface);
	} else {
		NET_DBG("Iface %d (%p) disconnected",
			net_if_get_by_iface(iface), iface);
		net_mgmt_event_notify(NET_EVENT_L4_DISCONNECTED, iface);
	}
}

static void conn_mgr_act_on_changes(void)
{
	int idx;

	for (idx = 0; idx < ARRAY_SIZE(iface_states); idx++) {
		enum net_conn_mgr_state state;

		if (iface_states[idx] == 0) {
			/* This interface is not used */
			continue;
		}

		if (!(iface_states[idx] & NET_STATE_CHANGED)) {
			continue;
		}

		state = NET_CONN_MGR_STATE_CONNECTED;

		state &= conn_mgr_iface_status(idx);
		if (state) {
			enum net_conn_mgr_state ip_state =
				NET_CONN_MGR_STATE_DISCONNECTED;

			if (IS_ENABLED(CONFIG_NET_IPV6)) {
				ip_state |= conn_mgr_ipv6_status(idx);
			}

			if (IS_ENABLED(CONFIG_NET_IPV4)) {
				ip_state |= conn_mgr_ipv4_status(idx);
			}

			state &= ip_state;
		}

		iface_states[idx] &= ~NET_STATE_CHANGED;

		if (state == NET_CONN_MGR_STATE_CONNECTED &&
		    !(iface_states[idx] & NET_STATE_CONNECTED)) {
			iface_states[idx] |= NET_STATE_CONNECTED;

			conn_mgr_notify_status(idx);
		} else if (state != NET_CONN_MGR_STATE_CONNECTED &&
			   (iface_states[idx] & NET_STATE_CONNECTED)) {
			iface_states[idx] &= ~NET_STATE_CONNECTED;

			conn_mgr_notify_status(idx);
		}
	}
}

static void conn_mgr_initial_state(struct net_if *iface)
{
	int idx = net_if_get_by_iface(iface) - 1;

	if (net_if_is_up(iface)) {
		NET_DBG("Iface %p UP", iface);
		iface_states[idx] = NET_STATE_IFACE_UP;
	}

	if (IS_ENABLED(CONFIG_NET_NATIVE_IPV6)) {
		if (net_if_ipv6_get_global_addr(NET_ADDR_PREFERRED, &iface)) {
			NET_DBG("IPv6 addr set");
			iface_states[idx] |= NET_STATE_IPV6_ADDR_SET |
						NET_STATE_IPV6_DAD_OK;
		} else if (net_if_ipv6_get_global_addr(NET_ADDR_TENTATIVE,
						       &iface)) {
			iface_states[idx] |= NET_STATE_IPV6_ADDR_SET;
		}
	}

	if (IS_ENABLED(CONFIG_NET_NATIVE_IPV4)) {
		if (net_if_ipv4_get_global_addr(iface, NET_ADDR_PREFERRED)) {
			NET_DBG("IPv4 addr set");
			iface_states[idx] |= NET_STATE_IPV4_ADDR_SET;
		}

	}

	iface_states[idx] |= NET_STATE_CHANGED;
}

static void conn_mgr_init_cb(struct net_if *iface, void *user_data)
{
	ARG_UNUSED(user_data);

	conn_mgr_initial_state(iface);
}

static void conn_mgr_handler(void)
{
	conn_mgr_init_events_handler();

	net_if_foreach(conn_mgr_init_cb, NULL);

	NET_DBG("Connection Manager started");

	while (true) {
		k_sem_take(&conn_mgr_lock, K_FOREVER);

		conn_mgr_act_on_changes();
	}
}

K_THREAD_DEFINE(conn_mgr, CONFIG_NET_CONNECTION_MANAGER_STACK_SIZE,
		(k_thread_entry_t)conn_mgr_handler, NULL, NULL, NULL,
		THREAD_PRIORITY, 0, 0);

void net_conn_mgr_resend_status(void)
{
	int idx;

	for (idx = 0; idx < ARRAY_SIZE(iface_states); idx++) {
		conn_mgr_notify_status(idx);
	}
}

static int conn_mgr_init(const struct device *dev)
{
	int i;

	ARG_UNUSED(dev);

	for (i = 0; i < ARRAY_SIZE(iface_states); i++) {
		iface_states[i] = 0;
	}

	k_thread_start(conn_mgr);

	return 0;
}

SYS_INIT(conn_mgr_init, APPLICATION, CONFIG_NET_CONNECTION_MANAGER_PRIORITY);
