/*
 * Copyright (c) 2020 Espressif Systems (Shanghai) Co., Ltd.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT espressif_esp32_wifi

#include <logging/log.h>
LOG_MODULE_REGISTER(esp32_wifi, CONFIG_WIFI_LOG_LEVEL);

#include <net/ethernet.h>
#include <net/net_pkt.h>
#include <net/net_if.h>
#include <device.h>
#include <soc.h>
#include <ethernet/eth_stats.h>
#include "esp_networking_priv.h"
#include "esp_private/wifi.h"
#include "esp_event.h"
#include "esp_timer.h"
#include "esp_wifi_system.h"
#include "esp_wpa.h"

#define DEV_DATA(dev) \
	((struct esp32_wifi_runtime *)(dev)->data)

/* use global iface pointer to support any ethernet driver */
/* necessary for wifi callback functions */
static struct net_if *esp32_wifi_iface;

struct esp32_wifi_runtime {
	struct net_if *iface;
	uint8_t mac_addr[6];
	bool tx_err;
	uint32_t tx_word;
	int tx_pos;
	uint8_t frame_buf[NET_ETH_MAX_FRAME_SIZE];
#if defined(CONFIG_NET_STATISTICS_ETHERNET)
	struct net_stats_eth stats;
#endif
};

static void esp_wifi_event_task(void);

K_MSGQ_DEFINE(esp_wifi_msgq, sizeof(system_event_t), 10, 4);
K_THREAD_DEFINE(esp_wifi_event_tid, CONFIG_ESP32_WIFI_EVENT_TASK_STACK_SIZE,
		esp_wifi_event_task, NULL, NULL, NULL, CONFIG_ESP32_WIFI_EVENT_TASK_PRIO, 0, 0);

/* internal wifi library callback function */
esp_err_t esp_event_send_internal(esp_event_base_t event_base,
				  int32_t event_id,
				  void *event_data,
				  size_t event_data_size,
				  uint32_t ticks_to_wait)
{
	k_msgq_put(&esp_wifi_msgq, (int32_t *)&event_id, K_FOREVER);
	return ESP_OK;
}

static int eth_esp32_send(const struct device *dev, struct net_pkt *pkt)
{
	const int pkt_len = net_pkt_get_len(pkt);

	/* Read the packet payload */
	if (net_pkt_read(pkt, DEV_DATA(dev)->frame_buf, pkt_len) < 0) {
		return -EIO;
	}

	/* Enqueue packet for transmission */
	esp_wifi_internal_tx(ESP_IF_WIFI_STA, (void *)DEV_DATA(dev)->frame_buf, pkt_len);

	LOG_DBG("pkt sent %p len %d", pkt, pkt_len);

	return 0;
}

static esp_err_t eth_esp32_rx(void *buffer, uint16_t len, void *eb)
{
	struct net_pkt *pkt;

	if (esp32_wifi_iface == NULL) {
		LOG_ERR("network interface unavailable");
		return ESP_FAIL;
	}

	pkt = net_pkt_rx_alloc_with_buffer(esp32_wifi_iface, len,
			AF_UNSPEC, 0, K_NO_WAIT);
	if (!pkt) {
		LOG_ERR("Failed to get net buffer");
		return ESP_FAIL;
	}

	if (net_pkt_write(pkt, buffer, len) < 0) {
		LOG_ERR("Failed to write pkt");
		goto pkt_unref;
	}

	if (net_recv_data(esp32_wifi_iface, pkt) < 0) {
		LOG_ERR("Failed to push received data");
		goto pkt_unref;
	}

	esp_wifi_internal_free_rx_buffer(eb);
	return ESP_OK;

pkt_unref:
	net_pkt_unref(pkt);
	return ESP_FAIL;
}

void esp_wifi_event_task(void)
{
	int32_t event_id;

	while (1) {
		k_msgq_get(&esp_wifi_msgq, &event_id, K_FOREVER);

		switch (event_id) {
		case ESP32_WIFI_EVENT_STA_START:
			LOG_INF("WIFI_EVENT_STA_START");
			net_if_up(esp32_wifi_iface);
			break;
		case ESP32_WIFI_EVENT_STA_STOP:
			LOG_INF("WIFI_EVENT_STA_STOP");
			net_if_down(esp32_wifi_iface);
			break;
		case ESP32_WIFI_EVENT_STA_CONNECTED:
			LOG_INF("WIFI_EVENT_STA_CONNECTED");
			net_eth_carrier_on(esp32_wifi_iface);
			break;
		case ESP32_WIFI_EVENT_STA_DISCONNECTED:
			LOG_INF("WIFI_EVENT_STA_DISCONNECTED");
			net_eth_carrier_off(esp32_wifi_iface);

			if (IS_ENABLED(CONFIG_ESP32_WIFI_STA_RECONNECT)) {
				esp_wifi_connect();
			}
			break;
		default:
			break;
		}
	}
}

static void eth_esp32_init(struct net_if *iface)
{
	const struct device *dev = net_if_get_device(iface);
	struct esp32_wifi_runtime *dev_data = DEV_DATA(dev);

	dev_data->iface = iface;
	esp32_wifi_iface = iface;

	/* Start interface when we are actually connected with WiFi network */
	net_if_flag_set(iface, NET_IF_NO_AUTO_START);
	esp_read_mac(dev_data->mac_addr, ESP_MAC_WIFI_STA);

	/* Assign link local address. */
	net_if_set_link_addr(iface,
			dev_data->mac_addr, 6, NET_LINK_ETHERNET);

	ethernet_init(iface);

	esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, eth_esp32_rx);
}

#if defined(CONFIG_NET_STATISTICS_ETHERNET)
static struct net_stats_eth *eth_esp32_stats(const struct device *dev)
{
	return &(DEV_DATA(dev)->stats);
}
#endif

static int eth_esp32_dev_init(const struct device *dev)
{
	esp_timer_init();

	wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT();
	esp_err_t ret = esp_wifi_init(&config);

	ret |= esp_supplicant_init();
	ret |= esp_wifi_start();

	if (IS_ENABLED(CONFIG_ESP32_WIFI_STA_AUTO)) {
		wifi_config_t wifi_config = {
			.sta = {
				.ssid = CONFIG_ESP32_WIFI_SSID,
				.password = CONFIG_ESP32_WIFI_PASSWORD,
			},
		};

		ret = esp_wifi_set_mode(WIFI_MODE_STA);
		ret |= esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
		ret |= esp_wifi_connect();
	}

	if (ret != ESP_OK) {
		LOG_ERR("Connect failed");
	}

	return ret;
}


static struct esp32_wifi_runtime eth_data;

static const struct ethernet_api eth_esp32_apis = {
	.iface_api.init	= eth_esp32_init,
	.send =  eth_esp32_send,
#if defined(CONFIG_NET_STATISTICS_ETHERNET)
	.get_stats = eth_esp32_stats,
#endif
};

NET_DEVICE_DT_INST_DEFINE(0,
		eth_esp32_dev_init, NULL,
		&eth_data, NULL, CONFIG_ETH_INIT_PRIORITY,
		&eth_esp32_apis, ETHERNET_L2,
		NET_L2_GET_CTX_TYPE(ETHERNET_L2), NET_ETH_MTU);
