/*-------------------------------------------------------------------------
 * 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::getUnusedData (size_t size)
{
	if (m_unusedData.size() < size)
	{
		m_unusedData.resize(size);
	}

	return &(m_unusedData[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
