/*-------------------------------------------------------------------------
 * drawElements Quality Program Test Executor
 * ------------------------------------------
 *
 * 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 Extract shader programs from log.
 *//*--------------------------------------------------------------------*/

#include "xeTestLogParser.hpp"
#include "xeTestResultParser.hpp"
#include "deFilePath.hpp"
#include "deStringUtil.hpp"
#include "deString.h"

#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <stdexcept>

using std::vector;
using std::string;
using std::set;
using std::map;

struct CommandLine
{
	CommandLine (void)
	{
	}

	string		filename;
	string		dstPath;
};

static const char* getShaderTypeSuffix (const xe::ri::Shader::ShaderType shaderType)
{
	switch (shaderType)
	{
		case xe::ri::Shader::SHADERTYPE_VERTEX:				return "vert";
		case xe::ri::Shader::SHADERTYPE_FRAGMENT:			return "frag";
		case xe::ri::Shader::SHADERTYPE_GEOMETRY:			return "geom";
		case xe::ri::Shader::SHADERTYPE_TESS_CONTROL:		return "tesc";
		case xe::ri::Shader::SHADERTYPE_TESS_EVALUATION:	return "tese";
		case xe::ri::Shader::SHADERTYPE_COMPUTE:			return "comp";
		default:
			throw xe::Error("Invalid shader type");
	}
}

static void writeShaderProgram (const CommandLine& cmdLine, const std::string& casePath, const xe::ri::ShaderProgram& shaderProgram, int programNdx)
{
	const string basePath = string(de::FilePath::join(cmdLine.dstPath, casePath).getPath()) + "." + de::toString(programNdx);

	for (int shaderNdx = 0; shaderNdx < shaderProgram.shaders.getNumItems(); shaderNdx++)
	{
		const xe::ri::Shader&	shader		= dynamic_cast<const xe::ri::Shader&>(shaderProgram.shaders.getItem(shaderNdx));
		const string			shaderPath	= basePath + "." + getShaderTypeSuffix(shader.shaderType);

		if (de::FilePath(shaderPath).exists())
			throw xe::Error("File '" + shaderPath + "' exists already");

		{
			std::ofstream out(shaderPath.c_str(), std::ifstream::binary|std::ifstream::out);

			if (!out.good())
				throw xe::Error("Failed to open '" + shaderPath + "'");

			out.write(shader.source.source.c_str(), shader.source.source.size());
		}
	}
}

struct StackEntry
{
	const xe::ri::List*		list;
	int						curNdx;

	explicit StackEntry (const xe::ri::List* list_) : list(list_), curNdx(0) {}
};

static void extractShaderPrograms (const CommandLine& cmdLine, const std::string& casePath, const xe::TestCaseResult& result)
{
	vector<StackEntry>	itemListStack;
	int					programNdx		= 0;

	itemListStack.push_back(StackEntry(&result.resultItems));

	while (!itemListStack.empty())
	{
		StackEntry& curEntry = itemListStack.back();

		if (curEntry.curNdx < curEntry.list->getNumItems())
		{
			const xe::ri::Item&	curItem	= curEntry.list->getItem(curEntry.curNdx);
			curEntry.curNdx += 1;

			if (curItem.getType() == xe::ri::TYPE_SHADERPROGRAM)
			{
				writeShaderProgram(cmdLine, casePath, static_cast<const xe::ri::ShaderProgram&>(curItem), programNdx);
				programNdx += 1;
			}
			else if (curItem.getType() == xe::ri::TYPE_SECTION)
				itemListStack.push_back(StackEntry(&static_cast<const xe::ri::Section&>(curItem).items));
		}
		else
			itemListStack.pop_back();
	}

	if (programNdx == 0)
		std::cout << "WARNING: no shader programs found in '" << casePath << "'\n";
}

class ShaderProgramExtractHandler : public xe::TestLogHandler
{
public:
	ShaderProgramExtractHandler (const CommandLine& cmdLine)
		: m_cmdLine(cmdLine)
	{
	}

	void setSessionInfo (const xe::SessionInfo&)
	{
		// Ignored.
	}

	xe::TestCaseResultPtr startTestCaseResult (const char* casePath)
	{
		return xe::TestCaseResultPtr(new xe::TestCaseResultData(casePath));
	}

	void testCaseResultUpdated (const xe::TestCaseResultPtr&)
	{
		// Ignored.
	}

	void testCaseResultComplete (const xe::TestCaseResultPtr& caseData)
	{
		if (caseData->getDataSize() > 0)
		{
			xe::TestCaseResult					fullResult;
			xe::TestResultParser::ParseResult	parseResult;

			m_testResultParser.init(&fullResult);
			parseResult = m_testResultParser.parse(caseData->getData(), caseData->getDataSize());
			DE_UNREF(parseResult);

			extractShaderPrograms(m_cmdLine, caseData->getTestCasePath(), fullResult);
		}
	}

private:
	const CommandLine&		m_cmdLine;
	xe::TestResultParser	m_testResultParser;
};

static void extractShaderProgramsFromLogFile (const CommandLine& cmdLine)
{
	std::ifstream					in				(cmdLine.filename.c_str(), std::ifstream::binary|std::ifstream::in);
	ShaderProgramExtractHandler		resultHandler	(cmdLine);
	xe::TestLogParser				parser			(&resultHandler);
	deUint8							buf				[1024];
	int								numRead			= 0;

	if (!in.good())
		throw std::runtime_error(string("Failed to open '") + cmdLine.filename + "'");

	for (;;)
	{
		in.read((char*)&buf[0], DE_LENGTH_OF_ARRAY(buf));
		numRead = (int)in.gcount();

		if (numRead <= 0)
			break;

		parser.parse(&buf[0], numRead);
	}

	in.close();
}

static void printHelp (const char* binName)
{
	printf("%s: [filename] [dst path (optional)]\n", binName);
}

static bool parseCommandLine (CommandLine& cmdLine, int argc, const char* const* argv)
{
	for (int argNdx = 1; argNdx < argc; argNdx++)
	{
		const char* arg = argv[argNdx];

		if (!deStringBeginsWith(arg, "--"))
		{
			if (cmdLine.filename.empty())
				cmdLine.filename = arg;
			else if (cmdLine.dstPath.empty())
				cmdLine.dstPath = arg;
			else
				return false;
		}
		else
			return false;
	}

	if (cmdLine.filename.empty())
		return false;

	return true;
}

int main (int argc, const char* const* argv)
{
	try
	{
		CommandLine cmdLine;

		if (!parseCommandLine(cmdLine, argc, argv))
		{
			printHelp(argv[0]);
			return -1;
		}

		extractShaderProgramsFromLogFile(cmdLine);
	}
	catch (const std::exception& e)
	{
		printf("FATAL ERROR: %s\n", e.what());
		return -1;
	}

	return 0;
}
