module S1AP_Functions {

/* (C) 2019 by Harald Welte <laforge@gnumonks.org>
 * 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 S1AP_IEs all;
import from S1AP_Types all;
import from S1AP_Constants all;
import from S1AP_PDU_Contents all;
import from S1AP_PDU_Descriptions all;
import from S1AP_Templates all;

function f_S1AP_get_ENB_UE_S1AP_ID(S1AP_PDU s1ap) return template (omit) ENB_UE_S1AP_ID
{
	if (ischosen(s1ap.initiatingMessage)) {
		var InitiatingMessage im := s1ap.initiatingMessage;
		select (s1ap) {
		case (tr_S1AP_InitialUE) {
			return im.value_.InitialUEMessage.protocolIEs[0].value_.ENB_UE_S1AP_ID;
			}
		case (tr_S1AP_DlNasTransport) {
			return im.value_.DownlinkNASTransport.protocolIEs[1].value_.ENB_UE_S1AP_ID;
			}
		case (tr_S1AP_UlNasTransport) {
			return im.value_.UplinkNASTransport.protocolIEs[1].value_.ENB_UE_S1AP_ID;
			}
		case (tr_S1AP_IntialCtxSetupReq) {
			return im.value_.initialContextSetupRequest.protocolIEs[1].value_.ENB_UE_S1AP_ID;
			}
		case (tr_S1AP_UeContextReleaseReq) {
			return im.value_.UEContextReleaseRequest.protocolIEs[1].value_.ENB_UE_S1AP_ID;
			}
		case (tr_S1AP_UeContextReleaseCmd) {
			if (ispresent(im.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_S1AP_IDs.uE_S1AP_ID_pair)) {
				return im.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_S1AP_IDs.uE_S1AP_ID_pair.eNB_UE_S1AP_ID;
			} else {
				return omit;
			}
			}
		case (tr_S1AP_UeContextModificationReq) {
			return im.value_.UEContextModificationRequest.protocolIEs[1].value_.ENB_UE_S1AP_ID;
			}
		case (tr_S1AP_ConnEstInd) {
			return im.value_.ConnectionEstablishmentIndication.protocolIEs[1].value_.ENB_UE_S1AP_ID;
			}
		case (tr_S1AP_RABSetupReq) {
			return im.value_.E_RABSetupRequest.protocolIEs[1].value_.ENB_UE_S1AP_ID;
			}
		/* TODO */
		}
	} else if (ischosen(s1ap.successfulOutcome)) {
		var SuccessfulOutcome so := s1ap.successfulOutcome;
		select (s1ap) {
		case (tr_S1AP_InitialCtxSetupResp) {
			return so.value_.initialContextSetupResponse.protocolIEs[1].value_.ENB_UE_S1AP_ID;
			}
		case (tr_S1AP_UeContextReleaseCompl) {
			return so.value_.UEContextReleaseComplete.protocolIEs[1].value_.ENB_UE_S1AP_ID;
			}
		/* TODO */
		}
	} else if (ischosen(s1ap.unsuccessfulOutcome)) {
		var UnsuccessfulOutcome uo := s1ap.unsuccessfulOutcome;
		select (s1ap) {
		case (tr_S1AP_InitialCtxSetupFail) {
			return uo.value_.initialContextSetupFailure.protocolIEs[1].value_.ENB_UE_S1AP_ID;
			}
		/* TODO */
		}
	}
	return omit;
}

function f_S1AP_get_MME_UE_S1AP_ID(S1AP_PDU s1ap) return template (omit) MME_UE_S1AP_ID
{
	if (ischosen(s1ap.initiatingMessage)) {
		var InitiatingMessage im := s1ap.initiatingMessage;
		select (s1ap) {
		case (tr_S1AP_DlNasTransport) {
			return im.value_.DownlinkNASTransport.protocolIEs[0].value_.MME_UE_S1AP_ID;
			}
		case (tr_S1AP_UlNasTransport) {
			return im.value_.UplinkNASTransport.protocolIEs[0].value_.MME_UE_S1AP_ID;
			}
		case (tr_S1AP_IntialCtxSetupReq) {
			return im.value_.initialContextSetupRequest.protocolIEs[0].value_.MME_UE_S1AP_ID;
			}
		case (tr_S1AP_UeContextReleaseReq) {
			return im.value_.UEContextReleaseRequest.protocolIEs[0].value_.MME_UE_S1AP_ID;
			}
		case (tr_S1AP_UeContextReleaseCmd) {
			if (ispresent(im.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_S1AP_IDs.uE_S1AP_ID_pair)) {
				return im.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_S1AP_IDs.uE_S1AP_ID_pair.mME_UE_S1AP_ID;
			} else {
				return im.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_S1AP_IDs.mME_UE_S1AP_ID;
			}
			}
		case (tr_S1AP_ConnEstInd) {
			return im.value_.ConnectionEstablishmentIndication.protocolIEs[0].value_.MME_UE_S1AP_ID;
			}
		case (tr_S1AP_UeContextModificationReq) {
			return im.value_.UEContextModificationRequest.protocolIEs[0].value_.MME_UE_S1AP_ID;
			}
		case (tr_S1AP_RABSetupReq) {
			return im.value_.E_RABSetupRequest.protocolIEs[0].value_.MME_UE_S1AP_ID;
			}
		/* TODO */
		}
	} else if (ischosen(s1ap.successfulOutcome)) {
		var SuccessfulOutcome so := s1ap.successfulOutcome;
		select (s1ap) {
		case (tr_S1AP_InitialCtxSetupResp) {
			return so.value_.initialContextSetupResponse.protocolIEs[0].value_.MME_UE_S1AP_ID;
			}
		case (tr_S1AP_UeContextReleaseCompl) {
			return so.value_.UEContextReleaseComplete.protocolIEs[0].value_.MME_UE_S1AP_ID;
			}
		/* TODO */
		}
	} else if (ischosen(s1ap.unsuccessfulOutcome)) {
		var UnsuccessfulOutcome uo := s1ap.unsuccessfulOutcome;
		select (s1ap) {
		case (tr_S1AP_InitialCtxSetupFail) {
			return uo.value_.initialContextSetupFailure.protocolIEs[0].value_.MME_UE_S1AP_ID;
			}
		/* TODO */
		}
	}
	return omit;
}

function f_S1AP_get_NAS_PDU(S1AP_PDU s1ap) return template (omit) NAS_PDU
{
	var integer i, j;

	if (ischosen(s1ap.initiatingMessage)) {
		var InitiatingMessage im := s1ap.initiatingMessage;
		select (s1ap) {
		case (tr_S1AP_DlNasTransport) {
			var DownlinkNASTransport msg := im.value_.DownlinkNASTransport;
			for (i := 0; i < lengthof(msg.protocolIEs); i := i+1) {
				if (msg.protocolIEs[i].id == id_NAS_PDU) {
					return msg.protocolIEs[i].value_.NAS_PDU;
				}
			}
			}
		case (tr_S1AP_UlNasTransport) {
			var UplinkNASTransport msg := im.value_.UplinkNASTransport;
			for (i := 0; i < lengthof(msg.protocolIEs); i := i+1) {
				if (msg.protocolIEs[i].id == id_NAS_PDU) {
					return msg.protocolIEs[i].value_.NAS_PDU;
				}
			}
			}
		case (tr_S1AP_IntialCtxSetupReq) {
			var InitialContextSetupRequest msg := im.value_.initialContextSetupRequest;
			for (i := 0; i < lengthof(msg.protocolIEs); i := i+1) {
				if (msg.protocolIEs[i].id == id_E_RABToBeSetupListCtxtSUReq) {
					var E_RABToBeSetupListCtxtSUReq rab_req := msg.protocolIEs[i].value_.E_RABToBeSetupListCtxtSUReq;
					for (j := 0; j < lengthof(rab_req); j := j+1) {
						var E_RABToBeSetupItemCtxtSUReq it := rab_req[j].value_.E_RABToBeSetupItemCtxtSUReq;
						return it.nAS_PDU;
					}
				}
			}
			return omit;
			}
		case (tr_S1AP_RABSetupReq) {
			var E_RABSetupRequest msg := im.value_.E_RABSetupRequest;
			for (i := 0; i < lengthof(msg.protocolIEs); i := i+1) {
				if (msg.protocolIEs[i].id == id_E_RABToBeSetupListBearerSUReq) {
					var E_RABToBeSetupListBearerSUReq rab_req := msg.protocolIEs[i].value_.E_RABToBeSetupListBearerSUReq;
					for (j := 0; j < lengthof(rab_req); j := j+1) {
						var E_RABToBeSetupItemBearerSUReq it := rab_req[j].value_.E_RABToBeSetupItemBearerSUReq;
						return it.nAS_PDU;
					}
				}
			}
			return omit;
			}
		}
	}
	return omit;
}

}
