/* REST interface API for PyHSS
 *
 * (C) 2025 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
 * Author: Oliver Smith <osmith@sysmocom.de>
 *
 * All rights reserved.
 *
 * Released under the terms of GNU General Public License, Version 2 or
 * (at your option) any later version.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

module PyHSS_REST_Functions {

import from General_Types all;

import from PIPEasp_PortType all;
import from PIPEasp_Types all;
import from PIPEasp_Templates all;


type component PyHSS_REST_CT {
	var boolean g_pipe_initialized := false;
	var integer g_next_auc_id := 1;
	port PIPEasp_PT PIPE;
}

private function f_pyhss_api_helper(charstring args)
runs on PyHSS_REST_CT {
	if (not g_pipe_initialized) {
		map(self:PIPE, system:PIPE);
		g_pipe_initialized := true;
	}
	f_PIPEasp_exec_sync(PIPE, "pyhss_api_helper.py " & args)
}

/* Get the algorithm value (algo), from PyHSS lib/database.py:
 * 1 = Comp128v1
 * 2 = Comp128v2
 * 3 = Comp128v3
 * All Other = 3G auth with 2g keys from 3G Milenage */
private function f_pyhss_algo(template (omit) charstring algo2g := omit,
			      template (omit) charstring algo3g := omit)
return integer {
	if (not istemplatekind(algo2g, "omit")) {
		if (valueof(algo2g) == "comp128v1") {
			return 1;
		} else if (valueof(algo2g) == "comp128v2") {
			return 2;
		} else if (valueof(algo2g) == "comp128v3") {
			return 3;
		} else {
			setverdict(fail, "f_pyhss_algo: Unexpected algo2g: ", algo2g);
			mtc.stop;
		}
	}

	if (not istemplatekind(algo3g, "omit")) {
		if (valueof(algo3g) == "milenage") {
			return 4;
		} else {
			setverdict(fail, "f_pyhss_algo: Unexpected algo3g: ", algo3g);
			mtc.stop;
		}
	}

	setverdict(fail, "f_pyhss_algo: algo2g and algo3g are unset");
	mtc.stop;

	return -1;
}

/* Create a subscriber */
function f_pyhss_rest_subscr_create(hexstring imsi,
				    hexstring msisdn,
				    /* 2g */
				    template (omit) charstring algo2g := omit,
				    template (omit) OCT16 ki := omit,
				    /* 3g */
				    template (omit) charstring algo3g := omit,
				    template (omit) OCT16 opc := omit)
runs on PyHSS_REST_CT {
	var integer algo := f_pyhss_algo(algo2g, algo3g);

	/* ki and opc cannot be NULL in the PyHSS DB */
	if (istemplatekind(ki, "omit")) {
		ki := '11111111111111111111111111111111'O;
	}
	if (istemplatekind(opc, "omit")) {
		opc := '22222222222222222222222222222222'O;
	}

	f_pyhss_api_helper(
		"add_subscr"
		& " --imsi " & hex2str(imsi)
		& " --msisdn " & hex2str(msisdn)
		& " --auc-id " & int2str(g_next_auc_id)
		& " --algo " & int2str(algo)
		& " --ki " & oct2str(valueof(ki))
		& " --opc " & oct2str(valueof(opc))
	);

	g_next_auc_id := g_next_auc_id + 1;
}

/* Delete a subscriber */
function f_pyhss_rest_subscr_delete(hexstring imsi)
runs on PyHSS_REST_CT{
	f_pyhss_api_helper("del_subscr --imsi " & hex2str(imsi));
}

}
