module BSC_MS_Simulation {

/* (C) 2017-2018 Harald Welte <laforge@gnumonks.org>
 * (C) 2018 sysmocom - s.f.m.c. Gmbh; Author: Daniel Willmann
 * 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 IPL4asp_Types all;

import from IPA_Emulation all;

import from Osmocom_CTRL_Functions all;
import from Osmocom_CTRL_Types all;

import from SCCP_Types all;
import from SCCPasp_Types all;
import from SCCP_Emulation all;

import from BSSAP_CodecPort all;
import from RAN_Emulation all;

import from BSC_MS_ConnectionHandler all;

type function void_fn_bsc(charstring id) runs on BSC_CT;
type record of BSC_MS_ConnHdlr BSC_MS_ConnHdlrList;

type component BSC_CT {
	/* component references */
	var IPA_Emulation_CT vc_IPA;
	var SCCP_CT vc_SCCP;
	var RAN_Emulation_CT vc_BSSMAP;
	/* test port to SCCP emulation */
	port SCCPasp_PT SCCP;
	/* test port to SCCPLite CTRL over IPA emulation */
	port IPA_CTRL_PT SCCPLITE_IPA_CTRL;

	var BSC_MS_TestHdlrParams g_pars;

	var charstring g_bsc_num_str;
}

modulepar {
	integer mp_num_iterations := 10;
}

/* helper function to create and connect a BSC_MS_ConnHdlr component */
private function f_connect_handler(inout BSC_MS_ConnHdlr vc_conn) runs on BSC_CT {
	/* connect client BSSAP port to BSSAP dispatcher */
	connect(vc_conn:BSSAP, vc_BSSMAP:CLIENT);
}

private function f_start_handler(void_fn_bsc_ms fn, charstring id, template (omit) BSC_MS_TestHdlrParams pars := omit)
runs on BSC_CT return BSC_MS_ConnHdlr {
	var BSC_MS_ConnHdlr vc_conn;
	vc_conn := BSC_MS_ConnHdlr.create(id);
	f_connect_handler(vc_conn);
	vc_conn.start(f_handler_init(fn, id, pars));
	return vc_conn;
}

/* first function inside ConnHdlr component; sets g_pars + starts function */
private function f_handler_init(void_fn_bsc_ms fn, charstring id, template (omit) BSC_MS_TestHdlrParams pars := omit)
runs on BSC_MS_ConnHdlr {
	if (isvalue(pars)) {
		g_pars := valueof(pars);
	}
	fn.apply(id);
}

function bsc_do_nothing(charstring id)
runs on BSC_CT {
}

/* Submit a location-state TRAP BSC->BSC-NAT */
function bsc_ctrl_location(charstring id)
runs on BSC_CT {
	log("Starting main of BSC_CT");
	f_ctrl_trap(SCCPLITE_IPA_CTRL, "bts.0.location-state",
		    "1234567,fix3d,0.340000,0.560000,0.780000,operational,unlocked,on,001,01");
	f_ctrl_exp_set(SCCPLITE_IPA_CTRL, "rf_locked", "1", "1");
}

function main(charstring remote_ip, PortNumber remote_port,
		charstring local_ip, PortNumber local_port,
		MSC_SCCP_MTP3_parameters sccp_pars,
		BSC_MS_TestHdlrParams pars,
		void_fn_bsc_ms fn_bsc_ms, void_fn_bsc fn_bsc, charstring id) runs on BSC_CT
{
	var integer i := 0;
	timer T := 2.0;
	var IPA_CCM_Parameters ccm_pars := IPA_Emulation.c_IPA_default_ccm_pars;
	ccm_pars.name := id;
	g_pars := pars;

	/* create components for IPA/SCCP/BSS[M]AP stack */
	vc_IPA := IPA_Emulation_CT.create(id & "-IPA");
	vc_SCCP := SCCP_CT.create(id & "-SCCP");
	vc_BSSMAP := RAN_Emulation_CT.create(id & "-BSSMAP");

	map(vc_IPA:IPA_PORT, system:IPA_CODEC_PT);

	/* connect MTP3 service provider (IPA) to lower side of SCCP */
	connect(vc_IPA:MTP3_SP_PORT, vc_SCCP:MTP3_SCCP_PORT);

	/* connect BSSMAP dispatcher to upper side of SCCP */
	connect(vc_BSSMAP:BSSAP, vc_SCCP:SCCP_SP_PORT);

	/* connect BSSMAP dispatcher to IPA_Emulation MGCP */
	connect(vc_BSSMAP:MGCP, vc_IPA:IPA_MGCP_PORT);
	/* connect BSSMAP dispatcher to IPA_Emulation CTRL */
	connect(vc_BSSMAP:CTRL, vc_IPA:IPA_CTRL_PORT);

	/* connect BSSMAP dispatcher to IPA_Emulation CTRL */
	connect(self:SCCPLITE_IPA_CTRL, vc_BSSMAP:CTRL_CLIENT);

	/* start components */
	vc_IPA.start(IPA_Emulation.main_client(remote_ip, remote_port, local_ip, local_port, ccm_pars));
	vc_SCCP.start(SCCPStart(sccp_pars));
	vc_BSSMAP.start(RAN_Emulation.main(BSC_MS_ConnectionHandler.BSC_MS_RanOps, id));

	/* Initial delay to wait for IPA connection establishment */
	T.start;
	alt {
	[] SCCPLITE_IPA_CTRL.receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_UP}) { }
	[] T.timeout {
		setverdict(fail, "Timeout CTRL waiting for ASP_IPA_EVENT_UP");
		mtc.stop;
		}
	}

	var BSC_MS_ConnHdlrList vc_conns;
	for (i := 0; i < mp_num_iterations; i := i+1) {
		vc_conns[i] := f_start_handler(fn_bsc_ms, id & "-MS-" & int2str(i), g_pars);
	}

	fn_bsc.apply(id);

	for (i := 0; i < mp_num_iterations; i := i+1) {
		vc_conns[i].done;
	}

	/* explicitly stop all components that we started above */
	vc_IPA.stop;
	vc_BSSMAP.stop;
	vc_SCCP.stop;
}

}
