/*
 * Copyright (c) 2023 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

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

#include <zephyr/net/net_if.h>
#include <zephyr/net/conn_mgr_connectivity.h>
#include <zephyr/sys/iterable_sections.h>

#include "conn_mgr_private.h"

int conn_mgr_if_connect(struct net_if *iface)
{
	struct conn_mgr_conn_binding *binding;
	struct conn_mgr_conn_api *api;
	int status;

	LOG_DBG("iface %p connect", iface);

	binding = conn_mgr_if_get_binding(iface);
	if (!binding) {
		return -ENOTSUP;
	}

	api = binding->impl->api;
	if (!api->connect) {
		return -ENOTSUP;
	}

	k_mutex_lock(binding->mutex, K_FOREVER);

	if (!net_if_is_admin_up(iface)) {
		status = net_if_up(iface);
		if (status) {
			goto out;
		}
	}

	status = api->connect(binding);

out:
	k_mutex_unlock(binding->mutex);

	return status;
}

int conn_mgr_if_disconnect(struct net_if *iface)
{
	struct conn_mgr_conn_binding *binding;
	struct conn_mgr_conn_api *api;
	int status = 0;

	LOG_DBG("iface %p disconnect", iface);

	binding = conn_mgr_if_get_binding(iface);
	if (!binding) {
		return -ENOTSUP;
	}

	api = binding->impl->api;
	if (!api->disconnect) {
		return -ENOTSUP;
	}

	k_mutex_lock(binding->mutex, K_FOREVER);

	if (!net_if_is_admin_up(iface)) {
		goto out;
	}

	status = api->disconnect(binding);

out:
	k_mutex_unlock(binding->mutex);

	return status;
}

bool conn_mgr_if_is_bound(struct net_if *iface)
{
	struct conn_mgr_conn_binding *binding = conn_mgr_if_get_binding(iface);

	return binding != NULL;
}

int conn_mgr_if_get_opt(struct net_if *iface, int optname, void *optval, size_t *optlen)
{
	struct conn_mgr_conn_binding *binding;
	struct conn_mgr_conn_api *api;
	int status;

	if (!optlen) {
		return -EINVAL;
	}

	if (!optval) {
		*optlen = 0;
		return -EINVAL;
	}

	binding = conn_mgr_if_get_binding(iface);
	if (!binding) {
		*optlen = 0;
		return -ENOTSUP;
	}

	api = binding->impl->api;
	if (!api->get_opt) {
		*optlen = 0;
		return -ENOTSUP;
	}

	k_mutex_lock(binding->mutex, K_FOREVER);

	status = api->get_opt(binding, optname, optval, optlen);

	k_mutex_unlock(binding->mutex);

	return status;
}

int conn_mgr_if_set_opt(struct net_if *iface, int optname, const void *optval, size_t optlen)
{
	struct conn_mgr_conn_binding *binding;
	struct conn_mgr_conn_api *api;
	int status;

	if (!optval) {
		return -EINVAL;
	}

	binding = conn_mgr_if_get_binding(iface);
	if (!binding) {
		return -ENOTSUP;
	}

	api = binding->impl->api;
	if (!api->set_opt) {
		return -ENOTSUP;
	}

	k_mutex_lock(binding->mutex, K_FOREVER);

	status = api->set_opt(binding, optname, optval, optlen);

	k_mutex_unlock(binding->mutex);

	return status;
}

int conn_mgr_if_set_flag(struct net_if *iface, enum conn_mgr_if_flag flag, bool value)
{
	struct conn_mgr_conn_binding *binding;

	if (flag >= CONN_MGR_NUM_IF_FLAGS) {
		return -EINVAL;
	}

	binding = conn_mgr_if_get_binding(iface);
	if (!binding) {
		return -ENOTSUP;
	}

	k_mutex_lock(binding->mutex, K_FOREVER);

	binding->flags &= ~BIT(flag);
	if (value) {
		binding->flags |= BIT(flag);
	}

	k_mutex_unlock(binding->mutex);

	return 0;
}

bool conn_mgr_if_get_flag(struct net_if *iface, enum conn_mgr_if_flag flag)
{
	struct conn_mgr_conn_binding *binding;
	bool value;

	if (flag >= CONN_MGR_NUM_IF_FLAGS) {
		return false;
	}

	binding = conn_mgr_if_get_binding(iface);
	if (!binding) {
		return false;
	}

	k_mutex_lock(binding->mutex, K_FOREVER);

	value = !!(binding->flags & BIT(flag));

	k_mutex_unlock(binding->mutex);

	return value;
}

int conn_mgr_if_get_timeout(struct net_if *iface)
{
	struct conn_mgr_conn_binding *binding = conn_mgr_if_get_binding(iface);
	int value;

	if (!binding) {
		return false;
	}

	k_mutex_lock(binding->mutex, K_FOREVER);

	value = binding->timeout;

	k_mutex_unlock(binding->mutex);

	return value;
}

int conn_mgr_if_set_timeout(struct net_if *iface, int timeout)
{
	struct conn_mgr_conn_binding *binding = conn_mgr_if_get_binding(iface);

	if (!binding) {
		return -ENOTSUP;
	}

	k_mutex_lock(binding->mutex, K_FOREVER);

	binding->timeout = timeout;

	k_mutex_unlock(binding->mutex);

	return 0;
}

void conn_mgr_conn_init(void)
{
	STRUCT_SECTION_FOREACH(conn_mgr_conn_binding, binding) {
		if (!(binding->impl->api)) {
			LOG_ERR("Connectivity implementation has NULL API, and will be treated as "
				"non-existent.");
		} else if (binding->impl->api->init) {
			k_mutex_lock(binding->mutex, K_FOREVER);

			/* Set initial default values for binding state */

			binding->timeout = CONN_MGR_IF_NO_TIMEOUT;

			/* Call binding initializer */

			binding->impl->api->init(binding);

			k_mutex_unlock(binding->mutex);
		}
	}
}
