/* SPDX-License-Identifier: BSD-3-Clause */
#include <srx/lyx.h>

#include "ietf-interfaces.h"

#define WPA_SUPPLICANT_FINIT_CONF "/etc/finit.d/available/wpa_supplicant-%s.conf"
#define WPA_SUPPLICANT_CONF       "/etc/wpa_supplicant-%s.conf"

static int wifi_gen_config(const char *ifname, const char *ssid, const char *country, const char *secret, const char* encryption, struct dagger *net)
{
	FILE *wpa_supplicant = NULL, *wpa = NULL;
	char *encryption_str;
	int rc = SR_ERR_OK;

	if (!secret && (ssid && country && encryption)) {
		/* Not an error, updated from two ways, interface cb and keystore cb. */
		return 0;
	}

	wpa = dagger_fopen_net_init(net, ifname, NETDAG_INIT_POST, "wpa_supplicant.sh");
	if (!wpa) {
		rc = SR_ERR_INTERNAL;
		goto out;
	}

	fprintf(wpa, "# Generated by Infix confd\n");

	fprintf(wpa, "if [ -f '/etc/finit.d/enabled/wifi@%s.conf' ];then\n", ifname);
	fprintf(wpa, "initctl -bfqn touch wifi@%s\n", ifname);
	fprintf(wpa, "else\n");
	fprintf(wpa, "initctl -bfqn enable wifi@%s\n", ifname);
	fprintf(wpa, "fi\n");
	fclose(wpa);

	wpa_supplicant = fopenf("w", WPA_SUPPLICANT_CONF, ifname);
	if (!wpa_supplicant) {
		rc = SR_ERR_INTERNAL;
		goto out;
	}

	if (!secret || !ssid || !country || !encryption) {
		fprintf(wpa_supplicant,
			"ctrl_interface=/run/wpa_supplicant\n"
			"autoscan=periodic:10\n"
			"ap_scan=1\n");
	} else {
		if (!strcmp(encryption, "disabled")) {
			asprintf(&encryption_str, "key_mgmt=NONE");
		} else {
			asprintf(&encryption_str, "key_mgmt=SAE WPA-PSK\npsk=\"%s\"", secret);
		}
		fprintf(wpa_supplicant,
			"country=%s\n"
			"ctrl_interface=/run/wpa_supplicant\n"
			"autoscan=periodic:10\n"
			"ap_scan=1\n"
			"network={\n"
			"bgscan=\"simple: 30:-45:300\"\n"
			"ssid=\"%s\"\n"
			"%s\n"
			"}\n", country, ssid, encryption_str);
			free(encryption_str);
	}
	fclose(wpa_supplicant);

out:
	return rc;

}
int wifi_gen(struct lyd_node *dif, struct lyd_node *cif, struct dagger *net)
{
	const char *ssid, *secret_name, *secret, *ifname, *country, *encryption;
	struct lyd_node *wifi, *secret_node;

	bool enabled;
	ifname      = lydx_get_cattr(cif, "name");

	if (cif && !lydx_get_child(cif, "wifi")) {
		return wifi_gen_config(ifname, NULL, NULL, NULL, NULL, net);
	}

	enabled     = lydx_get_bool(cif, "enabled");
	wifi        = lydx_get_child(cif, "wifi");

	ssid        = lydx_get_cattr(wifi, "ssid");
	secret_name = lydx_get_cattr(wifi, "secret");
	country     = lydx_get_cattr(wifi, "country-code");
	encryption  = lydx_get_cattr(wifi, "encryption");
	secret_node = lydx_get_xpathf(cif, "../../keystore/symmetric-keys/symmetric-key[name='%s']", secret_name);
	secret      = lydx_get_cattr(secret_node, "cleartext-key");

	if (!enabled)
		return wifi_gen_del(cif, net);

	return wifi_gen_config(ifname, ssid, country, secret, encryption, net);
}

int wifi_gen_del(struct lyd_node *dif,  struct dagger *net)
{
	const char *ifname = lydx_get_cattr(dif, "name");
	FILE *iw = dagger_fopen_net_exit(net, ifname, NETDAG_EXIT_PRE, "iw.sh");

	fprintf(iw, "# Generated by Infix confd\n");
	fprintf(iw, "iw dev %s disconnect\n", ifname);
	fprintf(iw, "initctl -bfqn disable wifi@%s\n", ifname);
	fclose(iw);
	erasef(WPA_SUPPLICANT_CONF, ifname);

	return SR_ERR_OK;
}
