///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2020 Ericsson Telecom AB
//
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v2.0
// which accompanies this distribution, and is available at
// https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
///////////////////////////////////////////////////////////////////////////////
//  File:               IFW_MQTT_Client_TestSteps.ttcn
//  Description:
//  Rev:                <RnXnn>
//  Prodnr:             CNL 113 910
//  Updated:            2020-02-06
//  Contact:            http://ttcn.ericsson.se
///////////////////////////////////////////////////////////////////////////////
module IFW_MQTT_Client_TestSteps
{
    import from IoT_FT_Framework_Definitions all;
    import from IFW_Common all;
    import from IFW_MQTT_Client_Definitions all;
    import from IFW_MQTT_Client_Functions all;
	import from MQTT_v3_1_1_Types all;

	function f_IFW_MqttClient_init(in integer p_clientIdx) runs on IFW_MAIN_CT
	return boolean
	{
	  var IFW_MQTT_Client_CT v_client := mqttClients[p_clientIdx];
	  if (v_client == null) { log("IFW: No mqtt client found"); return false; }	  
	  f_isRunningGuard(v_client);
	  
	  v_client.start(f_MQTT_Client_init());
      v_client.done;
      
	  return true;	  
	}
	
	function f_IFW_MqttClient_cleanUp(in integer p_clientIdx) runs on IFW_MAIN_CT
	return boolean
	{
	  var IFW_MQTT_Client_CT v_client := mqttClients[p_clientIdx];	  
	  if (v_client == null) { log("IFW: No mqtt client found"); return false; }	  
	  f_isRunningGuard(v_client);
	  
	  v_client.start(f_MQTT_Client_cleanUp());
      v_client.done;
      
	  return true;	  
	}	
	
	function f_IFW_MqttClient_setRemote(in integer p_clientIdx, in charstring p_remoteAddrId) runs on IFW_MAIN_CT
	return boolean
	{
 		var NamedHostPort v_addr;
		if (f_lookupAddress(p_remoteAddrId, v_addr))
		{
			var MqttClientContext v_ctx;
			f_IFW_MqttClient_getContext(p_clientIdx, v_ctx);
			v_ctx.remoteHost := v_addr.hostName;
			v_ctx.remotePort := v_addr.portNumber;
			
			f_IFW_MqttClient_setContext(p_clientIdx, v_ctx);
		}
		return true;
	}	
	
	function f_IFW_MqttClient_getContext(in integer p_clientIdx, out MqttClientContext p_mqttClientContext) runs on IFW_MAIN_CT
	return boolean
	{
	  var IFW_MQTT_Client_CT v_client := mqttClients[p_clientIdx];
	  if (v_client == null) { log("IFW: No mqtt client found"); return false; }	  
	  f_isRunningGuard(v_client);
	  
	  v_client.start(f_MQTT_Client_getContext());
      v_client.done(MqttClientContext:?) -> value p_mqttClientContext;
      
	  return true;
	}
	
	function f_IFW_MqttClient_setContext(in integer p_clientIdx, in MqttClientContext p_mqttClientContext) runs on IFW_MAIN_CT
	return boolean
	{
	  var IFW_MQTT_Client_CT v_client := mqttClients[p_clientIdx];	  
	  if (v_client == null) { log("IFW: No mqtt client found"); return false; }	  
	  f_isRunningGuard(v_client);
	  
	  v_client.start(f_MQTT_Client_setContext(p_mqttClientContext));
      v_client.done;
      
	  return true;
	}
	
    function f_IFW_MqttClient_setMessageToSend(in integer p_clientIdx, MQTT_v3_1_1_ReqResp p_msg) runs on IFW_MAIN_CT
	return boolean
	{
	  var IFW_MQTT_Client_CT v_client := mqttClients[p_clientIdx];	  
	  if (v_client == null) { log("IFW: No mqtt client found"); return false; }	  
	  f_isRunningGuard(v_client);
	  
	  v_client.start(f_MQTT_Client_setMessageToSend(p_msg));
      v_client.done;
      
	  return true;
	}
	
	function f_IFW_MqttClient_send(in integer p_clientIdx) runs on IFW_MAIN_CT
	return boolean
	{
	  var IFW_MQTT_Client_CT v_client := mqttClients[p_clientIdx];	  
	  if (v_client == null) { log("IFW: No mqtt client found"); return false; }	  
	  f_isRunningGuard(v_client);
	  
	  v_client.start(f_MQTT_Client_send());
      v_client.done;
      
	  return true;
	}
	
	function f_IFW_MqttClient_receive(in integer p_clientIdx) runs on IFW_MAIN_CT
	return boolean
	{
	  var IFW_MQTT_Client_CT v_client := mqttClients[p_clientIdx];	  
	  if (v_client == null) { log("IFW: No mqtt client found"); return false; }	  
	  f_isRunningGuard(v_client);
	  
	  v_client.start(f_MQTT_Client_receive());
      v_client.done;
      
	  return true;
	}
	
	function f_IFW_MqttClient_check(in integer p_clientIdx, template MQTT_v3_1_1_ReqResp p_msg) runs on IFW_MAIN_CT
	return boolean
	{
	  var boolean v_ret;
	  var IFW_MQTT_Client_CT v_client := mqttClients[p_clientIdx];	  
	  if (v_client == null) { log("IFW: No mqtt client found"); return false; }	  
	  f_isRunningGuard(v_client);
	  
	  v_client.start(f_MQTT_Client_check(p_msg));
      v_client.done(ReturnBoolean:?) -> value v_ret; 
      
	  return v_ret;
	}

}
