/*-------------------------------------------------------------------------
 * drawElements Quality Program Tester Core
 * ----------------------------------------
 *
 * 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 Thread test utilities
 *//*--------------------------------------------------------------------*/

#include "tcuThreadUtil.hpp"

#include "deClock.h"
#include "deMemory.h"

using std::vector;
using de::SharedPtr;

namespace tcu
{
namespace ThreadUtil
{

Event::Event (void)
	: m_result		(RESULT_NOT_READY)
	, m_waiterCount	(0)
	, m_waiters		(0, 0)
{
}

Event::~Event (void)
{
}

void Event::setResult (Result result)
{
	m_lock.lock();
	DE_ASSERT(m_result == RESULT_NOT_READY);
	m_result = result;
	m_lock.unlock();

	for (int i = 0; i < m_waiterCount; i++)
		m_waiters.increment();
}

Event::Result Event::waitReady (void)
{
	m_lock.lock();

	if (m_result == RESULT_NOT_READY)
		m_waiterCount++;
	else
	{
		m_lock.unlock();
		return m_result;
	}

	m_lock.unlock();

	m_waiters.decrement();

	return m_result;
}

Object::Object (const char* type, SharedPtr<Event> e)
	: m_type	(type)
	, m_modify	(e)
{
}

Object::~Object	(void)
{
}

void Object::read (SharedPtr<Event> event, std::vector<SharedPtr<Event> >& deps)
{
	// Make call depend on last modifying call
	deps.push_back(m_modify);

	// Add read dependency
	m_reads.push_back(event);
}

void Object::modify (SharedPtr<Event> event, std::vector<SharedPtr<Event> >& deps)
{
	// Make call depend on all reads
	for (int readNdx = 0; readNdx < (int)m_reads.size(); readNdx++)
	{
		deps.push_back(m_reads[readNdx]);
	}
	deps.push_back(m_modify);

	// Update last modifying call
	m_modify = event;

	// Clear read dependencies of last "version" of this object
	m_reads.clear();
}

Operation::Operation (const char* name)
	: m_name	(name)
	, m_event	(new Event)
{
}

Operation::~Operation (void)
{
}

void Operation::execute (Thread& thread)
{
	bool success = true;

	// Wait for dependencies and check that they succeeded
	for (int depNdx = 0; depNdx < (int)m_deps.size(); depNdx++)
	{
		if (m_deps[depNdx]->waitReady() != Event::RESULT_OK)
			success = false;
	}

	// Try execute operation
	if (success)
	{
		try
		{
			exec(thread);
		}
		catch (...)
		{
			// Got exception event failed
			m_event->setResult(Event::RESULT_FAILED);
			throw;
		}

		m_event->setResult(Event::RESULT_OK);
	}
	else
		// Some dependencies failed
		m_event->setResult(Event::RESULT_FAILED);

	// Release resources
	m_deps.clear();
	m_event = SharedPtr<Event>();
}

const MessageBuilder::EndToken Message::End = MessageBuilder::EndToken();

void MessageBuilder::operator<< (const EndToken&)
{
	m_thread.pushMessage(m_stream.str());
}

Thread::Thread (deUint32 seed)
	: m_random	(seed)
	, m_status	(THREADSTATUS_NOT_STARTED)
{
}

Thread::~Thread (void)
{
	for (int operationNdx = 0; operationNdx < (int)m_operations.size(); operationNdx++)
		delete m_operations[operationNdx];

	m_operations.clear();
}

deUint8* Thread::getDummyData (size_t size)
{
	if (m_dummyData.size() < size)
	{
		m_dummyData.resize(size);
	}

	return &(m_dummyData[0]);
}

void Thread::addOperation (Operation* operation)
{
	m_operations.push_back(operation);
}

void Thread::run (void)
{
	setStatus(THREADSTATUS_RUNNING);
	bool initOk = false;

	// Reserve at least two messages for each operation
	m_messages.reserve(m_operations.size()*2);
	try
	{
		init();
		initOk = true;
		for (int operationNdx = 0; operationNdx < (int)m_operations.size(); operationNdx++)
			m_operations[operationNdx]->execute(*this);

		deinit();
		setStatus(THREADSTATUS_READY);
	}
	catch (const tcu::NotSupportedError& e)
	{
		newMessage() << "tcu::NotSupportedError '" << e.what() << "'" << Message::End;
		deinit();
		setStatus(initOk ? THREADSTATUS_NOT_SUPPORTED : THREADSTATUS_INIT_FAILED);
	}
	catch (const tcu::Exception& e)
	{
		newMessage() << "tcu::Exception '" << e.what() << "'" << Message::End;
		deinit();
		setStatus(initOk ? THREADSTATUS_FAILED : THREADSTATUS_INIT_FAILED);
	}
	catch (const std::exception& error)
	{
		newMessage() << "std::exception '" << error.what() << "'" << Message::End;
		deinit();
		setStatus(initOk ? THREADSTATUS_FAILED : THREADSTATUS_INIT_FAILED);
	}
	catch (...)
	{
		newMessage() << "Unkown exception" << Message::End;
		deinit();
		setStatus(initOk ? THREADSTATUS_FAILED : THREADSTATUS_INIT_FAILED);
	}
}

void Thread::exec (void)
{
	start();
}

void Thread::pushMessage (const std::string& str)
{
	de::ScopedLock lock(m_messageLock);
	m_messages.push_back(Message(deGetMicroseconds(), str.c_str()));
}

int Thread::getMessageCount	 (void) const
{
	de::ScopedLock lock(m_messageLock);
	return (int)(m_messages.size());
}

Message Thread::getMessage (int index) const
{
	de::ScopedLock lock(m_messageLock);
	return m_messages[index];
}


DataBlock::DataBlock (SharedPtr<Event> event)
	: Object("DataBlock", event)
{
}

void DataBlock::setData (size_t size, const void* data)
{
	m_data = std::vector<deUint8>(size);
	deMemcpy(&(m_data[0]), data, size);
}

CompareData::CompareData (SharedPtr<DataBlock> a, SharedPtr<DataBlock> b)
	: Operation	("CompareData")
	, m_a		(a)
	, m_b		(b)
{
	readObject(SharedPtr<Object>(a));
	readObject(SharedPtr<Object>(b));
}

void CompareData::exec (Thread& thread)
{
	bool result = true;
	DE_ASSERT(m_a->getSize() == m_b->getSize());

	thread.newMessage() << "Begin -- CompareData" << Message::End;

	for (int byteNdx = 0; byteNdx < (int)m_a->getSize(); byteNdx++)
	{
		if (m_a->getData()[byteNdx] != m_b->getData()[byteNdx])
		{
			result = false;
			thread.newMessage() << "CompareData failed at offset :" << byteNdx << Message::End;
			break;
		}
	}

	if (result)
		thread.newMessage() << "CompareData passed" << Message::End;
	else
		TCU_FAIL("Data comparision failed");

	thread.newMessage() << "End -- CompareData" << Message::End;
}

} // ThreadUtil
} // tcu
