module Osmocom_VTY_Functions {
	import from TELNETasp_PortType all;

	modulepar {
		charstring mp_prompt_prefix := "OpenBSC";
	}

	const charstring VTY_VIEW_SUFFIX := "> ";
	const charstring VTY_ENABLE_SUFFIX := "# ";
	const charstring VTY_CFG_SUFFIX := "(*)";

	template charstring t_vty_unknown := pattern "*% Unknown command.";

	/* configure prompts in TELNETasp module */
	function f_vty_set_prompts(TELNETasp_PT pt) {
		var ASP_TelnetDynamicConfig vty_prompt[3] := {
			{
				prompt := {
					id := 1,
					prompt := mp_prompt_prefix & VTY_VIEW_SUFFIX,
					has_wildcards := false
				}
			}, {
				prompt := {
					id := 2,
					prompt := mp_prompt_prefix & VTY_ENABLE_SUFFIX,
					has_wildcards := false
				}
			}, {
				prompt := {
					id := 3,
					prompt := mp_prompt_prefix & VTY_CFG_SUFFIX,
					has_wildcards := true
				}
			}
		};

		/* set some configuration that isn't possible to express
		 * in the config file due to syntactic restrictions (Who invents config
		 * files that don't permit regular expressions? */
		for (var integer i := 0; i < sizeof(vty_prompt); i:= i + 1) {
			log(vty_prompt[i]);
			pt.send(vty_prompt[i]);
		}
	}

	/* wait for any of the permitted prompts; buffer + return all intermediate output */
	function f_vty_wait_for_prompt(TELNETasp_PT pt) return charstring {
		var charstring rx, buf := "";
		timer T := 2.0;

		T.start;
		alt {
			[] pt.receive(mp_prompt_prefix & VTY_VIEW_SUFFIX) { };
			[] pt.receive(mp_prompt_prefix & VTY_ENABLE_SUFFIX) { };
			[] pt.receive(pattern mp_prompt_prefix & VTY_CFG_SUFFIX) { };
			[] pt.receive(t_vty_unknown) {
				testcase.stop(fail, "VTY: Unknown Command");
				};
			[] pt.receive(charstring:?) -> value rx { buf := buf & rx; repeat };
			[] T.timeout {
				setverdict(fail, "VTY Timeout for prompt");
				self.stop;
				};
		}
		T.stop;
		return buf;
	}

	/* send a VTY command and obtain response until prompt is received */
	function f_vty_transceive_ret(TELNETasp_PT pt, charstring tx) return charstring {
		pt.send(tx);
		return f_vty_wait_for_prompt(pt);
	}

	/* send a VTY command and obtain response until prompt is received */
	function f_vty_transceive(TELNETasp_PT pt, charstring tx) {
		f_vty_transceive_ret(pt, tx);
	}

	type integer BtsNr (0..255);
	type integer BtsTrxNr (0..255);
	type integer BtsTimeslotNr (0..7);

	type charstring BtsGprsMode ("none", "gprs", "egrps");

	/* enter the'confiugration' mode of the VTY */
	function f_vty_enter_config(TELNETasp_PT pt) {
		f_vty_transceive(pt, "configure terminal")
	}

	function f_vty_enter_cfg_network(TELNETasp_PT pt) {
		f_vty_enter_config(pt);
		f_vty_transceive(pt, "network")
	}

	function f_vty_enter_cfg_bts(TELNETasp_PT pt, BtsNr bts := 0) {
		f_vty_enter_cfg_network(pt);
		f_vty_transceive(pt, "bts " & int2str(bts));
	}

	function f_vty_enter_cfg_trx(TELNETasp_PT pt, BtsNr bts := 0, BtsTrxNr trx := 0) {
		f_vty_enter_cfg_bts(pt, bts);
		f_vty_transceive(pt, "trx " & int2str(trx));
	}

	function f_vty_enter_cfg_ts(TELNETasp_PT pt, BtsNr bts := 0, BtsTrxNr trx := 0, BtsTimeslotNr ts) {
		f_vty_enter_cfg_trx(pt, bts, trx);
		f_vty_transceive(pt, "timeslot " & int2str(ts));
	}

}
