# -*- coding: utf-8 -*-

#-------------------------------------------------------------------------
# drawElements Quality Program utilities
# --------------------------------------
#
# Copyright 2016 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.
#
#-------------------------------------------------------------------------

import sys
import os
import xml.etree.cElementTree as ElementTree
import xml.dom.minidom as minidom

from build_caselists import Module, getModuleByName, getBuildConfig, genCaseList, getCaseListPath, DEFAULT_BUILD_DIR, DEFAULT_TARGET, GLCTS_BIN_NAME

sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "..", "scripts"))

from build.common import *
from build.config import ANY_GENERATOR
from build.build import build
from fnmatch import fnmatch
from copy import copy

GENERATED_FILE_WARNING = """\
/* WARNING: This is auto-generated file. Do not modify, since changes will
 * be lost! Modify the generating script instead.
 */"""

class Project:
	def __init__ (self, name, path, incpath, devicepath, copyright = None):
		self.name		= name
		self.path		= path
		self.incpath	= incpath
		self.devicepath	= devicepath
		self.copyright	= copyright

class Configuration:
	def __init__ (self, name, filters, glconfig = None, rotation = "unspecified", surfacetype = None, surfacewidth = None, surfaceheight = None, baseseed = None, fboconfig = None, required = False, runtime = None, os = "any", skip = "none"):
		self.name				= name
		self.glconfig			= glconfig
		self.rotation			= rotation
		self.surfacetype		= surfacetype
		self.required			= required
		self.surfacewidth		= surfacewidth
		self.surfaceheight		= surfaceheight
		self.baseseed			= baseseed
		self.fboconfig			= fboconfig
		self.filters			= filters
		self.expectedRuntime	= runtime
		self.os					= os
		self.skipPlatform		= skip

class Package:
	def __init__ (self, module, configurations, useforfirsteglconfig = True):
		self.module					= module
		self.useforfirsteglconfig	= useforfirsteglconfig
		self.configurations			= configurations

class Mustpass:
	def __init__ (self, project, version, packages, isCurrent):
		self.project		= project
		self.version		= version
		self.packages		= packages
		self.isCurrent		= isCurrent

class Filter:
	TYPE_INCLUDE = 0
	TYPE_EXCLUDE = 1

	def __init__ (self, type, filename):
		self.type		= type
		self.filename	= filename

def getSrcDir (mustpass):
	return os.path.join(mustpass.project.path, mustpass.version, "src")

def getTmpDir (mustpass):
	return os.path.join(mustpass.project.path, mustpass.version, "tmp")

def getModuleShorthand (module):
	return module.api.lower()

def getCaseListFileName (package, configuration):
	return "%s-%s.txt" % (getModuleShorthand(package.module), configuration.name)

def getDstDir(mustpass):
	return os.path.join(mustpass.project.path, mustpass.version)

def getDstCaseListPath (mustpass, package, configuration):
	return os.path.join(getDstDir(mustpass), getCaseListFileName(package, configuration))

def getCommandLine (config):
	cmdLine = ""

	if config.glconfig != None:
		cmdLine += "--deqp-gl-config-name=%s " % config.glconfig

	if config.rotation != None:
		cmdLine += "--deqp-screen-rotation=%s " % config.rotation

	if config.surfacetype != None:
		cmdLine += "--deqp-surface-type=%s " % config.surfacetype

	if config.surfacewidth != None:
		cmdLine += "--deqp-surface-width=%s " % config.surfacewidth

	if config.surfaceheight != None:
		cmdLine += "--deqp-surface-height=%s " % config.surfaceheight

	if config.baseseed != None:
		cmdLine += "--deqp-base-seed=%s " % config.baseseed

	if config.fboconfig != None:
		cmdLine += "--deqp-gl-config-name=%s --deqp-surface-type=fbo " % config.fboconfig

	cmdLine += "--deqp-watchdog=disable"

	return cmdLine

def readCaseList (filename):
	cases = []
	with open(filename, 'rt') as f:
		for line in f:
			if line[:6] == "TEST: ":
				cases.append(line[6:].strip())
	return cases

def getCaseList (buildCfg, generator, module):
	return readCaseList(getCaseListPath(buildCfg, module, "txt"))

def readPatternList (filename):
	ptrns = []
	with open(filename, 'rt') as f:
		for line in f:
			line = line.strip()
			if len(line) > 0 and line[0] != '#':
				ptrns.append(line)
	return ptrns

def applyPatterns (caseList, patterns, filename, op):
	matched			= set()
	errors			= []
	curList			= copy(caseList)
	trivialPtrns	= [p for p in patterns if p.find('*') < 0]
	regularPtrns	= [p for p in patterns if p.find('*') >= 0]

	# Apply trivial (just case paths)
	allCasesSet		= set(caseList)
	for path in trivialPtrns:
		if path in allCasesSet:
			if path in matched:
				errors.append((path, "Same case specified more than once"))
			matched.add(path)
		else:
			errors.append((path, "Test case not found"))

	curList = [c for c in curList if c not in matched]

	for pattern in regularPtrns:
		matchedThisPtrn = set()

		for case in curList:
			if fnmatch(case, pattern):
				matchedThisPtrn.add(case)

		if len(matchedThisPtrn) == 0:
			errors.append((pattern, "Pattern didn't match any cases"))

		matched	= matched | matchedThisPtrn
		curList = [c for c in curList if c not in matched]

	for pattern, reason in errors:
		print("ERROR: %s: %s" % (reason, pattern))

	if len(errors) > 0:
		die("Found %s invalid patterns while processing file %s" % (len(errors), filename))

	return [c for c in caseList if op(c in matched)]

def applyInclude (caseList, patterns, filename):
	return applyPatterns(caseList, patterns, filename, lambda b: b)

def applyExclude (caseList, patterns, filename):
	return applyPatterns(caseList, patterns, filename, lambda b: not b)

def readPatternLists (mustpass):
	lists = {}
	for package in mustpass.packages:
		for cfg in package.configurations:
			for filter in cfg.filters:
				if not filter.filename in lists:
					lists[filter.filename] = readPatternList(os.path.join(getSrcDir(mustpass), filter.filename))
	return lists

def applyFilters (caseList, patternLists, filters):
	res = copy(caseList)
	for filter in filters:
		ptrnList = patternLists[filter.filename]
		if filter.type == Filter.TYPE_INCLUDE:
			res = applyInclude(res, ptrnList, filter.filename)
		else:
			assert filter.type == Filter.TYPE_EXCLUDE
			res = applyExclude(res, ptrnList, filter.filename)
	return res


def include (filename):
	return Filter(Filter.TYPE_INCLUDE, filename)

def exclude (filename):
	return Filter(Filter.TYPE_EXCLUDE, filename)

def insertXMLHeaders (mustpass, doc):
	if mustpass.project.copyright != None:
		doc.insert(0, ElementTree.Comment(mustpass.project.copyright))
	doc.insert(1, ElementTree.Comment(GENERATED_FILE_WARNING))

def prettifyXML (doc):
	uglyString	= ElementTree.tostring(doc, 'utf-8')
	reparsed	= minidom.parseString(uglyString)
	return reparsed.toprettyxml(indent='\t', encoding='utf-8')

def genSpecXML (mustpass):
	mustpassElem = ElementTree.Element("Mustpass", version = mustpass.version)
	insertXMLHeaders(mustpass, mustpassElem)

	packageElem = ElementTree.SubElement(mustpassElem, "TestPackage", name = mustpass.project.name)

	for package in mustpass.packages:
		for config in package.configurations:
			configElem = ElementTree.SubElement(packageElem, "Configuration",
							caseListFile			= getCaseListFileName(package, config),
							commandLine				= getCommandLine(config),
							name					= config.name,
							os						= str(config.os),
							useForFirstEGLConfig	= str(package.useforfirsteglconfig)
							)

	return mustpassElem

def getIncludeGuardName (headerFile):
	return '_' + os.path.basename(headerFile).upper().replace('.', '_')

def convertToCamelcase(s):
    return ''.join(w.capitalize() or '_' for w in s.split('_'))

def getApiType(apiName):
	if apiName == "GLES2":
		return "glu::ApiType::es(2, 0)"
	if apiName == "GLES3":
		return "glu::ApiType::es(3, 0)"
	if apiName == "GLES31":
		return "glu::ApiType::es(3, 1)"
	if apiName == "GLES32":
		return "glu::ApiType::es(3, 2)"
	if apiName == "GL46":
		return "glu::ApiType::core(4, 6)"
	if apiName == "GL45":
		return "glu::ApiType::core(4, 5)"
	if apiName == "GL44":
		return "glu::ApiType::core(4, 4)"
	if apiName == "GL43":
		return "glu::ApiType::core(4, 3)"
	if apiName == "GL42":
		return "glu::ApiType::core(4, 2)"
	if apiName == "GL41":
		return "glu::ApiType::core(4, 1)"
	if apiName == "GL40":
		return "glu::ApiType::core(4, 0)"
	if apiName == "GL33":
		return "glu::ApiType::core(3, 3)"
	if apiName == "GL32":
		return "glu::ApiType::core(3, 2)"
	if apiName == "GL31":
		return "glu::ApiType::core(3, 1)"
	if apiName == "GL30":
		return "glu::ApiType::core(3, 0)"
	if apiName == "EGL":
		return "glu::ApiType()"
	if apiName == "GL42-COMPAT":
		return "glu::ApiType::compatibility(4, 2)"

	raise Exception("Unknown API %s" % apiName)
	return "Unknown"

def getConfigName(cfgName):
	if cfgName == None:
		return "DE_NULL"
	else:
		return '"' + cfgName + '"'

def getIntBaseSeed(baseSeed):
	if baseSeed == None:
		return "-1"
	else:
		return baseSeed

def genSpecCPPIncludeFile (specFilename, mustpass):
	fileBody = ""

	includeGuard = getIncludeGuardName(specFilename)
	fileBody += "#ifndef %s\n" % includeGuard
	fileBody += "#define %s\n" % includeGuard
	fileBody += mustpass.project.copyright
	fileBody += "\n\n"
	fileBody += GENERATED_FILE_WARNING
	fileBody += "\n\n"
	fileBody += 'const char* mustpassDir = "' + mustpass.project.devicepath + '/' + mustpass.version + '/";\n\n'

	gtf_wrapper_open = "#if defined(DEQP_GTF_AVAILABLE)\n"
	gtf_wrapper_close = "#endif // defined(DEQP_GTF_AVAILABLE)\n"
	android_wrapper_open = "#if DE_OS == DE_OS_ANDROID\n"
	android_wrapper_close = "#endif // DE_OS == DE_OS_ANDROID\n"
	skip_x11_wrapper_open = "#ifndef DEQP_SUPPORT_X11\n"
	skip_x11_wrapper_close = "#endif // DEQP_SUPPORT_X11\n"
	TABLE_ELEM_PATTERN	= "{apiType} {configName} {glConfigName} {screenRotation} {baseSeed} {fboConfig} {surfaceWidth} {surfaceHeight}"

	emitOtherCfgTbl = False
	firstCfgDecl = "static const RunParams %s_first_cfg[] = " % mustpass.project.name.lower().replace(' ','_')
	firstCfgTbl = "{\n"

	otherCfgDecl = "static const RunParams %s_other_cfg[] = " % mustpass.project.name.lower().replace(' ','_')
	otherCfgTbl = "{\n"

	for package in mustpass.packages:
		for config in package.configurations:
			pApiType = getApiType(package.module.api) + ','
			pConfigName = '"' + config.name + '",'
			pGLConfig = getConfigName(config.glconfig) + ','
			pRotation = '"' + config.rotation + '",'
			pSeed =  getIntBaseSeed(config.baseseed) + ','
			pFBOConfig = getConfigName(config.fboconfig) + ','
			pWidth = config.surfacewidth + ','
			pHeight = config.surfaceheight
			elemFinal = ""
			elemContent = TABLE_ELEM_PATTERN.format(apiType = pApiType, configName = pConfigName, glConfigName = pGLConfig, screenRotation = pRotation, baseSeed = pSeed, fboConfig = pFBOConfig, surfaceWidth = pWidth, surfaceHeight = pHeight)
			elem = "\t{ " + elemContent + " },\n"
			if package.module.name[:3] == "GTF":
				elemFinal += gtf_wrapper_open

			if config.os == "android":
				elemFinal += android_wrapper_open

			if config.skipPlatform == "x11":
				elemFinal += skip_x11_wrapper_open

			elemFinal += elem

			if config.skipPlatform == "x11":
				elemFinal += skip_x11_wrapper_close

			if config.os == "android":
				elemFinal += android_wrapper_close

			if package.module.name[:3] == "GTF":
				elemFinal += gtf_wrapper_close

			if package.useforfirsteglconfig == True:
				firstCfgTbl += elemFinal
			else:
				otherCfgTbl += elemFinal
				emitOtherCfgTbl = True

	firstCfgTbl += "};\n"
	otherCfgTbl += "};\n"

	fileBody += firstCfgDecl
	fileBody += firstCfgTbl

	if emitOtherCfgTbl == True:
		fileBody += "\n"
		fileBody += otherCfgDecl
		fileBody += otherCfgTbl

	fileBody += "\n"
	fileBody += "#endif // %s\n" % includeGuard
	return fileBody


def genSpecCPPIncludes (mustpassLists):
	for mustpass in mustpassLists:
		if mustpass.isCurrent == True:
			specFilename	= os.path.join(mustpass.project.incpath, "glc%s.hpp" % convertToCamelcase(mustpass.project.name.lower().replace(' ','_')))
			hpp = genSpecCPPIncludeFile(specFilename, mustpass)

			print("  Writing spec: " + specFilename)
			writeFile(specFilename, hpp)
			print("Done!")

def genMustpass (mustpass, moduleCaseLists):
	print("Generating mustpass '%s'" % mustpass.version)

	patternLists = readPatternLists(mustpass)

	for package in mustpass.packages:
		allCasesInPkg	= moduleCaseLists[package.module]

		for config in package.configurations:
			filtered	= applyFilters(allCasesInPkg, patternLists, config.filters)
			dstFile		= getDstCaseListPath(mustpass, package, config)

			print("  Writing deqp caselist: " + dstFile)
			writeFile(dstFile, "\n".join(filtered) + "\n")

	specXML			= genSpecXML(mustpass)
	specFilename	= os.path.join(mustpass.project.path, mustpass.version, "mustpass.xml")

	print("  Writing spec: " + specFilename)
	writeFile(specFilename, prettifyXML(specXML).decode())

	print("Done!")

def genMustpassLists (mustpassLists, generator, buildCfg):
	moduleCaseLists = {}

	# Getting case lists involves invoking build, so we want to cache the results
	build(buildCfg, generator, [GLCTS_BIN_NAME])
	genCaseList(buildCfg, generator, "txt")
	for mustpass in mustpassLists:
		for package in mustpass.packages:
			if not package.module in moduleCaseLists:
				moduleCaseLists[package.module] = getCaseList(buildCfg, generator, package.module)

	for mustpass in mustpassLists:
		genMustpass(mustpass, moduleCaseLists)


	genSpecCPPIncludes(mustpassLists)
