/*-------------------------------------------------------------------------
 * Vulkan CTS Framework
 * --------------------
 *
 * Copyright (c) 2015 Google Inc.
 *
 * 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 Program binary registry.
 *//*--------------------------------------------------------------------*/

#include "vkBinaryRegistry.hpp"
#include "tcuResource.hpp"
#include "tcuFormatUtil.hpp"
#include "deFilePath.hpp"
#include "deStringUtil.hpp"
#include "deDirectoryIterator.hpp"
#include "deString.h"
#include "deInt32.h"
#include "deFile.h"

#include <sstream>
#include <fstream>
#include <stdexcept>
#include <limits>

namespace vk
{
namespace BinaryRegistryDetail
{

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

namespace
{

string getProgramFileName (deUint32 index)
{
	return de::toString(tcu::toHex(index)) + ".spv";
}

string getProgramPath (const std::string& dirName, deUint32 index)
{
	return de::FilePath::join(dirName, getProgramFileName(index)).getPath();
}

bool isHexChr (char c)
{
	return de::inRange(c, '0', '9') || de::inRange(c, 'a', 'f') || de::inRange(c, 'A', 'F');
}

bool isProgramFileName (const std::string& name)
{
	// 0x + 00000000 + .spv
	if (name.length() != (2 + 8 + 4))
		return false;

	if (name[0] != '0' ||
		name[1] != 'x' ||
		name[10] != '.' ||
		name[11] != 's' ||
		name[12] != 'p' ||
		name[13] != 'v')
		return false;

	for (size_t ndx = 2; ndx < 10; ++ndx)
	{
		if (!isHexChr(name[ndx]))
			return false;
	}

	return true;
}

deUint32 getProgramIndexFromName (const std::string& name)
{
	DE_ASSERT(isProgramFileName(name));

	deUint32			index	= ~0u;
	std::stringstream	str;

	str << std::hex << name.substr(2,10);
	str >> index;

	DE_ASSERT(getProgramFileName(index) == name);

	return index;
}

string getIndexPath (const std::string& dirName)
{
	return de::FilePath::join(dirName, "index.bin").getPath();
}

void writeBinary (const ProgramBinary& binary, const std::string& dstPath)
{
	const de::FilePath	filePath(dstPath);

	if (!de::FilePath(filePath.getDirName()).exists())
		de::createDirectoryAndParents(filePath.getDirName().c_str());

	{
		std::ofstream	out		(dstPath.c_str(), std::ios_base::binary);

		if (!out.is_open() || !out.good())
			throw tcu::Exception("Failed to open " + dstPath);

		out.write((const char*)binary.getBinary(), binary.getSize());
		out.close();
	}
}

void writeBinary (const std::string& dstDir, deUint32 index, const ProgramBinary& binary)
{
	writeBinary(binary, getProgramPath(dstDir, index));
}

ProgramBinary* readBinary (const std::string& srcPath)
{
	std::ifstream	in		(srcPath.c_str(), std::ios::binary | std::ios::ate);
	const size_t	size	= (size_t)in.tellg();

	if (!in.is_open() || !in.good())
		throw tcu::Exception("Failed to open " + srcPath);

	if (size == 0)
		throw tcu::Exception("Malformed binary, size = 0");

	in.seekg(0, std::ios::beg);

	{
		std::vector<deUint8>	bytes	(size);

		in.read((char*)&bytes[0], size);
		DE_ASSERT(bytes[0] != 0);

		return new ProgramBinary(vk::PROGRAM_FORMAT_SPIRV, bytes.size(), &bytes[0]);
	}
}

deUint32 binaryHash (const ProgramBinary* binary)
{
	return deMemoryHash(binary->getBinary(), binary->getSize());
}

deBool binaryEqual (const ProgramBinary* a, const ProgramBinary* b)
{
	if (a->getSize() == b->getSize())
		return deMemoryEqual(a->getBinary(), b->getBinary(), a->getSize());
	else
		return DE_FALSE;
}

std::vector<deUint32> getSearchPath (const ProgramIdentifier& id)
{
	const std::string	combinedStr		= id.testCasePath + '#' + id.programName;
	const size_t		strLen			= combinedStr.size();
	const size_t		numWords		= strLen/4 + 1;		// Must always end up with at least one 0 byte
	vector<deUint32>	words			(numWords, 0u);

	deMemcpy(&words[0], combinedStr.c_str(), strLen);

	return words;
}

const deUint32* findBinaryIndex (BinaryIndexAccess* index, const ProgramIdentifier& id)
{
	const vector<deUint32>	words	= getSearchPath(id);
	size_t					nodeNdx	= 0;
	size_t					wordNdx	= 0;

	for (;;)
	{
		const BinaryIndexNode&	curNode	= (*index)[nodeNdx];

		if (curNode.word == words[wordNdx])
		{
			if (wordNdx+1 < words.size())
			{
				TCU_CHECK_INTERNAL((size_t)curNode.index < index->size());

				nodeNdx  = curNode.index;
				wordNdx	+= 1;
			}
			else if (wordNdx+1 == words.size())
				return &curNode.index;
			else
				return DE_NULL;
		}
		else if (curNode.word != 0)
		{
			nodeNdx += 1;

			// Index should always be null-terminated
			TCU_CHECK_INTERNAL(nodeNdx < index->size());
		}
		else
			return DE_NULL;
	}

	return DE_NULL;
}

//! Sparse index node used for final binary index construction
struct SparseIndexNode
{
	deUint32						word;
	deUint32						index;
	std::vector<SparseIndexNode*>	children;

	SparseIndexNode (deUint32 word_, deUint32 index_)
		: word	(word_)
		, index	(index_)
	{}

	SparseIndexNode (void)
		: word	(0)
		, index	(0)
	{}

	~SparseIndexNode (void)
	{
		for (size_t ndx = 0; ndx < children.size(); ndx++)
			delete children[ndx];
	}
};

#if defined(DE_DEBUG)
bool isNullByteTerminated (deUint32 word)
{
	deUint8 bytes[4];
	deMemcpy(bytes, &word, sizeof(word));
	return bytes[3] == 0;
}
#endif

void addToSparseIndex (SparseIndexNode* group, const deUint32* words, size_t numWords, deUint32 index)
{
	const deUint32		curWord	= words[0];
	SparseIndexNode*	child	= DE_NULL;

	for (size_t childNdx = 0; childNdx < group->children.size(); childNdx++)
	{
		if (group->children[childNdx]->word == curWord)
		{
			child = group->children[childNdx];
			break;
		}
	}

	DE_ASSERT(numWords > 1 || !child);

	if (!child)
	{
		group->children.reserve(group->children.size()+1);
		group->children.push_back(new SparseIndexNode(curWord, numWords == 1 ? index : 0));

		child = group->children.back();
	}

	if (numWords > 1)
		addToSparseIndex(child, words+1, numWords-1, index);
	else
		DE_ASSERT(isNullByteTerminated(curWord));
}

// Prepares sparse index for finalization. Ensures that child with word = 0 is moved
// to the end, or one is added if there is no such child already.
void normalizeSparseIndex (SparseIndexNode* group)
{
	int		zeroChildPos	= -1;

	for (size_t childNdx = 0; childNdx < group->children.size(); childNdx++)
	{
		normalizeSparseIndex(group->children[childNdx]);

		if (group->children[childNdx]->word == 0)
		{
			DE_ASSERT(zeroChildPos < 0);
			zeroChildPos = (int)childNdx;
		}
	}

	if (zeroChildPos >= 0)
	{
		// Move child with word = 0 to last
		while (zeroChildPos != (int)group->children.size()-1)
		{
			std::swap(group->children[zeroChildPos], group->children[zeroChildPos+1]);
			zeroChildPos += 1;
		}
	}
	else if (!group->children.empty())
	{
		group->children.reserve(group->children.size()+1);
		group->children.push_back(new SparseIndexNode(0, 0));
	}
}

deUint32 getIndexSize (const SparseIndexNode* group)
{
	size_t	numNodes	= group->children.size();

	for (size_t childNdx = 0; childNdx < group->children.size(); childNdx++)
		numNodes += getIndexSize(group->children[childNdx]);

	DE_ASSERT(numNodes <= std::numeric_limits<deUint32>::max());

	return (deUint32)numNodes;
}

deUint32 addAndCountNodes (BinaryIndexNode* index, deUint32 baseOffset, const SparseIndexNode* group)
{
	const deUint32	numLocalNodes	= (deUint32)group->children.size();
	deUint32		curOffset		= numLocalNodes;

	// Must be normalized prior to construction of final index
	DE_ASSERT(group->children.empty() || group->children.back()->word == 0);

	for (size_t childNdx = 0; childNdx < numLocalNodes; childNdx++)
	{
		const SparseIndexNode*	child		= group->children[childNdx];
		const deUint32			subtreeSize	= addAndCountNodes(index+curOffset, baseOffset+curOffset, child);

		index[childNdx].word = child->word;

		if (subtreeSize == 0)
			index[childNdx].index = child->index;
		else
		{
			DE_ASSERT(child->index == 0);
			index[childNdx].index = baseOffset+curOffset;
		}

		curOffset += subtreeSize;
	}

	return curOffset;
}

void buildFinalIndex (std::vector<BinaryIndexNode>* dst, const SparseIndexNode* root)
{
	const deUint32	indexSize	= getIndexSize(root);

	if (indexSize > 0)
	{
		dst->resize(indexSize);
		addAndCountNodes(&(*dst)[0], 0, root);
	}
	else
	{
		// Generate empty index
		dst->resize(1);
		(*dst)[0].word	= 0u;
		(*dst)[0].index	= 0u;
	}
}

void buildBinaryIndex (std::vector<BinaryIndexNode>* dst, size_t numEntries, const ProgramIdentifierIndex* entries)
{
	de::UniquePtr<SparseIndexNode>	sparseIndex	(new SparseIndexNode());

	for (size_t ndx = 0; ndx < numEntries; ndx++)
	{
		const std::vector<deUint32>	searchPath	= getSearchPath(entries[ndx].id);
		addToSparseIndex(sparseIndex.get(), &searchPath[0], searchPath.size(), entries[ndx].index);
	}

	normalizeSparseIndex(sparseIndex.get());
	buildFinalIndex(dst, sparseIndex.get());
}

} // anonymous

// BinaryIndexHash

DE_IMPLEMENT_POOL_HASH(BinaryIndexHashImpl, const ProgramBinary*, deUint32, binaryHash, binaryEqual);

BinaryIndexHash::BinaryIndexHash (void)
	: m_hash(BinaryIndexHashImpl_create(m_memPool.getRawPool()))
{
	if (!m_hash)
		throw std::bad_alloc();
}

BinaryIndexHash::~BinaryIndexHash (void)
{
}

deUint32* BinaryIndexHash::find (const ProgramBinary* binary) const
{
	return BinaryIndexHashImpl_find(m_hash, binary);
}

void BinaryIndexHash::insert (const ProgramBinary* binary, deUint32 index)
{
	if (!BinaryIndexHashImpl_insert(m_hash, binary, index))
		throw std::bad_alloc();
}

// BinaryRegistryWriter

BinaryRegistryWriter::BinaryRegistryWriter (const std::string& dstPath)
	: m_dstPath(dstPath)
{
	if (de::FilePath(dstPath).exists())
		initFromPath(dstPath);
}

BinaryRegistryWriter::~BinaryRegistryWriter (void)
{
	for (BinaryVector::const_iterator binaryIter = m_binaries.begin();
		 binaryIter != m_binaries.end();
		 ++binaryIter)
		delete binaryIter->binary;
}

void BinaryRegistryWriter::initFromPath (const std::string& srcPath)
{
	DE_ASSERT(m_binaries.empty());

	for (de::DirectoryIterator iter(srcPath); iter.hasItem(); iter.next())
	{
		const de::FilePath	path		= iter.getItem();
		const std::string	baseName	= path.getBaseName();

		if (isProgramFileName(baseName))
		{
			const deUint32						index	= getProgramIndexFromName(baseName);
			const de::UniquePtr<ProgramBinary>	binary	(readBinary(path.getPath()));

			addBinary(index, *binary);
			// \note referenceCount is left to 0 and will only be incremented
			//		 if binary is reused (added via addProgram()).
		}
	}
}

void BinaryRegistryWriter::addProgram (const ProgramIdentifier& id, const ProgramBinary& binary)
{
	const deUint32* const	indexPtr	= findBinary(binary);
	deUint32				index		= indexPtr ? *indexPtr : ~0u;

	if (!indexPtr)
	{
		index = getNextSlot();
		addBinary(index, binary);
	}

	m_binaries[index].referenceCount += 1;
	m_binaryIndices.push_back(ProgramIdentifierIndex(id, index));
}

deUint32* BinaryRegistryWriter::findBinary (const ProgramBinary& binary) const
{
	return m_binaryHash.find(&binary);
}

deUint32 BinaryRegistryWriter::getNextSlot (void) const
{
	const deUint32	index	= (deUint32)m_binaries.size();

	if ((size_t)index != m_binaries.size())
		throw std::bad_alloc(); // Overflow

	return index;
}

void BinaryRegistryWriter::addBinary (deUint32 index, const ProgramBinary& binary)
{
	DE_ASSERT(binary.getFormat() == vk::PROGRAM_FORMAT_SPIRV);
	DE_ASSERT(findBinary(binary) == DE_NULL);

	ProgramBinary* const	binaryClone		= new ProgramBinary(binary);

	try
	{
		if (m_binaries.size() < (size_t)index+1)
			m_binaries.resize(index+1);

		DE_ASSERT(!m_binaries[index].binary);
		DE_ASSERT(m_binaries[index].referenceCount == 0);

		m_binaries[index].binary = binaryClone;
		// \note referenceCount is not incremented here
	}
	catch (...)
	{
		delete binaryClone;
		throw;
	}

	m_binaryHash.insert(binaryClone, index);
}

void BinaryRegistryWriter::write (void) const
{
	writeToPath(m_dstPath);
}

void BinaryRegistryWriter::writeToPath (const std::string& dstPath) const
{
	if (!de::FilePath(dstPath).exists())
		de::createDirectoryAndParents(dstPath.c_str());

	DE_ASSERT(m_binaries.size() <= 0xffffffffu);
	for (size_t binaryNdx = 0; binaryNdx < m_binaries.size(); ++binaryNdx)
	{
		const BinarySlot&	slot	= m_binaries[binaryNdx];

		if (slot.referenceCount > 0)
		{
			DE_ASSERT(slot.binary);
			writeBinary(dstPath, (deUint32)binaryNdx, *slot.binary);
		}
		else
		{
			// Delete stale binary if such exists
			const std::string	progPath	= getProgramPath(dstPath, (deUint32)binaryNdx);

			if (de::FilePath(progPath).exists())
				deDeleteFile(progPath.c_str());
		}

	}

	// Write index
	{
		const de::FilePath				indexPath	= getIndexPath(dstPath);
		std::vector<BinaryIndexNode>	index;

		buildBinaryIndex(&index, m_binaryIndices.size(), !m_binaryIndices.empty() ? &m_binaryIndices[0] : DE_NULL);

		// Even in empty index there is always terminating node for the root group
		DE_ASSERT(!index.empty());

		if (!de::FilePath(indexPath.getDirName()).exists())
			de::createDirectoryAndParents(indexPath.getDirName().c_str());

		{
			std::ofstream indexOut(indexPath.getPath(), std::ios_base::binary);

			if (!indexOut.is_open() || !indexOut.good())
				throw tcu::InternalError(string("Failed to open program binary index file ") + indexPath.getPath());

			indexOut.write((const char*)&index[0], index.size()*sizeof(BinaryIndexNode));
		}
	}
}

// BinaryRegistryReader

BinaryRegistryReader::BinaryRegistryReader (const tcu::Archive& archive, const std::string& srcPath)
	: m_archive	(archive)
	, m_srcPath	(srcPath)
{
}

BinaryRegistryReader::~BinaryRegistryReader (void)
{
}

ProgramBinary* BinaryRegistryReader::loadProgram (const ProgramIdentifier& id) const
{
	if (!m_binaryIndex)
	{
		try
		{
			m_binaryIndex = BinaryIndexPtr(new BinaryIndexAccess(de::MovePtr<tcu::Resource>(m_archive.getResource(getIndexPath(m_srcPath).c_str()))));
		}
		catch (const tcu::ResourceError& e)
		{
			throw ProgramNotFoundException(id, string("Failed to open binary index (") + e.what() + ")");
		}
	}

	{
		const deUint32*	indexPos	= findBinaryIndex(m_binaryIndex.get(), id);

		if (indexPos)
		{
			const string	fullPath	= getProgramPath(m_srcPath, *indexPos);

			try
			{
				de::UniquePtr<tcu::Resource>	progRes		(m_archive.getResource(fullPath.c_str()));
				const int						progSize	= progRes->getSize();
				vector<deUint8>					bytes		(progSize);

				TCU_CHECK_INTERNAL(!bytes.empty());

				progRes->read(&bytes[0], progSize);

				return new ProgramBinary(vk::PROGRAM_FORMAT_SPIRV, bytes.size(), &bytes[0]);
			}
			catch (const tcu::ResourceError& e)
			{
				throw ProgramNotFoundException(id, e.what());
			}
		}
		else
			throw ProgramNotFoundException(id, "Program not found in index");
	}
}

} // BinaryRegistryDetail
} // vk
