module HTTP_Adapter {

/* HTTP Adapter component, originally part of Integration Tests for osmo-remsim-server
 * (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
 *
 * This test suite tests osmo-remsim-server by attaching to the external interfaces
 * such as RSPRO for simulated clients + bankds and RSRES (REST backend interface).
 */

import from HTTPmsg_Types all;
import from HTTPmsg_PortType all;
import from Native_Functions all;

type component http_CT {
	port HTTPmsg_PT HTTP;
	var charstring g_http_host;
	var integer g_http_port;
};

function f_http_init(charstring host, integer http_port) runs on http_CT {
	map(self:HTTP, system:HTTP);
	g_http_host := host;
	g_http_port := http_port;
}

template (value) Connect ts_HTTP_Connect(template (value) charstring hostname,
					 template (value) integer http_port := 80,
					 template (value) boolean use_ssl := false) := {
	hostname := hostname,
	portnumber := http_port,
	use_ssl := use_ssl
}
template (value) Close ts_HTTP_Close := { client_id := omit };

/* function to add HeaderLines to a an existing set of HeaderLines. HeaderLines that are already present, are updated. */
function f_overlay_HTTP_Header(HeaderLines hdr, HeaderLines additional_hdr) return template (value) HeaderLines
{
	var integer i;
	var integer k;
	var boolean updated;

	for (i := 0; i < lengthof(additional_hdr); i := i+1) {
		updated := false;
		for (k := 0; k < lengthof(hdr); k := k+1) {
			if (f_str_tolower(hdr[k].header_name) == f_str_tolower(additional_hdr[i].header_name)) {
				hdr[k] := additional_hdr[i];
				updated := true;
			}
		}
		if (updated == false) {
			hdr := hdr & { additional_hdr[i] };
		}
	}

	return hdr;
}

template (value) HeaderLine ts_HeaderLine(charstring header_name, charstring header_value) := {
	header_name := header_name,
	header_value := header_value
}

function f_ts_HTTP_Header(template (omit) charstring body := omit,
			  template (omit) charstring host := omit,
			  HeaderLines custom_hdr := { })
return template (value) HeaderLines {
	var HeaderLines hdr := { };

	/* Build default header */
	if (not istemplatekind(host, "omit")) {
		hdr := hdr & {valueof(ts_HeaderLine("Host", valueof(host)))};
	}
	hdr := hdr & {{ header_name := "Content-Type", header_value := "application/json" }};
	if (not istemplatekind(body, "omit")) {
		hdr := hdr & {valueof(ts_HeaderLine("Content-Length", int2str(lengthof(body))))};
	}

	return f_overlay_HTTP_Header(hdr, custom_hdr);
}

function f_ts_body_or_empty(template (omit) charstring body) return template (value) charstring {
	if (istemplatekind(body, "omit")) {
		return "";
	}
	return body;
}

template (value) HTTPMessage ts_HTTP_Req(charstring url,
					 charstring method := "GET",
					 template (omit) charstring body := omit,
					 integer v_maj := 1, integer v_min := 1,
					 charstring host,
					 HeaderLines custom_hdr := { }) := {
	request := {
		client_id := omit,
		method := method,
		uri := url,
		version_major := v_maj,
		version_minor := v_min,
		header := f_ts_HTTP_Header(body, host, custom_hdr),
		body := f_ts_body_or_empty(body)
	}
}

template HTTPMessage tr_HTTP_Resp(template integer sts := ?) := {
	response := {
		client_id := ?,
		version_major := ?,
		version_minor := ?,
		statuscode := sts,
		statustext := ?,
		header := ?,
		body := ?
	}
};

template HTTPMessage tr_HTTP_Resp2xx := tr_HTTP_Resp((200..299));

function f_http_tx_request(charstring url, charstring method := "GET", template charstring body := omit,
			   HeaderLines custom_hdr := { })
runs on http_CT {
	HTTP.send(ts_HTTP_Connect(g_http_host, g_http_port));
	HTTP.receive(Connect_result:?);
	HTTP.send(ts_HTTP_Req(url, method, body, host := g_http_host & ":" & int2str(g_http_port), custom_hdr := custom_hdr));
}

function f_http_rx_response(template HTTPMessage exp := tr_HTTP_Resp2xx, float tout := 2.0)
runs on http_CT return HTTPMessage {
	var HTTPMessage resp;
	timer T := tout;
	T.start;
	alt {
	[] HTTP.receive(exp) -> value resp {
		setverdict(pass);
		}
	[] HTTP.receive(tr_HTTP_Resp) -> value resp {
		setverdict(fail, "Unexpected HTTP response ", resp);
		}
	[] T.timeout {
		setverdict(fail, "Timeout waiting for HTTP response");
		self.stop;
		}
	}
	HTTP.send(ts_HTTP_Close);
	return resp;
}

/* run a HTTP request and return the response */
function f_http_transact(charstring url, charstring method := "GET",
			 template (omit) charstring body := omit, template HTTPMessage exp := tr_HTTP_Resp2xx,
			 float tout := 2.0, HeaderLines custom_hdr := { })
runs on http_CT return HTTPMessage {
	f_http_tx_request(url, method, body, custom_hdr);
	return f_http_rx_response(exp, tout);
}

}
