/* main.c - Application main entry point */

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

#include <zephyr.h>
#include <linker/sections.h>
#include <ztest.h>
#include <random/rand32.h>

#include <net/ethernet.h>
#include <net/dummy.h>
#include <net/net_if.h>
#include <net/socket.h>

struct fake_dev_context {
	uint8_t mac_addr[sizeof(struct net_eth_addr)];
	struct net_if *iface;
};

static int fake_dev_pm_control(const struct device *dev,
			       enum pm_device_action action)
{
	struct fake_dev_context *ctx = dev->data;
	int ret;

	switch (action) {
	case PM_DEVICE_ACTION_SUSPEND:
		ret = net_if_suspend(ctx->iface);
		if (ret == -EBUSY) {
			goto out;
		}
		break;
	case PM_DEVICE_ACTION_RESUME:
		ret = net_if_resume(ctx->iface);
		break;
	default:
		ret = -ENOTSUP;
		break;
	}

out:

	return ret;
}


static int fake_dev_send(const struct device *dev, struct net_pkt *pkt)
{
	ARG_UNUSED(dev);
	ARG_UNUSED(pkt);

	return 0;
}

static uint8_t *fake_dev_get_mac(struct fake_dev_context *ctx)
{
	if (ctx->mac_addr[2] == 0x00) {
		/* 00-00-5E-00-53-xx Documentation RFC 7042 */
		ctx->mac_addr[0] = 0x00;
		ctx->mac_addr[1] = 0x00;
		ctx->mac_addr[2] = 0x5E;
		ctx->mac_addr[3] = 0x00;
		ctx->mac_addr[4] = 0x53;
		ctx->mac_addr[5] = sys_rand32_get();
	}

	return ctx->mac_addr;
}

static void fake_dev_iface_init(struct net_if *iface)
{
	const struct device *dev = net_if_get_device(iface);
	struct fake_dev_context *ctx = dev->data;
	uint8_t *mac = fake_dev_get_mac(ctx);

	net_if_set_link_addr(iface, mac, 6, NET_LINK_ETHERNET);

	ctx->iface = iface;
}

int fake_dev_init(const struct device *dev)
{
	ARG_UNUSED(dev);

	return 0;
}

struct fake_dev_context fake_dev_context_data;

static struct dummy_api fake_dev_if_api = {
	.iface_api.init = fake_dev_iface_init,
	.send = fake_dev_send,
};

#define _ETH_L2_LAYER    DUMMY_L2
#define _ETH_L2_CTX_TYPE NET_L2_GET_CTX_TYPE(DUMMY_L2)

NET_DEVICE_INIT(fake_dev, "fake_dev",
		fake_dev_init, fake_dev_pm_control,
		&fake_dev_context_data, NULL,
		CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
		&fake_dev_if_api, _ETH_L2_LAYER, _ETH_L2_CTX_TYPE, 127);

void test_setup(void)
{
	struct net_if *iface;
	struct in_addr in4addr_my = { { { 192, 168, 0, 2 } } };
	struct net_if_addr *ifaddr;

	iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY));

	net_if_up(iface);

	ifaddr = net_if_ipv4_addr_add(iface, &in4addr_my, NET_ADDR_MANUAL, 0);
	zassert_not_null(ifaddr, "Could not add iface address");
}

void test_pm(void)
{
	struct net_if *iface =
		net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY));
	const struct device *dev = net_if_get_device(iface);
	char data[] = "some data";
	struct sockaddr_in addr4;
	int sock;
	int ret;

	addr4.sin_family = AF_INET;
	addr4.sin_port = htons(12345);
	inet_pton(AF_INET, "192.168.0.1", &addr4.sin_addr);

	sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	zassert_true(sock >= 0, "Could not open socket");

	zassert_false(net_if_is_suspended(iface), "net iface is not suspended");

	/* Let's send some data, it should go through */
	ret = sendto(sock, data, ARRAY_SIZE(data), 0,
		     (struct sockaddr *)&addr4, sizeof(struct sockaddr_in));
	zassert_true(ret > 0, "Could not send data");

	/* Let's make sure net stack's thread gets ran, or setting PM state
	 * might return -EBUSY instead
	 */
	k_yield();

	ret = pm_device_state_set(dev, PM_DEVICE_STATE_SUSPENDED);
	zassert_true(ret == 0, "Could not set state");

	zassert_true(net_if_is_suspended(iface), "net iface is not suspended");

	/* Let's try to suspend it again, it should fail relevantly */
	ret = pm_device_state_set(dev, PM_DEVICE_STATE_SUSPENDED);
	zassert_true(ret == -EALREADY, "Could change state");

	zassert_true(net_if_is_suspended(iface), "net iface is not suspended");

	/* Let's send some data, it should fail relevantly */
	ret = sendto(sock, data, ARRAY_SIZE(data), 0,
		     (struct sockaddr *)&addr4, sizeof(struct sockaddr_in));
	zassert_true(ret < 0, "Could send data");

	ret = pm_device_state_set(dev, PM_DEVICE_STATE_ACTIVE);
	zassert_true(ret == 0, "Could not set state");

	zassert_false(net_if_is_suspended(iface), "net iface is suspended");

	ret = pm_device_state_set(dev, PM_DEVICE_STATE_ACTIVE);
	zassert_true(ret == -EALREADY, "Could change state");

	/* Let's send some data, it should go through */
	ret = sendto(sock, data, ARRAY_SIZE(data), 0,
		     (struct sockaddr *)&addr4, sizeof(struct sockaddr_in));
	zassert_true(ret > 0, "Could not send data");

	close(sock);
}

void test_main(void)
{
	ztest_test_suite(test_net_pm,
			 ztest_unit_test(test_setup),
			 ztest_unit_test(test_pm));
	ztest_run_test_suite(test_net_pm);
}
