#
# gen_win.py -- base class for generating windows projects
#

import os
import sys
import string

try:
  from cStringIO import StringIO
except ImportError:
  from StringIO import StringIO

import gen_base
import ezt


class WinGeneratorBase(gen_base.GeneratorBase):
  "Base class for all Windows project files generators"

  _extension_map = {
    ('exe', 'target'): '.exe',
    ('exe', 'object'): '.obj',
    ('lib', 'target'): '.dll',
    ('lib', 'object'): '.obj',
    ('script', 'target'): '',
    ('script', 'object'): '',
    }

  envvars={
    "$(SVN_APR_LIBS)": ["apr"],
    "$(SVN_APRUTIL_LIBS)": ["aprutil", "apriconv"],
    "$(NEON_LIBS)":  ["neon"],
    "$(SVN_DB_LIBS)": [],
    "$(SVN_XMLRPC_LIBS)": [],
    "$(SVN_RA_LIB_LINK)": ["libsvn_ra_dav", "libsvn_ra_local", "libsvn_ra_svn"],
  }

  def copyfile(self, dest, src):
    "Copy file to dest from src"

    open(dest, 'wb').write(open(src, 'rb').read())

  def movefile(self, dest, src):
    "Move file to dest from src if src exists"

    if os.path.exists(src):
      open(dest,'wb').write(open(src, 'rb').read())
      os.unlink(src)

  def parse_options(self, options):
    self.httpd_path = None
    self.zlib_path = None
    self.openssl_path = None
    self.skip_targets = { 'mod_dav_svn': None,
                          'mod_authz_svn': None }

    # Instrumentation options
    self.instrument_apr_pools = None
    self.instrument_purify_quantify = None

    for opt, val in options:
      if opt == '--with-httpd':
        self.httpd_path = os.path.abspath(val)
        del self.skip_targets['mod_dav_svn']
        del self.skip_targets['mod_authz_svn']
      elif opt == '--with-zlib':
        self.zlib_path = os.path.abspath(val)
      elif opt == '--with-openssl':
        self.openssl_path = os.path.abspath(val)
      elif opt == '--enable-purify':
        self.instrument_purify_quantify = 1
        self.instrument_apr_pools = 1
      elif opt == '--enable-quantify':
        self.instrument_purify_quantify = 1
      elif opt == '--enable-pool-debug':
        self.instrument_apr_pools = 1

  def __init__(self, fname, verfname, options, subdir):
    """
    Do some Windows specific setup

    Copy getdate.c from getdate.cw

    To avoid some compiler issues,
    move mod_dav_svn/log.c to mod_dav_svn/davlog.c &
    move mod_dav_svn/repos.c to mod_dav_svn/davrepos.c

    Find db-4.0.x or db-4.1.x

    Configure inno-setup
    TODO Revisit this, it may not be needed

    Build the list of Platforms & Configurations &
    create the necessary paths

    """

    # parse (and save) the options that were passed to us
    self.parse_options(options)

    #Find db-4.0.x or db-4.1.x
    #We translate all slashes to windows format later on
    db41 = self.search_for("libdb41.lib", ["db4-win32/lib"])
    if db41:
      sys.stderr.write("Found libdb41.lib in %s\n" % db41)
      self.dblibname = "libdb41"
      self.dblibpath = db41
    else:
      db40 = self.search_for("libdb40.lib", ["db4-win32/lib"])
      if db40:
        sys.stderr.write("Found libdb40.lib in %s\n" % db40)
        self.dblibname = "libdb40"
        self.dblibpath = db40
      else:
        sys.stderr.write("DB not found; assuming db-4.0.X in db4-win32 "
                         "by default\n")
        self.dblibname = "libdb40"
        self.dblibpath = os.path.join("db4-win32","lib")
    self.dbincpath = string.replace(self.dblibpath, "lib", "include")
    self.dbbindll = "%s//%s.dll" % (string.replace(self.dblibpath,
                                                   "lib", "bin"),
                                    self.dblibname)
    self.envvars["$(SVN_DB_LIBS)"] = [self.dblibname]

    # Find the right perl library name to link swig bindings with
    fp = os.popen('perl -MConfig -e ' + escape_shell_arg(
                  'print "$Config{revision}$Config{patchlevel}"'), 'r')
    try:
      num = fp.readline()
      if num:
        self.perl_lib = 'perl' + string.rstrip(num) + '.lib'
        sys.stderr.write('Found installed perl version number. Perl bindings\n'
                         '  will be linked with %s\n' % self.perl_lib)
      else:
        self.perl_lib = 'perl56.lib'
        sys.stderr.write('Could not detect perl version. Perl bindings will\n'
                         '  be linked with %s\n' % self.perl_lib)
    finally:
      fp.close()

    #Make some files for the installer so that we don't need to require sed or some other command to do it
    ### GJS: don't do this right now
    if 0:
      buf = open(os.path.join("packages","win32-innosetup","svn.iss.in"), 'rb').read()
      buf = buf.replace("@VERSION@", "0.16.1+").replace("@RELEASE@", "4365")
      buf = buf.replace("@DBBINDLL@", self.dbbindll)
      svnissrel = os.path.join("packages","win32-innosetup","svn.iss.release")
      svnissdeb = os.path.join("packages","win32-innosetup","svn.iss.debug")
      if self.write_file_if_changed(svnissrel, buf.replace("@CONFIG@", "Release")):
        print 'Wrote %s' % svnissrel
      if self.write_file_if_changed(svnissdeb, buf.replace("@CONFIG@", "Debug")):
        print 'Wrote %s' % svnissdeb

    # Generate the build_neon.bat file
    data = {'zlib_path': self.zlib_path,
            'openssl_path': self.openssl_path}
    self.write_with_template(os.path.join('build', 'win32', 'build_neon.bat'),
                             'build_neon.ezt', data)

    # gstein wrote:
    # > we don't want to munge the working copy since we might be
    # > generating the Windows build files on a Unix box prior to
    # > release. this copy already occurs in svn_config.dsp. (is that
    # > broken or something?)
    # No, but if getdate.c doesn't exist, it won't get pulled into the
    # libsvn_subr.dsp (or .vcproj or whatever), so it won't get built.
    getdate_c = os.path.join('subversion', 'libsvn_subr', 'getdate.c')
    if not os.path.exists(getdate_c):
      getdate_cw = getdate_c + 'w'
      print 'Copied', getdate_cw, 'to', getdate_c
      self.copyfile(getdate_c, getdate_cw)

    #Initialize parent
    gen_base.GeneratorBase.__init__(self, fname, verfname)

    #Make the project files directory if it doesn't exist
    #TODO win32 might not be the best path as win64 stuff will go here too
    self.projfilesdir=os.path.join("build","win32",subdir)
    if not os.path.exists(self.projfilesdir):
      os.makedirs(self.projfilesdir)

    #Here we can add additional platforms to compile for
    self.platforms = ['Win32']

    #Here we can add additional modes to compile for
    self.configs = ['Debug','Release']

    #Here we could enable shared libraries
    self.shared = 0

  def search_for(self, name, paths):
    "Search for the existence of name in paths & return the first path it was found under"
    for x in paths:
      x = string.replace(x, "/", os.sep)
      if os.path.exists(os.path.join(x, name)):
        return x

  def subst_win_env(self, s):
    "Substitute s with a value from envvars if a match was found"

    if not self.envvars.has_key(s):
      return [s]

    a=self.envvars[s]
    ret=[]
    for b in a:
      ret.append(b)
    return ret

  def map_rootpath(self, list, rootpath):
    "Return a list with rootpath prepended"

    result = [ ]
    for item in list:
      result.append(rootpath + '\\' + item)
    return result

  def make_windirs(self, list):
    "Return a list with all the current os slashes replaced with windows slashes"

    return map(lambda x:string.replace(x, os.sep, '\\'), list)

  def _find_libs(self, libs_option):
    "Override the parents _find_libs function so that environment substitution happens first"

    libs = [ ]
    for x in string.split(libs_option):
      for libname in self.subst_win_env(x):
        if self.targets.has_key(libname):
          libs.append(self.targets[libname])
        else:
          libs.append(gen_base.ExternalLibrary(libname))
    return libs

  def get_install_targets(self):
    "Generate the list of targets"
    # Generate a fake depaprutil project
    self.targets['depsubr'] = gen_base.TargetUtility('depsubr', None,
                                                     'build/win32',
                                                     None, None, self.cfg,
                                                     None)
    self.targets['depdelta'] = gen_base.TargetUtility('depdelta', None,
                                                      'build/win32',
                                                      None, None, self.cfg,
                                                      None)

    install_targets = self.targets.values() \
                      + self.graph.get_all_sources(gen_base.DT_INSTALL)
    install_targets = gen_base.unique(install_targets)

    # sort these for output stability, to watch out for regressions.
    install_targets.sort()
    return install_targets

  def get_configs(self, target, rootpath):
    "Get the list of configurations for the project"
    configs = [ ]
    for cfg in self.configs:
      configs.append(
        ProjectItem(name=cfg,
                    lower=string.lower(cfg),
                    defines=self.get_win_defines(target, cfg),
                    libdirs=self.get_win_lib_dirs(target,rootpath, cfg),
                    libs=self.get_win_libs(target, cfg),
                    ))
    return configs
  
  def get_proj_sources(self, quote_path, target, rootpath):
    "Get the list of source files for each project"
    sources = [ ]
    if not isinstance(target, gen_base.TargetUtility):
      for src, reldir in self.get_win_sources(target):
        rsrc = string.replace(os.path.join(rootpath, src), os.sep, '\\')
        if quote_path and '-' in rsrc:
          rsrc = '"%s"' % rsrc
        sources.append(ProjectItem(path=rsrc, reldir=reldir, user_deps=[],
                                   swig_language=None))

    if isinstance(target, gen_base.SWIGLibrary):
      for obj in self.graph.get_sources(gen_base.DT_LINK, target.name):
        if isinstance(obj, gen_base.SWIGObject):
          for cobj in self.graph.get_sources(gen_base.DT_OBJECT, obj):
            if isinstance(cobj, gen_base.SWIGObject):
              csrc = rootpath + '\\' + string.replace(cobj.fname, '/', '\\')

              if isinstance(target, gen_base.SWIGRuntimeLibrary):
                bsrc = rootpath + "\\build\\win32\\gen_swig_runtime.py"
                sources.append(ProjectItem(path=bsrc, reldir=None, user_deps=[],
                                           swig_language=target.lang,
                                           swig_target=csrc, swig_output=None))
                continue

              # output path passed to swig has to use forward slashes,
              # otherwise the generated python files (for shadow
              # classes) will be saved to the wrong directory
              cout = string.replace(os.path.join(rootpath, cobj.fname),
                                    os.sep, '/')
                                    
              # included header files that the generated c file depends on
              user_deps = []

              for iobj in self.graph.get_sources(gen_base.DT_SWIG_C, cobj):
                isrc = rootpath + '\\' + string.replace(str(iobj), '/', '\\')

                if not isinstance(iobj, gen_base.SWIGSource):
                  user_deps.append(isrc)
                  continue

                sources.append(ProjectItem(path=isrc, reldir=None,
                                           user_deps=user_deps,
                                           swig_language=target.lang,
                                           swig_target=csrc, swig_output=cout))
        
    sources.sort(lambda x, y: cmp(x.path, y.path))
    return sources
  
  def gen_proj_names(self, install_targets):
    "Generate project file names for the targets"
    # Generate project file names for the targets: replace dashes with
    # underscores and replace *-test with test_* (so that the test
    # programs are visually separare from the rest of the projects)
    for target in install_targets:
      name = target.name
      pos = string.find(name, '-test')
      if pos >= 0:
        proj_name = 'test_' + string.replace(name[:pos], '-', '_')
      elif isinstance(target, gen_base.SWIGLibrary):
        proj_name = 'swig_' + string.replace(name, '-', '_')
      else:
        proj_name = string.replace(name, '-', '_')
      target.proj_name = proj_name
  
  def adjust_win_depends(self, target, name):
    "Handle special dependencies if needed"
    
    # For MSVC we need to hack around Apache modules &
    # libsvn_ra because dependencies implies linking
    # and there is no way around that
    if name == '__CONFIG__':
      depends = []
    else:
      depends = [self.targets['__CONFIG__']]

    if target.is_apache_mod:
      if target.name == 'mod_authz_svn':
        depends.append(self.targets['mod_dav_svn'])
      pass
    elif name == 'depdelta':
      depends.append(self.targets['libsvn_delta'])
    elif name == 'libsvn_wc':
      depends.append(self.targets['depdelta'])
    elif name == 'depsubr':
      depends.append(self.targets['libsvn_subr'])
    elif name == 'libsvn_ra_svn':
      depends.append(self.targets['depsubr'])
    elif name == 'libsvn_ra_dav':
      depends.append(self.targets['depsubr'])
      depends.append(self.targets['neon'])
    elif isinstance(target, gen_base.Target):
      if isinstance(target, gen_base.TargetExe):
        deps = { }
        for obj in self.get_win_depends(target, 0):
          deps[obj] = None
        for obj in self.get_win_depends(target, 2):
          if isinstance(obj, gen_base.TargetLib):
            deps[obj] = None
        deps = deps.keys()
        deps.sort()
        depends.extend(deps)
      else:
        depends.extend(self.get_unique_win_depends(target))
    elif isinstance(target, gen_base.SWIGLibrary):
      for lib in self.graph.get_sources(gen_base.DT_LINK, target.name):
        if hasattr(lib, 'proj_name'):
          depends.append(lib)
          depends.extend(self.get_win_depends(lib, 0))          
      if not isinstance(target, gen_base.SWIGRuntimeLibrary):
        runtime = self.targets['swig_runtime'].get_library(target.lang)
        if runtime: depends.append(runtime)
    else:
      assert 0
      
    return depends
    
  
  def get_win_depends(self, target, recurse=0):
    """
    Return the list of dependencies for target not including external libraries
    If recurse is 0, return just target's dependencies
    If recurse is 1, return a list of dependencies plus dependencies of dependencies
    If recurse is 2, only return the dependencies of target's dependencies

    """
    deps = { }

    for obj in self.graph.get_sources(gen_base.DT_LINK, target.name):
      if not isinstance(obj, gen_base.Target):
        continue

      if recurse != 2:
        deps[obj] = None

      if recurse:
        for dep in self.get_win_depends(obj, 1):
          deps[dep] = None

    deps = deps.keys()
    deps.sort()
    return deps

  def get_unique_win_depends(self, target):
    "Return the list of dependencies for target that are not already depended upon by a child"

    deps = { }

    sub = self.get_win_depends(target, 2)
    
    for obj in self.graph.get_sources(gen_base.DT_LINK, target.name):
      if not isinstance(obj, gen_base.Target):
        continue

      if isinstance(obj, gen_base.TargetSWIG):
        tname = obj.install + '-' + gen_base.lang_abbrev[target.language]
        for dep in self.graph.get_sources(gen_base.DT_INSTALL, tname):
          deps[dep] = None
        continue

      # if the object is in 'sub', then skip it
      if obj not in sub:
        deps[obj] = None

    deps = deps.keys()
    deps.sort()
    return deps

  def get_win_defines(self, target, cfg):
    "Return the list of defines for target"

    fakedefines = ["WIN32","_WINDOWS","alloca=_alloca"]
    if target.is_apache_mod:
      if target.name == 'mod_dav_svn':
        fakedefines.extend(["AP_DECLARE_EXPORT"])
      pass
    else:
      fakedefines.extend(["APR_DECLARE_STATIC","APU_DECLARE_STATIC"])

    if isinstance(target, gen_base.SWIGLibrary):
      fakedefines.append("SWIG_GLOBAL")

    if cfg == 'Debug':
      fakedefines.extend(["_DEBUG","SVN_DEBUG"])
    elif cfg == 'Release':
      fakedefines.append("NDEBUG")
    return fakedefines

  def get_win_includes(self, target, rootpath):
    "Return the list of include directories for target"

    if target.is_apache_mod:
      fakeincludes = self.map_rootpath(["subversion/include",
                                        self.dbincpath,
                                        ""],
                                       rootpath)
      fakeincludes.extend([
        self.httpd_path + "/srclib/apr/include",
        self.httpd_path + "/srclib/apr-util/include",
        self.httpd_path + "/srclib/apr-util/xml/expat/lib",
        self.httpd_path + "/include"
        ])
    elif isinstance(target, gen_base.SWIGLibrary):
      fakeincludes = self.map_rootpath(["subversion/bindings/swig",
                                        "subversion/include",
                                        "apr/include"], rootpath)  
    else:
      fakeincludes = self.map_rootpath(["subversion/include",
                                        "apr/include",
                                        "apr-util/include",
                                        "apr-util/xml/expat/lib",
                                        "neon/src",
                                        self.dbincpath,
                                        ""],
                                       rootpath)

    return self.make_windirs(fakeincludes)

  def get_win_lib_dirs(self, target, rootpath, cfg):
    "Return the list of library directories for target"

    libcfg = string.replace(string.replace(cfg, "Debug", "LibD"),
                            "Release", "LibR")

    fakelibdirs = self.map_rootpath([self.dblibpath], rootpath)
    if target.is_apache_mod:
      fakelibdirs.extend([
        self.httpd_path + "/%s" % cfg,
        self.httpd_path + "/srclib/apr/%s" % cfg,
        self.httpd_path + "/srclib/apr-util/%s" % cfg,
        self.httpd_path + "/srclib/apr-util/xml/expat/lib/%s" % libcfg
        ])
      if target.name == 'mod_dav_svn':
        fakelibdirs.extend([self.httpd_path + "/modules/dav/main/%s" % cfg])

    return self.make_windirs(fakelibdirs)

  def get_win_libs(self, target, cfg):
    "Return the list of external libraries needed for target"

    if target.is_apache_mod:
      if target.name == 'mod_dav_svn':
        libs = [ self.dblibname+(cfg == 'Debug' and 'd.lib' or '.lib'),
                 'mod_dav.lib' ]
      else:
        libs = []
      libs.extend([ 'xml.lib',
                    'libapr.lib',
                    'libaprutil.lib',
                    'libhttpd.lib',
                    'mswsock.lib',
                    'ws2_32.lib',
                    'advapi32.lib',
                    'rpcrt4.lib',
                    'shfolder.lib' ])
      return libs

    if isinstance(target, gen_base.SWIGLibrary):
      libs = [ self.dblibname+(cfg == 'Debug' and 'd.lib' or '.lib'),
               'mswsock.lib',
               'ws2_32.lib',
               'advapi32.lib',
               'rpcrt4.lib',
               'shfolder.lib' ]
      if target.lang == 'perl':
        libs.append(self.perl_lib)
      return libs

    if not isinstance(target, gen_base.TargetExe):
      return []

    nondeplibs = ['setargv.obj']
    depends = [target] + self.get_win_depends(target, 1)
    for dep in depends:
      for lib in self.graph.get_sources(gen_base.DT_LINK, dep.name):
        if not isinstance(lib, gen_base.ExternalLibrary):
          continue

        if cfg == 'Debug' and lib.fname == self.dblibname:
          nondeplibs.append(lib.fname+'d.lib')
        else:
          nondeplibs.append(lib.fname+'.lib')

    return nondeplibs

  def get_win_sources(self, target, reldir_prefix=''):
    "Return the list of source files that need to be compliled for target"

    sources = { }

    if target.is_apache_mod:
      # get (fname, reldir) pairs for dependent libs
      for dep_tgt in self.get_win_depends(target, 1):
        if not isinstance(dep_tgt, gen_base.TargetLib):
          continue
        subdir = string.replace(dep_tgt.name, 'libsvn_', '')
        for src in self.get_win_sources(dep_tgt, subdir):
          sources[src] = None

    for obj in self.graph.get_sources(gen_base.DT_LINK, target.name):
      if isinstance(obj, gen_base.Target):
        continue

      for src in self.graph.get_sources(gen_base.DT_OBJECT, obj):
        if isinstance(src, gen_base.SourceFile):
          if reldir_prefix:
            if src.reldir:
              reldir = reldir_prefix + '\\' + src.reldir
            else:
              reldir = reldir_prefix
          else:
            reldir = src.reldir
        else:
          reldir = ''
        sources[str(src), reldir] = None

    return sources.keys()

  def write_file_if_changed(self, fname, new_contents):
    """Rewrite the file if new_contents are different than its current content.

    If you have your windows projects open and generate the projects
    it's not a small thing for windows to re-read all projects so
    only update those that have changed.
    """

    try:
      old_contents = open(fname, 'rb').read()
    except IOError:
      old_contents = None
    if old_contents != new_contents:
      open(fname, 'wb').write(new_contents)
      print "Wrote:", fname

  def write_with_template(self, fname, tname, data):
    fout = StringIO()

    template = ezt.Template(compress_whitespace = 0)
    template.parse_file(os.path.join('build', 'generator', tname))
    template.generate(fout, data)

    self.write_file_if_changed(fname, fout.getvalue())

  def write(self):
    "Override me when creating a new project type"

    raise NotImplementedError

class ProjectItem:
  "A generic item class for holding sources info, config info, etc for a project"
  def __init__(self, **kw):
    vars(self).update(kw)

if sys.platform == "win32":
  def escape_shell_arg(str):
    return '"' + string.replace(str, '"', '"^""') + '"'
else:
  def escape_shell_arg(str):
    return "'" + string.replace(str, "'", "'\\''") + "'"

