import os
import sys

from distutils.core import setup
from distutils.extension import Extension
from Pyrex.Distutils import build_ext
import Pyrex.Compiler.Main
from distutils.dep_util import newer

def replace_suffix(path, new_suffix):
  return os.path.splitext(path)[0] + new_suffix

def find_includes(filename):
  includes = []

  for line in open(filename).readlines():
    if line.startswith('include "'):
      includes.append( line.split('"')[1] )

  # XXX should recursivly scan files?
    
  return includes
      
class pyrex_build_ext(build_ext):
  def swig_sources (self, sources, ext=None):
    if not self.extensions:
      return

    # collect the names of the source (.pyx) files
    pyx_sources = []
    pyx_sources = [source for source in sources if source.endswith('.pyx')]
    other_sources = [source for source in sources if not source.endswith('.pyx')]
    deps = [source for source in ext.depends if source.endswith('.pxd') or source.endswith('.pyx')]

    extension = self.swig_cpp and '.cpp' or '.c'
    for pyx in pyx_sources:
      # should I raise an exception if it doesn't exist?
      if os.path.exists(pyx):
        print "pyrex'ing %s..." % pyx
        source = pyx

        target = replace_suffix(source, extension)

        pxd = replace_suffix(source, '.pxd')          

        if os.path.exists(pxd):
          includes = find_includes(pxd)

        compile = False
       
        if self.force:
          print "forcing compile"
          compile = True
        elif newer(source, target):
          print "%s is newer than %s" % (source, target)
          compile = True 
        else:
          for file in deps:
            if newer(file, target):
              print "include %s is newer than %s" % (file, target)
              compile = True
              break

        if compile:
          if self.pyrex_compile(source) != 0:
            print "errors compiling %s. aborting and removing %s" % (source, target)
            os.unlink(target)
            sys.exit(1)

          if self.swig_cpp:
            # rename .c to .cpp (Pyrex always builds .c ...)
            if os.path.exists(target):
              os.unlink(target)
            #os.rename(source.replace('.pyx', '.c'), target)
            os.rename(replace_suffix(source, '.c'), target)
            # massage the cpp file
            self.c_to_cpp(target)
        else:
          print "not compiling"

    return [replace_suffix(src, extension) for src in pyx_sources] + other_sources

  def pyrex_compile(self, source):
    result = Pyrex.Compiler.Main.compile(source)
    return result.num_errors

class PyrexExtension(Extension):
  def __init__(self, name, sources, **kwargs):
    pyx = sources[0]
    pxd = replace_suffix(pyx, '.pxd')
    includes = find_includes(pyx) + find_includes(pxd)

    try:
      kwargs['depends'] += includes
    except KeyError:
      kwargs['depends'] = includes

    Extension.__init__(self, name, sources, **kwargs)

