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

#-------------------------------------------------------------------------
# drawElements Quality Program utilities
# --------------------------------------
#
# Copyright 2015 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 os
import sys
import copy
import multiprocessing

from common import which, HostInfo, DEQP_DIR

try:
	import _winreg
except:
	_winreg = None

class BuildConfig:
	def __init__ (self, buildDir, buildType, args, srcPath = DEQP_DIR):
		self.srcPath		= srcPath
		self.buildDir		= buildDir
		self.buildType		= buildType
		self.args			= copy.copy(args)
		self.cmakePath		= BuildConfig.findCMake()

	def getSrcPath (self):
		return self.srcPath

	def getBuildDir (self):
		return self.buildDir

	def getBuildType (self):
		return self.buildType

	def getArgs (self):
		return self.args

	def getCMakePath (self):
		return self.cmakePath

	@staticmethod
	def findCMake ():
		if which("cmake") == None:
			possiblePaths = [
				"/Applications/CMake.app/Contents/bin/cmake"
			]
			for path in possiblePaths:
				if os.path.exists(path):
					return path

		# Fall back to PATH - may fail later
		return "cmake"

class CMakeGenerator:
	def __init__ (self, name, isMultiConfig = False, extraBuildArgs = []):
		self.name			= name
		self.isMultiConfig	= isMultiConfig
		self.extraBuildArgs	= copy.copy(extraBuildArgs)

	def getName (self):
		return self.name

	def getGenerateArgs (self, buildType):
		args = ['-G', self.name]
		if not self.isMultiConfig:
			args.append('-DCMAKE_BUILD_TYPE=%s' % buildType)
		return args

	def getBuildArgs (self, buildType):
		args = []
		if self.isMultiConfig:
			args += ['--config', buildType]
		if len(self.extraBuildArgs) > 0:
			args += ['--'] + self.extraBuildArgs
		return args

	def getBinaryPath (self, buildType, basePath):
		return basePath

class UnixMakefileGenerator(CMakeGenerator):
	def __init__(self):
		CMakeGenerator.__init__(self, "Unix Makefiles", extraBuildArgs = ["-j%d" % multiprocessing.cpu_count()])

	def isAvailable (self):
		return which('make') != None

class NMakeGenerator(CMakeGenerator):
	def __init__(self):
		CMakeGenerator.__init__(self, "NMake Makefiles")

	def isAvailable (self):
		return which('nmake') != None

class NinjaGenerator(CMakeGenerator):
	def __init__(self):
		CMakeGenerator.__init__(self, "Ninja")

	def isAvailable (self):
		return which('ninja') != None

class VSProjectGenerator(CMakeGenerator):
	ARCH_32BIT	= 0
	ARCH_64BIT	= 1

	def __init__(self, version, arch):
		name = "Visual Studio %d" % version
		if arch == self.ARCH_64BIT:
			name += " Win64"

		CMakeGenerator.__init__(self, name, isMultiConfig = True, extraBuildArgs = ['/m'])
		self.version		= version
		self.arch			= arch

	def getBinaryPath (self, buildType, basePath):
		return os.path.join(os.path.dirname(basePath), buildType, os.path.basename(basePath) + ".exe")

	@staticmethod
	def getNativeArch ():
		bits = HostInfo.getArchBits()

		if bits == 32:
			return VSProjectGenerator.ARCH_32BIT
		elif bits == 64:
			return VSProjectGenerator.ARCH_64BIT
		else:
			raise Exception("Unhandled bits '%s'" % bits)

	@staticmethod
	def registryKeyAvailable (root, arch, name):
		try:
			key = _winreg.OpenKey(root, name, 0, _winreg.KEY_READ | arch)
			_winreg.CloseKey(key)
			return True
		except:
			return False

	def isAvailable (self):
		if sys.platform == 'win32' and _winreg != None:
			nativeArch = VSProjectGenerator.getNativeArch()
			if nativeArch == self.ARCH_32BIT and self.arch == self.ARCH_64BIT:
				return False

			arch = _winreg.KEY_WOW64_32KEY if nativeArch == self.ARCH_64BIT else 0
			keyMap = {
				10:		[(_winreg.HKEY_CLASSES_ROOT, "VisualStudio.DTE.10.0"), (_winreg.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\VCExpress\\10.0")],
				11:		[(_winreg.HKEY_CLASSES_ROOT, "VisualStudio.DTE.11.0"), (_winreg.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\VCExpress\\11.0")],
				12:		[(_winreg.HKEY_CLASSES_ROOT, "VisualStudio.DTE.12.0"), (_winreg.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\VCExpress\\12.0")],
				14:		[(_winreg.HKEY_CLASSES_ROOT, "VisualStudio.DTE.14.0"), (_winreg.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\VCExpress\\14.0")],
				15:		[(_winreg.HKEY_CLASSES_ROOT, "VisualStudio.DTE.15.0"), (_winreg.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\VCExpress\\15.0")]
			}

			if not self.version in keyMap:
				raise Exception("Unsupported VS version %d" % self.version)

			keys = keyMap[self.version]
			for root, name in keys:
				if VSProjectGenerator.registryKeyAvailable(root, arch, name):
					return True
			return False
		else:
			return False

# Pre-defined generators

MAKEFILE_GENERATOR		= UnixMakefileGenerator()
NMAKE_GENERATOR			= NMakeGenerator()
NINJA_GENERATOR			= NinjaGenerator()
VS2010_X32_GENERATOR	= VSProjectGenerator(10, VSProjectGenerator.ARCH_32BIT)
VS2010_X64_GENERATOR	= VSProjectGenerator(10, VSProjectGenerator.ARCH_64BIT)
VS2012_X32_GENERATOR	= VSProjectGenerator(11, VSProjectGenerator.ARCH_32BIT)
VS2012_X64_GENERATOR	= VSProjectGenerator(11, VSProjectGenerator.ARCH_64BIT)
VS2013_X32_GENERATOR	= VSProjectGenerator(12, VSProjectGenerator.ARCH_32BIT)
VS2013_X64_GENERATOR	= VSProjectGenerator(12, VSProjectGenerator.ARCH_64BIT)
VS2015_X32_GENERATOR	= VSProjectGenerator(14, VSProjectGenerator.ARCH_32BIT)
VS2015_X64_GENERATOR	= VSProjectGenerator(14, VSProjectGenerator.ARCH_64BIT)
VS2017_X32_GENERATOR	= VSProjectGenerator(15, VSProjectGenerator.ARCH_32BIT)
VS2017_X64_GENERATOR	= VSProjectGenerator(15, VSProjectGenerator.ARCH_64BIT)

def selectFirstAvailableGenerator (generators):
	for generator in generators:
		if generator.isAvailable():
			return generator
	return None

ANY_VS_X32_GENERATOR	= selectFirstAvailableGenerator([
								VS2017_X32_GENERATOR,
								VS2015_X32_GENERATOR,
								VS2013_X32_GENERATOR,
								VS2012_X32_GENERATOR,
								VS2010_X32_GENERATOR,
							])
ANY_VS_X64_GENERATOR	= selectFirstAvailableGenerator([
								VS2017_X64_GENERATOR,
								VS2015_X64_GENERATOR,
								VS2013_X64_GENERATOR,
								VS2012_X64_GENERATOR,
								VS2010_X64_GENERATOR,
							])
ANY_UNIX_GENERATOR		= selectFirstAvailableGenerator([
								NINJA_GENERATOR,
								MAKEFILE_GENERATOR,
								NMAKE_GENERATOR,
							])
ANY_GENERATOR			= selectFirstAvailableGenerator([
								VS2017_X64_GENERATOR,
								VS2017_X32_GENERATOR,
								VS2015_X64_GENERATOR,
								VS2015_X32_GENERATOR,
								VS2013_X64_GENERATOR,
								VS2012_X64_GENERATOR,
								VS2010_X64_GENERATOR,
								VS2013_X32_GENERATOR,
								VS2012_X32_GENERATOR,
								VS2010_X32_GENERATOR,
								NINJA_GENERATOR,
								MAKEFILE_GENERATOR,
								NMAKE_GENERATOR,
							])
