# -*- 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"):
		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

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 == "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"
	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

			elemFinal += elem

			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)
