module NG_NAS_Functions {

/* (C) 2025 by sysmocom - s.f.m.c. GmbH <info@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
 */

import from NG_NAS_MsgContainers all;
import from NG_NAS_TypeDefs all;
import from EAP_TypeDefs all;

import from General_Types all;
import from Misc_Helpers all;

import from NG_NAS_Osmo_Types all;

external function enc_NG_NAS_UL_Message_Type(in NG_NAS_UL_Message_Type pdu) return octetstring
with { extension "prototype(convert)" extension "encode(RAW)" }
external function dec_NG_NAS_UL_Message_Type(in octetstring stream) return NG_NAS_UL_Message_Type
with { extension "prototype(convert)" extension "decode(RAW)" }

external function enc_NG_NAS_DL_Message_Type(in NG_NAS_DL_Message_Type pdu) return octetstring
with { extension "prototype(convert)" extension "encode(RAW)" }
external function dec_NG_NAS_DL_Message_Type(in octetstring stream) return NG_NAS_DL_Message_Type
with { extension "prototype(convert)" extension "decode(RAW)" }

external function enc_NG_NAS_DL_SM_Message_Type(in NG_NAS_DL_SM_Message_Type pdu) return octetstring
with { extension "prototype(convert)" extension "encode(RAW)" }
external function dec_NG_NAS_DL_SM_Message_Type(in octetstring stream) return NG_NAS_DL_SM_Message_Type
with { extension "prototype(convert)" extension "decode(RAW)" }


/* Decode 3GPP TS 24.501 9.11.3.39 Payload container based on 9.11.3.40 Payload container type.
 * Trying to decode it directly through dec_NG_NAS_DL_Message_Type() may end up with unexpected
 * union choice due to circumstancial match in previous field securityHeaderType.
 * pct = PayloadContainerType.container, payload = PayloadContainer.payload
 */
function f_dec_NG_NAS_DL_Message_Payload_Container(BIT4 pct, octetstring payload) return NG_NAS_DL_Message_Type
{
	var NG_NAS_DL_Message_Type ret;
	select (pct) {
	case (c_PayloadContainer_N1_SM_Info) {
		var NG_NAS_DL_SM_Message_Type sm := dec_NG_NAS_DL_SM_Message_Type(payload);
		if (ischosen(sm.pdu_Session_Authentication_Command)) {
			ret.pdu_Session_Authentication_Command := sm.pdu_Session_Authentication_Command;
		} else if (ischosen(sm.pdu_Session_Authentication_Result)) {
			ret.pdu_Session_Authentication_Result := sm.pdu_Session_Authentication_Result;
		} else if (ischosen(sm.pdu_Session_Establishment_Accept)) {
			ret.pdu_Session_Establishment_Accept := sm.pdu_Session_Establishment_Accept;
		} else if (ischosen(sm.pdu_Session_Establishment_Reject)) {
			ret.pdu_Session_Establishment_Reject := sm.pdu_Session_Establishment_Reject;
		} else if (ischosen(sm.pdu_Session_Modification_Command)) {
			ret.pdu_Session_Modification_Command := sm.pdu_Session_Modification_Command;
		} else if (ischosen(sm.pdu_Session_Modification_Reject)) {
			ret.pdu_Session_Modification_Reject := sm.pdu_Session_Modification_Reject;
		} else if (ischosen(sm.pdu_Session_Release_Command)) {
			ret.pdu_Session_Release_Command := sm.pdu_Session_Release_Command;
		} else if (ischosen(sm.pdu_Session_Release_Reject)) {
			ret.pdu_Session_Release_Reject := sm.pdu_Session_Release_Reject;
		} else if (ischosen(sm.gsm_Status)) {
			ret.gsm_Status := sm.gsm_Status;
		} else {
			Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
						log2str("Unexpected decoded Payload Container ", sm));
		}
		return ret;
		}
	case else {
		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
					log2str("Unimplemented decoding of Payload Container Type ",
						pct, ", Payload Container ", payload));
		}
	}
	return ret;
}

}
