/*-------------------------------------------------------------------------
 * drawElements Quality Program Execution Server
 * ---------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Test Driver.
 *//*--------------------------------------------------------------------*/

#include "xsTestDriver.hpp"
#include "deClock.h"

#include <string>
#include <vector>
#include <cstdio>

using std::string;
using std::vector;

#if 0
#	define DBG_PRINT(X) printf X
#else
#	define DBG_PRINT(X)
#endif

namespace xs
{

TestDriver::TestDriver (xs::TestProcess* testProcess)
	: m_state				(STATE_NOT_STARTED)
	, m_lastExitCode		(0)
	, m_process				(testProcess)
	, m_lastProcessDataTime	(0)
	, m_dataMsgTmpBuf		(SEND_RECV_TMP_BUFFER_SIZE)
{
}

TestDriver::~TestDriver (void)
{
	reset();
}

void TestDriver::reset (void)
{
	m_process->cleanup();

	m_state = STATE_NOT_STARTED;
}

void TestDriver::startProcess (const char* name, const char* params, const char* workingDir, const char* caseList)
{
	try
	{
		m_process->start(name, params, workingDir, caseList);
		m_state = STATE_PROCESS_STARTED;
	}
	catch (const TestProcessException& e)
	{
		printf("Failed to launch test process: %s\n", e.what());
		m_state				= STATE_PROCESS_LAUNCH_FAILED;
		m_lastLaunchFailure	= e.what();
	}
}

void TestDriver::stopProcess (void)
{
	m_process->terminate();
}

bool TestDriver::poll (ByteBuffer& messageBuffer)
{
	switch (m_state)
	{
		case STATE_NOT_STARTED:
			return false; // Nothing to report.

		case STATE_PROCESS_LAUNCH_FAILED:
			DBG_PRINT(("  STATE_PROCESS_LAUNCH_FAILED\n"));
			if (writeMessage(messageBuffer, ProcessLaunchFailedMessage(m_lastLaunchFailure.c_str())))
			{
				m_state				= STATE_NOT_STARTED;
				m_lastLaunchFailure	= "";
				return true;
			}
			else
				return false;

		case STATE_PROCESS_STARTED:
			DBG_PRINT(("  STATE_PROCESS_STARTED\n"));
			if (writeMessage(messageBuffer, ProcessStartedMessage()))
			{
				m_state = STATE_PROCESS_RUNNING;
				return true;
			}
			else
				return false;

		case STATE_PROCESS_RUNNING:
		{
			DBG_PRINT(("  STATE_PROCESS_RUNNING\n"));
			bool gotProcessData = false;

			// Poll log file and info buffer.
			gotProcessData = pollLogFile(messageBuffer)	|| gotProcessData;
			gotProcessData = pollInfo(messageBuffer)	|| gotProcessData;

			if (gotProcessData)
				return true; // Got IO.

			if (!m_process->isRunning())
			{
				// Process died.
				m_state					= STATE_READING_DATA;
				m_lastExitCode			= m_process->getExitCode();
				m_lastProcessDataTime	= deGetMicroseconds();

				return true; // Got state change.
			}

			return false; // Nothing to report.
		}

		case STATE_READING_DATA:
		{
			DBG_PRINT(("  STATE_READING_DATA\n"));
			bool gotProcessData = false;

			// Poll log file and info buffer.
			gotProcessData = pollLogFile(messageBuffer)	|| gotProcessData;
			gotProcessData = pollInfo(messageBuffer)	|| gotProcessData;

			if (gotProcessData)
			{
				// Got data.
				m_lastProcessDataTime = deGetMicroseconds();
				return true;
			}
			else if (deGetMicroseconds() - m_lastProcessDataTime > READ_DATA_TIMEOUT*1000)
			{
				// Read timeout occurred.
				m_state = STATE_PROCESS_FINISHED;
				return true; // State change.
			}
			else
				return false; // Still waiting for data.
		}

		case STATE_PROCESS_FINISHED:
			DBG_PRINT(("  STATE_PROCESS_FINISHED\n"));
			if (writeMessage(messageBuffer, ProcessFinishedMessage(m_lastExitCode)))
			{
				// Signal TestProcess to clean up any remaining resources.
				m_process->cleanup();

				m_state			= STATE_NOT_STARTED;
				m_lastExitCode	= 0;
				return true;
			}
			else
				return false;

		default:
			DE_ASSERT(DE_FALSE);
			return false;
	}
}

bool TestDriver::pollLogFile (ByteBuffer& messageBuffer)
{
	return pollBuffer(messageBuffer, MESSAGETYPE_PROCESS_LOG_DATA);
}

bool TestDriver::pollInfo (ByteBuffer& messageBuffer)
{
	return pollBuffer(messageBuffer, MESSAGETYPE_INFO);
}

bool TestDriver::pollBuffer (ByteBuffer& messageBuffer, MessageType msgType)
{
	const int minBytesAvailable = MESSAGE_HEADER_SIZE + MIN_MSG_PAYLOAD_SIZE;

	if (messageBuffer.getNumFree() < minBytesAvailable)
		return false; // Not enough space in message buffer.

	const int	maxMsgSize	= de::min((int)m_dataMsgTmpBuf.size(), messageBuffer.getNumFree());
	int			numRead		= 0;
	int			msgSize		= MESSAGE_HEADER_SIZE+1; // One byte is reserved for terminating 0.

	// Fill in data \note Last byte is reserved for 0.
	numRead = msgType == MESSAGETYPE_PROCESS_LOG_DATA
			? m_process->readTestLog(&m_dataMsgTmpBuf[MESSAGE_HEADER_SIZE], maxMsgSize-MESSAGE_HEADER_SIZE-1)
			: m_process->readInfoLog(&m_dataMsgTmpBuf[MESSAGE_HEADER_SIZE], maxMsgSize-MESSAGE_HEADER_SIZE-1);

	if (numRead <= 0)
		return false; // Didn't get any data.

	msgSize += numRead;

	// Terminate with 0.
	m_dataMsgTmpBuf[msgSize-1] = 0;

	// Write header.
	Message::writeHeader(msgType, msgSize, &m_dataMsgTmpBuf[0], MESSAGE_HEADER_SIZE);

	// Write to messagebuffer.
	messageBuffer.pushFront(&m_dataMsgTmpBuf[0], msgSize);

	DBG_PRINT(("  wrote %d bytes of %s data\n", msgSize, msgType == MESSAGETYPE_INFO ? "info" : "log"));

	return true;
}

bool TestDriver::writeMessage (ByteBuffer& messageBuffer, const Message& message)
{
	vector<deUint8> buf;
	message.write(buf);

	if (messageBuffer.getNumFree() < (int)buf.size())
		return false;

	messageBuffer.pushFront(&buf[0], (int)buf.size());
	return true;
}

} // xs
