package org.etsi.mts.tdl.execution.java.tri;

/**
 * Provides the mechanism for communicating with the system under test. This is
 * usually a protocol stack implementation or an adapter for user interface.
 * 
 * An implementation may choose to support multiple concurrent connections and
 * either a message or procedure based communication (or both) depending on the
 * testing needs.
 *
 * An implementation <b>must</b> be able to handle multiple receive calls (be
 * the execution engine) for the same incoming data (see:
 * {@link #receive(Data, Connection) receive()}. Received data should be managed
 * using FIFO stack.
 */
public interface SystemAdapter {

	/**
	 * Prepare the adapter for all connections configured for an upcoming test
	 * description execution. This method is called before any test behaviour is
	 * executed and is a good place for doing any necessary initialization.
	 */
	void configure(Connection[] connections);

	/**
	 * Encode and send the data to system under test using protocol or adapter
	 * specific means.
	 * 
	 * @param message    The data to be sent.
	 * @param connection The connection on which the message is to be sent.
	 */
	void send(Data message, Connection connection);

	/**
	 * Blocks until incoming data is available and tries to decode the first
	 * received data chunk using provided type and match against provided value.
	 * <p>
	 * Implementation should only consider one (the oldest) chunk of incoming data
	 * at a time. If the data matches then it is decoded and returned, otherwise the
	 * method throws <b>AssertionError</b>.
	 * <p>
	 * Special <b>null</b> value is used for <code>expected</code> parameter when
	 * the adapter should accept any data and return it (potentially without
	 * decoding). This value is only used for logging (and the format must thus be
	 * supported by the {@link Reporter Reporter} implementation).
	 * 
	 * @param expected   The type to be used for decoding incoming data and value to
	 *                   match against. If null then returns any data that is
	 *                   available after decoding.
	 * @param connection The connection on which the message is to be received.
	 * @return The data in expected format or null if most recent data didn't match
	 *         the expected one.
	 * @throws InterruptedException If the waiting thread is interrupted.
	 * @throws AssertionError       If the received data didn't match the expected
	 *                              data.
	 */
	Data receive(Data expected, Connection connection) throws InterruptedException, AssertionError;

	/**
	 * Calls a remote procedure and blocks until reply is received or exception is
	 * thrown.
	 * <p>
	 * Either <code>expectedReturn</code> or <code>expectedException</code> shall be
	 * provided, but not both. When the reply/exception is received, tries to decode
	 * and match against <code>expectedReturn</code> or
	 * <code>expectedException</code> respectively.
	 * <p>
	 * The received reply or exception is always considered handled when this
	 * function returns.
	 * 
	 * @param operation         The operation to call.
	 * @param arguments         All argument values for operation parameters.
	 * @param expectedReturn    The type to be used for decoding received reply and
	 *                          value to match against.
	 * @param expectedException The type to be used for decoding received exception
	 *                          and value to match against.
	 * @param connection        The connection on which the procedure is to be
	 *                          called.
	 * @return The reply or exception in expected format.
	 * @throws InterruptedException If the waiting thread is interrupted.
	 * @throws AssertionError       If the received reply or exception didn't match
	 *                              the expected data.
	 */
	Data call(Procedure operation, Argument[] arguments, Data expectedReturn, Data expectedException,
			Connection connection) throws InterruptedException, AssertionError;

	/**
	 * @see #receive(Data, Connection)
	 */
	Data[] receiveCall(Procedure operation, Data[] expectedArguments, Connection connection)
			throws InterruptedException, AssertionError;

	/**
	 * Encode and send the <code>reply</code> or <code>exception</code> to system
	 * under test using protocol or adapter specific means.
	 * 
	 * @param operation  The operation to which to respond.
	 * @param reply      The reply to be sent.
	 * @param exception  The exception to be raised.
	 * @param connection The connection on which the response is to be sent.
	 */
	void replyCall(Procedure operation, Data reply, Data exception, Connection connection);

}
