import sys, os
import subprocess as sub
import itertools as itl
import fnmatch
Import('env', 'compiler', 'InstallDir', 'g_msvs_variant')

# This function is not used, but could be handy if we need to add a list
# of files of a certain type from an irregular folder structure. Newer versions
# of python have this functionality built in.  We are currently limited to 2.7

def recursive_glob(treeroot, pattern):
	results = []
	for base, dirs, files in os.walk(treeroot):
		goodfiles = fnmatch.filter(files, pattern)
		results.extend(env.File(os.path.join(base, f)) for f in goodfiles)
	return results
# 	('SoarKernel/SoarKernel.cxx',       recursive_glob(kernel_env.Dir('SoarKernel/src').abspath(), '*.cpp')),    # Kernel

def SWIGVersion(env):
	if not env.WhereIs('swig'):
		return None
	p = sub.Popen('swig -version'.split(), stdout=sub.PIPE)
	out = p.communicate()[0].decode().split()
	p.wait()

	return tuple(int(x) for x in out[2].split('.'))


def CheckSWIG(env):
	version = SWIGVersion(env)
	if version is None:
		return False

	if version >= (1, 3, 31):
		return True

	print('swig version 1.3.31 or higher is required')
	return False


kernel_env = env.Clone()

# Windows DLLs need to get linked to dependencies, whereas Linux and Mac shared objects do not
if os.name == 'nt':
	kernel_env['LIBS'] = ['advapi32']
else:
	kernel_env['LIBS'] = []

if sys.platform == 'darwin':
	install_name = os.path.join('@loader_path', env['LIBPREFIX'] + 'Soar' + env['SHLIBSUFFIX'])
	kernel_env.Append(LINKFLAGS = ['-install_name', install_name])
# Add -v verbose setting for debugging link errors.  May not generally want
# 	kernel_env.Append(LINKFLAGS = ['-v'])

if env['SCU']:
	scu = 0
else:
	scu = 1

srcs = [
	# SCU source                        NO_SCU source
	('shared/shared.cxx',               Glob('shared/*.cpp')),            		# shared
	('SoarKernel/sqlite/sqlite3.c',     ['SoarKernel/sqlite/sqlite3.c']), 		# sqlite
	('KernelSML/KernelSML.cxx',         Glob('KernelSML/src/*.cpp')),     		# KernelSML
	('ClientSML/ClientSML.cxx',         Glob('ClientSML/src/*.cpp')),     		# ClientSML
	('ConnectionSML/ConnectionSML.cxx', Glob('ConnectionSML/src/*.cpp')), 		# ConnectionSML
	('ElementXML/ElementXML.cxx',       Glob('ElementXML/src/*.cpp')),    		# ElementXML
# 	('CLI/CommandLineInterface.cxx',    Glob('CLI/src/*.cpp')),           		# CLI
]

if env['NO_SCU_KERNEL']:
	srcs.append([Glob('SoarKernel/src/*/*.cpp'),	Glob('SoarKernel/src/*/*.cpp')])
else:
	srcs.append(['SoarKernel/SoarKernel.cxx',		Glob('SoarKernel/src/*/*.cpp')])
if env['NO_SCU_CLI']:
	srcs.append([Glob('CLI/src/*.cpp'),				Glob('CLI/src/*.cpp')])
else:
	srcs.append(['CLI/CommandLineInterface.cxx',	Glob('CLI/src/*.cpp')])


# print('Soar compiler settings')
# print('CXXFlags ', kernel_env.Dump('CXXFLAGS'))
# print('CPPFLAGS ', kernel_env.Dump('CPPFLAGS'))
# print('LINKFLAGS ', kernel_env.Dump('LINKFLAGS'))
# print('LIBS ', kernel_env.Dump('LIBS'))
# print('LIBPATH ', kernel_env.Dump('LIBPATH'))
# print('CPPPATH ', kernel_env.Dump('CPPPATH'))

svs_objs = []
if not GetOption('nosvs'):
    svs_objs, svs_inc = SConscript('SVS/SConscript')
    kernel_env.Prepend(CPPPATH = svs_inc)

if GetOption('static'):
	soarlib = kernel_env.Library('Soar', [s[scu] for s in srcs] + svs_objs)
else:
	soarlib = kernel_env.SharedLibrary('Soar', [s[scu] for s in srcs] + svs_objs)[:2]
	if compiler == 'msvc':
		kernel_env.Append(CPPFLAGS = ['/D', '_USRDLL'])

Export('soarlib');

#settings_install = env.Install(env['OUT_DIR'], 'settings.soar')
#scripts_install = InstallDir(env, env['OUT_DIR'], '../scripts', '*.*')

lib_install = env.Alias('kernel', env.Install(env['OUT_DIR'], soarlib))
# settings_install = env.Alias('settings', env.Install(env['OUT_DIR'], 'settings.soar'))
#env.Install(env['OUT_DIR'], 'settings.soar')
#env.Install(env['OUT_DIR'], '../scripts')

# headers
headers = []
for d in ['ElementXML/src', 'ConnectionSML/src', 'ClientSML/src', 'shared']:
	headers.extend(InstallDir(env, env['OUT_DIR'] + '/include', env.Dir(d).srcnode().abspath, '*.h*'))
env.Alias('headers', headers)

if not CheckSWIG(env):
	print('SWIG not found. Will not define sml_* build targets. Install swig to build wrappers for other languages.')
else:
	env["SWIG_VERSION"] = SWIGVersion(env)
	for x in 'Python Java Tcl CSharp'.split():
		SConscript(os.path.join('ClientSMLSWIG', x, 'SConscript'))

if 'MSVSProject' in kernel_env['BUILDERS']:
	vcproj = kernel_env.MSVSProject(
		target = '#core' + env['MSVSPROJECTSUFFIX'],
		srcs = list(itl.chain.from_iterable([[str(f) for f in s[1]] for s in srcs])),
		buildtarget = lib_install,
		variant = g_msvs_variant,
		auto_build_solution = 0,
	)

	Import('msvs_projs')
	msvs_projs.append(vcproj)
