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

#include "supp_events.h"

#include "includes.h"
#include "common.h"

#define MAC_STR_FORMAT "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx"

static const char * const supplicant_event_map[] = {
	"CTRL-EVENT-CONNECTED",
	"CTRL-EVENT-DISCONNECTED",
	"CTRL-EVENT-ASSOC-REJECT",
	"CTRL-EVENT-AUTH-REJECT",
	"CTRL-EVENT-TERMINATING",
	"CTRL-EVENT-SSID-TEMP-DISABLED",
	"CTRL-EVENT-SSID-REENABLED",
	"CTRL-EVENT-SCAN-STARTED",
	"CTRL-EVENT-SCAN-RESULTS",
	"CTRL-EVENT-SCAN-FAILED",
	"CTRL-EVENT-BSS-ADDED",
	"CTRL-EVENT-BSS-REMOVED",
	"CTRL-EVENT-NETWORK-NOT-FOUND",
	"CTRL-EVENT-NETWORK-ADDED",
	"CTRL-EVENT-NETWORK-REMOVED",
	"CTRL-EVENT-DSCP-POLICY",
};

static int supplicant_process_status(struct supplicant_int_event_data *event_data,
				     char *supplicant_status)
{
	int ret = 1; /* For cases where parsing is not being done*/
	int event = -1;
	int i;
	unsigned char *mac;
	union supplicant_event_data *data;

	data = (union supplicant_event_data *)event_data->data;

	for (i = 0; i < ARRAY_SIZE(supplicant_event_map); i++) {
		if (strncmp(supplicant_status, supplicant_event_map[i],
		    strlen(supplicant_event_map[i])) == 0) {
			event = i;
			break;
		}
	}

	if (i >= ARRAY_SIZE(supplicant_event_map)) {
		wpa_printf(MSG_ERROR, "Event not supported: %s\n", supplicant_status);
		return -ENOTSUP;
	}

	event_data->event = event;

	switch (event_data->event) {
	case SUPPLICANT_EVENT_CONNECTED:
		mac = data->connected.bssid;
		ret = sscanf(supplicant_status +
			     sizeof("CTRL-EVENT-CONNECTED - Connection to") - 1,
			     MAC_STR_FORMAT,
			     &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
		event_data->data_len = sizeof(data->connected);
		break;
	case SUPPLICANT_EVENT_DISCONNECTED:
		mac = data->disconnected.bssid;
		ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-DISCONNECTED bssid=") - 1,
			     MAC_STR_FORMAT" reason=%d", &mac[0], &mac[1], &mac[2],
			     &mac[3], &mac[4], &mac[5], &data->disconnected.reason_code);
		event_data->data_len = sizeof(data->disconnected);
		break;
	case SUPPLICANT_EVENT_ASSOC_REJECT:
		/* TODO */
		break;
	case SUPPLICANT_EVENT_AUTH_REJECT:
		mac = data->auth_reject.bssid;
		ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-AUTH-REJECT ") - 1,
			     MAC_STR_FORMAT
			     " auth_type=%u auth_transaction=%u status_code=%u",
			     &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5],
			     &data->auth_reject.auth_type,
			     &data->auth_reject.auth_transaction,
			     &data->auth_reject.status_code);
		event_data->data_len = sizeof(data->auth_reject);
		break;
	case SUPPLICANT_EVENT_SSID_TEMP_DISABLED:
		ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-SSID-TEMP-DISABLED ") - 1,
			     "id=%d ssid=%s auth_failures=%u duration=%d reason=%s",
			     &data->temp_disabled.id, data->temp_disabled.ssid,
			     &data->temp_disabled.auth_failures,
			     &data->temp_disabled.duration,
			     data->temp_disabled.reason_code);
		event_data->data_len = sizeof(data->temp_disabled);
		break;
	case SUPPLICANT_EVENT_SSID_REENABLED:
		ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-SSID-REENABLED ") - 1,
			     "id=%d ssid=%s", &data->reenabled.id,
			     data->reenabled.ssid);
		event_data->data_len = sizeof(data->reenabled);
		break;
	case SUPPLICANT_EVENT_BSS_ADDED:
		mac = data->bss_added.bssid;
		ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-BSS-ADDED ") - 1,
			     "%u "MAC_STR_FORMAT,
			     &data->bss_added.id,
			     &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
		event_data->data_len = sizeof(data->bss_added);
		break;
	case SUPPLICANT_EVENT_BSS_REMOVED:
		mac = data->bss_removed.bssid;
		ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-BSS-REMOVED ") - 1,
			     "%u "MAC_STR_FORMAT,
			     &data->bss_removed.id,
			     &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
		event_data->data_len = sizeof(data->bss_removed);
		break;
	case SUPPLICANT_EVENT_TERMINATING:
	case SUPPLICANT_EVENT_SCAN_STARTED:
	case SUPPLICANT_EVENT_SCAN_FAILED:
	case SUPPLICANT_EVENT_NETWORK_NOT_FOUND:
	case SUPPLICANT_EVENT_NETWORK_ADDED:
	case SUPPLICANT_EVENT_NETWORK_REMOVED:
		strncpy(data->supplicant_event_str, supplicant_event_map[event],
			sizeof(data->supplicant_event_str));
		event_data->data_len = strlen(data->supplicant_event_str) + 1;
	case SUPPLICANT_EVENT_DSCP_POLICY:
		/* TODO */
		break;
	default:
		break;
	}

	if (ret <= 0) {
		wpa_printf(MSG_ERROR, "%s Parse failed: %s",
			   supplicant_event_map[event_data->event], strerror(errno));
	}

	return ret;
}

int supplicant_send_wifi_mgmt_event(const char *ifname, enum net_event_wifi_cmd event,
				    void *supplicant_status, size_t len)
{
	struct net_if *iface = net_if_get_by_index(net_if_get_by_name(ifname));
	union supplicant_event_data data;
	struct supplicant_int_event_data event_data;

	if (!iface) {
		wpa_printf(MSG_ERROR, "Could not find iface for %s", ifname);
		return -ENODEV;
	}

	switch (event) {
	case NET_EVENT_WIFI_CMD_CONNECT_RESULT:
		wifi_mgmt_raise_connect_result_event(iface, *(int *)supplicant_status);
		break;
	case NET_EVENT_WIFI_CMD_DISCONNECT_RESULT:
		wifi_mgmt_raise_disconnect_result_event(iface, *(int *)supplicant_status);
		break;
	case NET_EVENT_SUPPLICANT_CMD_INT_EVENT:
		event_data.data = &data;
		if (supplicant_process_status(&event_data, (char *)supplicant_status) > 0) {
			net_mgmt_event_notify_with_info(NET_EVENT_SUPPLICANT_INT_EVENT,
						iface, &event_data, sizeof(event_data));
		}
		break;
	default:
		wpa_printf(MSG_ERROR, "Unsupported event %d", event);
		return -EINVAL;
	}

	return 0;
}

int supplicant_generate_state_event(const char *ifname,
				    enum net_event_supplicant_cmd event,
				    int status)
{
	struct net_if *iface;

	iface = net_if_get_by_index(net_if_get_by_name(ifname));
	if (!iface) {
		wpa_printf(MSG_ERROR, "Could not find iface for %s", ifname);
		return -ENODEV;
	}

	switch (event) {
	case NET_EVENT_SUPPLICANT_CMD_READY:
		net_mgmt_event_notify(NET_EVENT_SUPPLICANT_READY, iface);
		break;
	case NET_EVENT_SUPPLICANT_CMD_NOT_READY:
		net_mgmt_event_notify(NET_EVENT_SUPPLICANT_NOT_READY, iface);
		break;
	case NET_EVENT_SUPPLICANT_CMD_IFACE_ADDED:
		net_mgmt_event_notify(NET_EVENT_SUPPLICANT_IFACE_ADDED, iface);
		break;
	case NET_EVENT_SUPPLICANT_CMD_IFACE_REMOVING:
		net_mgmt_event_notify(NET_EVENT_SUPPLICANT_IFACE_REMOVING, iface);
		break;
	case NET_EVENT_SUPPLICANT_CMD_IFACE_REMOVED:
		net_mgmt_event_notify_with_info(NET_EVENT_SUPPLICANT_IFACE_REMOVED,
						iface, &status, sizeof(status));
		break;
	default:
		wpa_printf(MSG_ERROR, "Unsupported event %d", event);
		return -EINVAL;
	}

	return 0;
}
