#!/usr/bin/python
# Project: Soar <http://soar.googlecode.com>
# Author: Mazin Assanie
#
# If you get an error when compiling Tcl_sml_ClientInterface_wrap.cpp, try
# deleting that file from your build directory.  There's probably a way
# to have scons detect that file should be regenerated
import sys
import os
import SCons.Script

Import('env')
clone = env.Clone()

tcl_sml_alias = clone['SML_TCL_ALIAS']

LIB_NAME = 'Tcl_sml_ClientInterface'

if clone.PrepareForCompilingWithTcl(clone["TCL_PATH"], clone["TCL_SUFFIX"]):
    print(f'{env["INDENT"]}Tcl SML library is buildable')
elif clone['TCL_REQUIRED']:
    raise ValueError('Tcl was requested by user explicitly, but Tcl is not available')
else:
    print(f'{env["INDENT"]}Tcl SML library is *not* buildable')
    Return()


# dirs
lib_install_dir = clone.Dir('$OUT_DIR')
include_dirs = [ clone.Dir(f'#Core/{d}/src').abspath for d in 'ClientSML ElementXML ConnectionSML SoarKernel'.split() ]
include_dirs.append(clone.Dir('#Core/shared').abspath)
include_dirs.append(clone.Dir('#Core/SoarKernel/src/debug').abspath)
include_dirs.append(clone.Dir('#Core/SoarKernel/src/decision_process').abspath)
include_dirs.append(clone.Dir('#Core/SoarKernel/src/episodic_memory').abspath)
include_dirs.append(clone.Dir('#Core/SoarKernel/src/explain').abspath)
include_dirs.append(clone.Dir('#Core/SoarKernel/src/explanation_based_chunking').abspath)
include_dirs.append(clone.Dir('#Core/SoarKernel/src/interface').abspath)
include_dirs.append(clone.Dir('#Core/SoarKernel/src/output_manager').abspath)
include_dirs.append(clone.Dir('#Core/SoarKernel/src/parsing').abspath)
include_dirs.append(clone.Dir('#Core/SoarKernel/src/reinforcement_learning').abspath)
include_dirs.append(clone.Dir('#Core/SoarKernel/src/semantic_memory').abspath)
include_dirs.append(clone.Dir('#Core/SoarKernel/src/shared').abspath)
include_dirs.append(clone.Dir('#Core/SoarKernel/src/soar_representation').abspath)
# files
swig_tcl_wrapper_cpp = clone.File('Tcl_sml_ClientInterface_wrap.cpp')
swig_tcl_interface = clone.File('Tcl_sml_ClientInterface.i')
makepkg_script = clone.File('SconsMakeTclSMLPackage.tcl')
pkgindex = os.path.join(lib_install_dir.abspath, 'pkgIndex.tcl')
soar_dll = clone.File(os.path.join(lib_install_dir.abspath, 'Soar'))

# Create commands to create SWIG wrapper file and pkgIndex file
includes = ' '.join(f'-I{d}' for d in include_dirs)
nosvs = ''
if GetOption('nosvs'):
  nosvs = '-DNO_SVS'
wrap_cmd = f'swig -o {swig_tcl_wrapper_cpp.abspath} -c++ -tcl -pkgversion {clone["SOAR_VERSION"]} -Wall {includes} {nosvs} {swig_tcl_interface}'


# Set up SWIGScanner to find dependencies for .i file
SWIGScanner = SCons.Scanner.ClassicCPP("SWIGScan", ".i", "CPPPATH", '^[ \t]*[%,#][ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")')
clone.Append(SCANNERS=[SWIGScanner])

# Create the SWIG wrapper cpp file
tclstep1 = clone.Command(swig_tcl_wrapper_cpp, swig_tcl_interface, wrap_cmd)

# clone.Append(CPPFLAGS = ['-w', '-DUSE_TCL_STUBS'])

if os.name == 'posix':
  clone.Append(CXXFLAGS=Split('-Wno-unused -fno-strict-aliasing'))

# Prevent "Command line warning D9025 : overriding '/W2' with '/w'"
if '/W2' in clone['CPPFLAGS']:
  clone['CPPFLAGS'].remove('/W2')

# Create the SWIG dll for tcl
tclstep2 = clone.SharedLibrary(LIB_NAME, swig_tcl_wrapper_cpp)
lib = clone.Install(lib_install_dir, tclstep2)

# Create the pkgIndex file for the SWIG dll (so tcl can find it with a package require command)
if sys.platform == 'win32':
    tcl_shname = 'tclsh86t'
    tcl_pkgindex_name = 'pkgIndex_win.tcl'
elif sys.platform == 'darwin':
    tcl_shname = 'tclsh8.6'
    tcl_pkgindex_name = 'pkgIndex_mac.tcl'
else:
    tcl_shname = 'tclsh8.6'
    tcl_pkgindex_name = 'pkgIndex_linux.tcl'
# makepkg_cmd = f'{os.path.join(tcl_bins.abspath, tcl_shname)} {makepkg_script} {lib_install_dir}'
# tclstep3 = clone.Command(pkgindex, lib, makepkg_cmd)

# Note: Disabled script that manually generated pkgindex.  Unless it's being put in a directory with
#       other files that would need to be included in the index, it should always generate the same
#       file.  Script can have issues when being built on some network drives or if it can't find
#       tclsh, so it doesn't seem to be worth the hassle.  Instead, we'll just copy a pkgindex file.
#       Users who need to regenerate can do so manually
tclstep3 = clone.InstallAs(os.path.join(lib_install_dir.abspath, 'pkgIndex.tcl'), tcl_pkgindex_name)

# Set up dependencies between steps, so SCons knows when to re-compile
clone.Depends(tclstep1, swig_tcl_interface)
clone.Depends(tclstep2, swig_tcl_wrapper_cpp)
clone.Depends(tclstep3, lib)
clone.Depends(clone.File('#Core/SoarKernel/src/shared/soar_instance.h'), swig_tcl_wrapper_cpp)
# clone.Depends(soarlib, swig_tcl_wrapper_cpp)

# Tell SCons to clean up intermediate files when doing a scons -c
clone.Clean(lib, [swig_tcl_wrapper_cpp, pkgindex])

install_test = clone.Install(lib_install_dir.abspath, clone.File('TestTclSML.tcl'))

# Set up alias to compile everything
clone.Alias(tcl_sml_alias, tclstep3 + install_test)
