/*-------------------------------------------------------------------------
 * 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 Test log compare utility.
 *//*--------------------------------------------------------------------*/

#include "xeTestLogParser.hpp"
#include "xeTestResultParser.hpp"
#include "deFilePath.hpp"
#include "deString.h"
#include "deThread.hpp"
#include "deCommandLine.hpp"

#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <set>
#include <map>

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

enum OutputMode
{
	OUTPUTMODE_ALL = 0,
	OUTPUTMODE_DIFF,

	OUTPUTMODE_LAST
};

enum OutputFormat
{
	OUTPUTFORMAT_TEXT = 0,
	OUTPUTFORMAT_CSV,

	OUTPUTFORMAT_LAST
};

enum OutputValue
{
	OUTPUTVALUE_STATUS_CODE = 0,
	OUTPUTVALUE_STATUS_DETAILS,

	OUTPUTVALUE_LAST
};

namespace opt
{

DE_DECLARE_COMMAND_LINE_OPT(OutMode,	OutputMode);
DE_DECLARE_COMMAND_LINE_OPT(OutFormat,	OutputFormat);
DE_DECLARE_COMMAND_LINE_OPT(OutValue,	OutputValue);

static void registerOptions (de::cmdline::Parser& parser)
{
	using de::cmdline::Option;
	using de::cmdline::NamedValue;

	static const NamedValue<OutputMode> s_outputModes[] =
	{
		{ "all",	OUTPUTMODE_ALL	},
		{ "diff",	OUTPUTMODE_DIFF	}
	};
	static const NamedValue<OutputFormat> s_outputFormats[] =
	{
		{ "text",	OUTPUTFORMAT_TEXT	},
		{ "csv",	OUTPUTFORMAT_CSV	}
	};
	static const NamedValue<OutputValue> s_outputValues[] =
	{
		{ "code",		OUTPUTVALUE_STATUS_CODE		},
		{ "details",	OUTPUTVALUE_STATUS_DETAILS	}
	};

	parser << Option<OutFormat>		("f",	"format",		"Output format",	s_outputFormats,	"csv")
		   << Option<OutMode>		("m",	"mode",			"Output mode",		s_outputModes,		"all")
		   << Option<OutValue>		("v",	"value",		"Value to extract",	s_outputValues,		"code");
}

} // opt

struct CommandLine
{
	CommandLine (void)
		: outMode	(OUTPUTMODE_ALL)
		, outFormat	(OUTPUTFORMAT_CSV)
		, outValue	(OUTPUTVALUE_STATUS_CODE)
	{
	}

	OutputMode			outMode;
	OutputFormat		outFormat;
	OutputValue			outValue;
	vector<string>		filenames;
};

struct ShortBatchResult
{
	vector<xe::TestCaseResultHeader>	resultHeaders;
	map<string, int>					resultMap;
};

class ShortResultHandler : public xe::TestLogHandler
{
public:
	ShortResultHandler (ShortBatchResult& result)
		: m_result(result)
	{
	}

	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)
	{
		xe::TestCaseResultHeader	header;
		int							caseNdx	= (int)m_result.resultHeaders.size();

		header.casePath			= caseData->getTestCasePath();
		header.caseType			= xe::TESTCASETYPE_SELF_VALIDATE;
		header.statusCode		= caseData->getStatusCode();
		header.statusDetails	= caseData->getStatusDetails();

		if (header.statusCode == xe::TESTSTATUSCODE_LAST)
		{
			xe::TestCaseResult fullResult;

			xe::parseTestCaseResultFromData(&m_testResultParser, &fullResult, *caseData.get());

			header = xe::TestCaseResultHeader(fullResult);
		}

		// Insert into result list & map.
		m_result.resultHeaders.push_back(header);
		m_result.resultMap[header.casePath] = caseNdx;
	}

private:
	ShortBatchResult&		m_result;
	xe::TestResultParser	m_testResultParser;
};

static void readLogFile (ShortBatchResult& batchResult, const char* filename)
{
	std::ifstream		in				(filename, std::ifstream::binary|std::ifstream::in);
	ShortResultHandler	resultHandler	(batchResult);
	xe::TestLogParser	parser			(&resultHandler);
	deUint8				buf				[1024];
	int					numRead			= 0;

	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();
}

class LogFileReader : public de::Thread
{
public:
	LogFileReader (ShortBatchResult& batchResult, const char* filename)
		: m_batchResult	(batchResult)
		, m_filename	(filename)
	{
	}

	void run (void)
	{
		readLogFile(m_batchResult, m_filename.c_str());
	}

private:
	ShortBatchResult&	m_batchResult;
	std::string			m_filename;
};

static void computeCaseList (vector<string>& cases, const vector<ShortBatchResult>& batchResults)
{
	// \todo [2012-07-10 pyry] Do proper case ordering (eg. handle missing cases nicely).
	set<string> addedCases;

	for (vector<ShortBatchResult>::const_iterator batchIter = batchResults.begin(); batchIter != batchResults.end(); batchIter++)
	{
		for (vector<xe::TestCaseResultHeader>::const_iterator caseIter = batchIter->resultHeaders.begin(); caseIter != batchIter->resultHeaders.end(); caseIter++)
		{
			if (addedCases.find(caseIter->casePath) == addedCases.end())
			{
				cases.push_back(caseIter->casePath);
				addedCases.insert(caseIter->casePath);
			}
		}
	}
}

static void getTestResultHeaders (vector<xe::TestCaseResultHeader>& headers, const vector<ShortBatchResult>& batchResults, const char* casePath)
{
	headers.resize(batchResults.size());

	for (int ndx = 0; ndx < (int)batchResults.size(); ndx++)
	{
		const ShortBatchResult&				batchResult	= batchResults[ndx];
		map<string, int>::const_iterator	resultPos	= batchResult.resultMap.find(casePath);

		if (resultPos != batchResult.resultMap.end())
			headers[ndx] = batchResult.resultHeaders[resultPos->second];
		else
		{
			headers[ndx].casePath	= casePath;
			headers[ndx].caseType	= xe::TESTCASETYPE_SELF_VALIDATE;
			headers[ndx].statusCode	= xe::TESTSTATUSCODE_LAST;
		}
	}
}

static const char* getStatusCodeName (xe::TestStatusCode code)
{
	if (code == xe::TESTSTATUSCODE_LAST)
		return "Missing";
	else
		return xe::getTestStatusCodeName(code);
}

static bool runCompare (const CommandLine& cmdLine, std::ostream& dst)
{
	vector<ShortBatchResult>	results;
	vector<string>				batchNames;
	bool						compareOk	= true;

	XE_CHECK(!cmdLine.filenames.empty());

	try
	{
		// Read in batch results
		results.resize(cmdLine.filenames.size());
		{
			std::vector<de::SharedPtr<LogFileReader> > readers;

			for (int ndx = 0; ndx < (int)cmdLine.filenames.size(); ndx++)
			{
				readers.push_back(de::SharedPtr<LogFileReader>(new LogFileReader(results[ndx], cmdLine.filenames[ndx].c_str())));
				readers.back()->start();
			}

			for (int ndx = 0; ndx < (int)cmdLine.filenames.size(); ndx++)
			{
				readers[ndx]->join();

				// Use file name as batch name.
				batchNames.push_back(de::FilePath(cmdLine.filenames[ndx].c_str()).getBaseName());
			}
		}

		// Compute unified case list.
		vector<string> caseList;
		computeCaseList(caseList, results);

		// Stats.
		int		numCases		= (int)caseList.size();
		int		numEqual		= 0;

		if (cmdLine.outFormat == OUTPUTFORMAT_CSV)
		{
			dst << "TestCasePath";
			for (vector<string>::const_iterator nameIter = batchNames.begin(); nameIter != batchNames.end(); nameIter++)
				dst << "," << *nameIter;
			dst << "\n";
		}

		// Compare cases.
		for (vector<string>::const_iterator caseIter = caseList.begin(); caseIter != caseList.end(); caseIter++)
		{
			const string&						caseName	= *caseIter;
			vector<xe::TestCaseResultHeader>	headers;
			bool								allEqual	= true;

			getTestResultHeaders(headers, results, caseName.c_str());

			for (vector<xe::TestCaseResultHeader>::const_iterator iter = headers.begin()+1; iter != headers.end(); iter++)
			{
				if (iter->statusCode != headers[0].statusCode)
				{
					allEqual = false;
					break;
				}
			}

			if (allEqual)
				numEqual += 1;

			if (cmdLine.outMode == OUTPUTMODE_ALL || !allEqual)
			{
				if (cmdLine.outFormat == OUTPUTFORMAT_TEXT)
				{
					dst << caseName << "\n";
					for (int ndx = 0; ndx < (int)headers.size(); ndx++)
						dst << "  " << batchNames[ndx] << ": " << getStatusCodeName(headers[ndx].statusCode) << " (" << headers[ndx].statusDetails << ")\n";
					dst << "\n";
				}
				else if (cmdLine.outFormat == OUTPUTFORMAT_CSV)
				{
					dst << caseName;
					for (vector<xe::TestCaseResultHeader>::const_iterator iter = headers.begin(); iter != headers.end(); iter++)
						dst << "," << (cmdLine.outValue == OUTPUTVALUE_STATUS_CODE ? getStatusCodeName(iter->statusCode) : iter->statusDetails.c_str());
					dst << "\n";
				}
			}
		}

		compareOk = numEqual == numCases;

		if (cmdLine.outFormat == OUTPUTFORMAT_TEXT)
		{
			dst << "  " << numEqual << " / " << numCases << " test case results match.\n";
			dst << "  Comparison " << (compareOk ? "passed" : "FAILED") << "!\n";
		}
	}
	catch (const std::exception& e)
	{
		printf("%s\n", e.what());
		compareOk = false;
	}

	return compareOk;
}

static bool parseCommandLine (CommandLine& cmdLine, int argc, const char* const* argv)
{
	de::cmdline::Parser			parser;
	de::cmdline::CommandLine	opts;

	XE_CHECK(argc >= 1);

	opt::registerOptions(parser);

	if (!parser.parse(argc-1, &argv[1], &opts, std::cerr)	||
		opts.getArgs().empty())
	{
		std::cout << argv[0] << ": [options] [filenames]\n";
		parser.help(std::cout);
		return false;
	}

	cmdLine.outFormat	= opts.getOption<opt::OutFormat>();
	cmdLine.outMode		= opts.getOption<opt::OutMode>();
	cmdLine.outValue	= opts.getOption<opt::OutValue>();
	cmdLine.filenames	= opts.getArgs();

	return true;
}

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

	if (!parseCommandLine(cmdLine, argc, argv))
		return -1;

	try
	{
		bool compareOk = runCompare(cmdLine, std::cout);
		return compareOk ? 0 : -1;
	}
	catch (const std::exception& e)
	{
		printf("FATAL ERROR: %s\n", e.what());
		return -1;
	}
}
