#!/usr/bin/python

"""Generate or update SConscript files for the src and include directories of
   an IMP module.
"""

import os
import sys
import getopt
import shutil

class SConscriptGenerator:
    def __init__(self, dir, extension, prefix, suffix, excludes):
        self.dir, self.extension = dir, extension
        self.prefix, self.suffix, self.excludes = prefix, suffix, excludes
        self.script_name = "SConscript"

    def make(self):
        if not os.path.exists(self.dir):
            print "There is no %s subdirectory under the current directory." \
                  % self.dir
            print "You should run this script within an IMP main directory,"
            sys.exit(1)
        else:
            print "Generating SConscript files for %s directory" % self.dir
            self.scandir(self.dir)

    def open_file(self, dir):
        fname = os.path.join(dir, self.script_name)
        return file(fname, 'w')

    def exclude_file(self, filename):
        return filename in self.excludes or filename.startswith('.')

    def file_has_extension(self, filename, dir):
        # Special case embedded Boost headers
        if dir.endswith('boost') and self.extension == '.h':
            return filename.endswith('.hpp')
        else:
            return filename.endswith(self.extension)

    def scandir(self, dir, top=True):
        files = os.listdir(dir)
        subdirs = [x for x in files if os.path.isdir(os.path.join(dir, x)) \
                                       and x != '.svn']
        subdirs.sort()
        srcs = [x for x in files if self.file_has_extension(x, dir) \
                                    and not self.exclude_file(x)]
        srcs.sort()
    
        subdirs = [x for x in subdirs if self.scandir(os.path.join(dir, x),
                                                      top=False)]
        #if len(subdirs) + len(srcs):
        self.write_output(dir, subdirs, srcs, top)
        return len(srcs) > 0

    def write_output(self, dir, subdirs, srcs, top):
        f = self.open_file(dir)
        if top:
            print >> f, "Import('env')\n" + self.prefix
        print >> f, "files = ["
        print >> f, "\n".join([" " * 9 + "'%s'," % x for x in srcs])
        f.write("        ]")
        if top:
            if len(subdirs) > 0:
                sep = " \\\n" + " " * 8 + "+ "
                print >> f, sep.join([''] + ["SConscript('%s/SConscript')" \
                                             % x for x in subdirs])
            else:
                print >> f
            print >> f, self.suffix
        else:
            print >> f, "\n\nfiles = [File(x) for x in files]"
            print >> f, "Return('files')"

def main():
    if len(sys.argv) != 2:
        print "usage: "+sys.argv[0] + " modulename"
        sys.exit(1)
    module = sys.argv[1]
    h_excludes = ['version_info.h', 'config.h']
    cpp_excludes = ['version_info.cpp', 'link_0.cpp', 'link_1.cpp']

    if module=='kernel':
        srcpath=os.path.join('kernel', 'src')
        includepath= os.path.join('kernel', 'include')
    else:
        srcpath=os.path.join('modules', module, 'src')
        includepath=os.path.join('modules', module, 'include')
    g = SConscriptGenerator(srcpath, '.cpp', "",
                            "\n# Build and install the shared library:\n" + \
                            "env.IMPModuleLib(files)",
                            cpp_excludes)
    g.make()

    g = SConscriptGenerator(includepath, '.h', "",
                            "\n# Install the include files:\n" + \
                            "env.IMPModuleInclude(files)", h_excludes)
    g.make()


if __name__ == '__main__':
    main()