import re
import SCons
from SCons.Action import Action
from SCons.Scanner import Scanner

pyx_from_import_re = re.compile(r'^from\s+(\S+)\s+cimport', re.M)
pyx_import_re = re.compile(r'^cimport\s+(\S+)', re.M)
cdef_import_re = re.compile(r'^cdef extern from\s+.(\S+).:', re.M)


def pyx_scan(node, env, path, arg=None):
  contents = node.get_text_contents()

  # from <module> cimport ...
  matches = pyx_from_import_re.findall(contents)
  # cimport <module>
  matches += pyx_import_re.findall(contents)

  # Modules can be either .pxd or .pyx files
  files = [m.replace('.', '/') + '.pxd' for m in matches]
  files += [m.replace('.', '/') + '.pyx' for m in matches]

  # cdef extern from <file>
  files += cdef_import_re.findall(contents)

  # Handle relative imports
  cur_dir = str(node.get_dir())
  files = [cur_dir + f if f.startswith('/') else f for f in files]

  # Filter out non-existing files (probably system imports)
  files = [f for f in files if env.File(f).exists()]
  return env.File(files)


pyxscanner = Scanner(function=pyx_scan, skeys=['.pyx', '.pxd'], recursive=True)
cythonAction = Action("$CYTHONCOM")


def create_builder(env):
  try:
    cython = env['BUILDERS']['Cython']
  except KeyError:
    cython = SCons.Builder.Builder(
      action=cythonAction,
      emitter={},
      suffix=cython_suffix_emitter,
      single_source=1
    )
    env.Append(SCANNERS=pyxscanner)
    env['BUILDERS']['Cython'] = cython
  return cython

def cython_suffix_emitter(env, source):
  return "$CYTHONCFILESUFFIX"

def generate(env):
  env["CYTHON"] = "cythonize"
  env["CYTHONCOM"] = "$CYTHON $CYTHONFLAGS $SOURCE"
  env["CYTHONCFILESUFFIX"] = ".cpp"

  c_file, _ = SCons.Tool.createCFileBuilders(env)

  c_file.suffix['.pyx'] = cython_suffix_emitter
  c_file.add_action('.pyx', cythonAction)

  c_file.suffix['.py'] = cython_suffix_emitter
  c_file.add_action('.py', cythonAction)

  create_builder(env)

def exists(env):
  return True