/*-------------------------------------------------------------------------
 * 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 (int 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)
{
	m_status = 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();
		m_status =  THREADSTATUS_READY;
	}
	catch (const tcu::NotSupportedError& e)
	{
		newMessage() << "tcu::NotSupportedError '" << e.what() << "'" << Message::End;
		deinit();
		m_status = (initOk ? THREADSTATUS_NOT_SUPPORTED : THREADSTATUS_INIT_FAILED);
	}
	catch (const tcu::Exception& e)
	{
		newMessage() << "tcu::Exception '" << e.what() << "'" << Message::End;
		deinit();
		m_status = (initOk ? THREADSTATUS_FAILED : THREADSTATUS_INIT_FAILED);
	}
	catch (const std::exception& error)
	{
		newMessage() << "std::exception '" << error.what() << "'" << Message::End;
		deinit();
		m_status = (initOk ? THREADSTATUS_FAILED : THREADSTATUS_INIT_FAILED);
	}
	catch (...)
	{
		newMessage() << "Unkown exception" << Message::End;
		deinit();
		m_status = (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, (int)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
