# -*- 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, 'rb') 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, 'rb') 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",
							useForFirstEGLConfig	= str(package.useforfirsteglconfig),
							name					= config.name,
							caseListFile			= getCaseListFileName(package, config),
							commandLine				= getCommandLine(config),
							os						= str(config.os))

	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()"

	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))

	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)
