# Copyright 2010 Google Inc.
# All Rights Reserved.
#
# Author: Tim Haloun (thaloun@google.com)
#         Daniel Petersson (dape@google.com)
#
import os
import SCons.Util

class LibraryInfo:
  """Records information on the libraries defined in a build configuration.

  Attributes:
    lib_targets: Dictionary of library target params for lookups in
        ExtendComponent().
    prebuilt_libraries: Set of all prebuilt static libraries.
    system_libraries: Set of libraries not found in the above (used to detect
        out-of-order build rules).
  """

  # Dictionary of LibraryInfo objects keyed by BUILD_TYPE value.
  __library_info = {}

  @staticmethod
  def get(env):
    """Gets the LibraryInfo object for the current build type.

    Args:
      env: The environment object.

    Returns:
      The LibraryInfo object.
    """
    return LibraryInfo.__library_info.setdefault(env['BUILD_TYPE'],
                                                 LibraryInfo())

  def __init__(self):
    self.lib_targets = {}
    self.prebuilt_libraries = set()
    self.system_libraries = set()


def _GetLibParams(env, lib):
  """Gets the params for the given library if it is a library target.

  Returns the params that were specified when the given lib target name was
  created, or None if no such lib target has been defined. In the None case, it
  additionally records the negative result so as to detect out-of-order
  dependencies for future targets.

  Args:
    env: The environment object.
    lib: The library's name as a string.

  Returns:
    Its dictionary of params, or None.
  """
  info = LibraryInfo.get(env)
  if lib in info.lib_targets:
    return info.lib_targets[lib]
  else:
    if lib not in info.prebuilt_libraries and lib not in info.system_libraries:
      info.system_libraries.add(lib)
    return None


def _RecordLibParams(env, lib, params):
  """Record the params used for a library target.

  Record the params used for a library target while checking for several error
  conditions.

  Args:
    env: The environment object.
    lib: The library target's name as a string.
    params: Its dictionary of params.

  Raises:
    Exception: The lib target has already been recorded, or the lib was
        previously declared to be prebuilt, or the lib target is being defined
        after a reverse library dependency.
  """
  info = LibraryInfo.get(env)
  if lib in info.lib_targets:
    raise Exception('Multiple definitions of ' + lib)
  if lib in info.prebuilt_libraries:
    raise Exception(lib + ' already declared as a prebuilt library')
  if lib in info.system_libraries:
    raise Exception(lib + ' cannot be defined after its reverse library '
                    'dependencies')
  info.lib_targets[lib] = params


def _IsPrebuiltLibrary(env, lib):
  """Checks whether or not the given library is a prebuilt static library.

  Returns whether or not the given library name has been declared to be a
  prebuilt static library. In the False case, it additionally records the
  negative result so as to detect out-of-order dependencies for future targets.

  Args:
    env: The environment object.
    lib: The library's name as a string.

  Returns:
    True or False
  """
  info = LibraryInfo.get(env)
  if lib in info.prebuilt_libraries:
    return True
  else:
    if lib not in info.lib_targets and lib not in info.system_libraries:
      info.system_libraries.add(lib)
    return False


def _RecordPrebuiltLibrary(env, lib):
  """Record that a library is a prebuilt static library.

  Record that the given library name refers to a prebuilt static library while
  checking for several error conditions.

  Args:
    env: The environment object.
    lib: The library's name as a string.

  Raises:
    Exception: The lib has already been recorded to be prebuilt, or the lib was
        previously declared as a target, or the lib is being declared as
        prebuilt after a reverse library dependency.
  """
  info = LibraryInfo.get(env)
  if lib in info.prebuilt_libraries:
    raise Exception('Multiple prebuilt declarations of ' + lib)
  if lib in info.lib_targets:
    raise Exception(lib + ' already defined as a target')
  if lib in info.system_libraries:
    raise Exception(lib + ' cannot be declared as prebuilt after its reverse '
                    'library dependencies')
  info.prebuilt_libraries.add(lib)


def _GenericLibrary(env, static, **kwargs):
  """Extends ComponentLibrary to support multiplatform builds
     of dynamic or static libraries.

  Args:
    env: The environment object.
    kwargs: The keyword arguments.

  Returns:
    See swtoolkit ComponentLibrary
  """
  params = CombineDicts(kwargs, {'COMPONENT_STATIC': static})
  return ExtendComponent(env, 'ComponentLibrary', **params)


def DeclarePrebuiltLibraries(env, libraries):
  """Informs the build engine about external static libraries.

  Informs the build engine that the given external library name(s) are prebuilt
  static libraries, as opposed to shared libraries.

  Args:
    env: The environment object.
    libraries: The library or libraries that are being declared as prebuilt
        static libraries.
  """
  if not SCons.Util.is_List(libraries):
    libraries = [libraries]
  for library in libraries:
    _RecordPrebuiltLibrary(env, library)


def Library(env, **kwargs):
  """Extends ComponentLibrary to support multiplatform builds of static
     libraries.

  Args:
    env: The current environment.
    kwargs: The keyword arguments.

  Returns:
    See swtoolkit ComponentLibrary
  """
  return _GenericLibrary(env, True, **kwargs)


def DynamicLibrary(env, **kwargs):
  """Extends ComponentLibrary to support multiplatform builds
     of dynmic libraries.

  Args:
    env: The environment object.
    kwargs: The keyword arguments.

  Returns:
    See swtoolkit ComponentLibrary
  """
  return _GenericLibrary(env, False, **kwargs)


def Object(env, **kwargs):
  return ExtendComponent(env, 'ComponentObject', **kwargs)


def Unittest(env, **kwargs):
  """Extends ComponentTestProgram to support unittest built
     for multiple platforms.

  Args:
    env: The current environment.
    kwargs: The keyword arguments.

  Returns:
    See swtoolkit ComponentProgram.
  """
  kwargs['name'] = kwargs['name'] + '_unittest'

  common_test_params = {
    'posix_cppdefines': ['GUNIT_NO_GOOGLE3', 'GTEST_HAS_RTTI=0'],
    'libs': ['unittest_main', 'gunit']
  }
  if 'explicit_libs' not in kwargs:
    common_test_params['win_libs'] = [
      'advapi32',
      'crypt32',
      'iphlpapi',
      'secur32',
      'shell32',
      'shlwapi',
      'user32',
      'wininet',
      'ws2_32'
    ]
    common_test_params['lin_libs'] = [
      'crypto',
      'pthread',
      'ssl',
    ]

  params = CombineDicts(kwargs, common_test_params)
  return ExtendComponent(env, 'ComponentTestProgram', **params)


def App(env, **kwargs):
  """Extends ComponentProgram to support executables with platform specific
     options.

  Args:
    env: The current environment.
    kwargs: The keyword arguments.

  Returns:
    See swtoolkit ComponentProgram.
  """
  if 'explicit_libs' not in kwargs:
    common_app_params = {
      'win_libs': [
        'advapi32',
        'crypt32',
        'iphlpapi',
        'secur32',
        'shell32',
        'shlwapi',
        'user32',
        'wininet',
        'ws2_32'
      ]}
    params = CombineDicts(kwargs, common_app_params)
  else:
    params = kwargs
  return ExtendComponent(env, 'ComponentProgram', **params)

def WiX(env, **kwargs):
  """ Extends the WiX builder
  Args:
    env: The current environment.
    kwargs: The keyword arguments.

  Returns:
    The node produced by the environment's wix builder
  """
  return ExtendComponent(env, 'WiX', **kwargs)

def Repository(env, at, path):
  """Maps a directory external to $MAIN_DIR to the given path so that sources
     compiled from it end up in the correct place under $OBJ_DIR.  NOT required
     when only referring to header files.

  Args:
    env: The current environment object.
    at: The 'mount point' within the current directory.
    path: Path to the actual directory.
  """
  env.Dir(at).addRepository(env.Dir(path))


def Components(*paths):
  """Completes the directory paths with the correct file
     names such that the directory/directory.scons name
     convention can be used.

  Args:
    paths: The paths to complete. If it refers to an existing
           file then it is ignored.

  Returns:
    The completed lif scons files that are needed to build talk.
  """
  files = []
  for path in paths:
    if os.path.isfile(path):
      files.append(path)
    else:
      files.append(ExpandSconsPath(path))
  return files


def ExpandSconsPath(path):
  """Expands a directory path into the path to the
     scons file that our build uses.
     Ex: magiflute/plugin/common => magicflute/plugin/common/common.scons

  Args:
    path: The directory path to expand.

  Returns:
    The expanded path.
  """
  return '%s/%s.scons' % (path, os.path.basename(path))


def ReadVersion(filename):
  """Executes the supplied file and pulls out a version definition from it. """
  defs = {}
  execfile(str(filename), defs)
  if 'version' not in defs:
    return '0.0.0.0'
  version = defs['version']
  parts = version.split(',')
  build = os.environ.get('GOOGLE_VERSION_BUILDNUMBER')
  if build:
    parts[-1] = str(build)
  return '.'.join(parts)


#-------------------------------------------------------------------------------
# Helper methods for translating talk.Foo() declarations in to manipulations of
# environmuent construction variables, including parameter parsing and merging,
#
def PopEntry(dictionary, key):
  """Get the value from a dictionary by key. If the key
     isn't in the dictionary then None is returned. If it is in
     the dictionary the value is fetched and then is it removed
     from the dictionary.

  Args:
    dictionary: The dictionary.
    key: The key to get the value for.
  Returns:
    The value or None if the key is missing.
  """
  value = None
  if key in dictionary:
    value = dictionary[key]
    dictionary.pop(key)
  return value


def MergeAndFilterByPlatform(env, params):
  """Take a dictionary of arguments to lists of values, and, depending on
     which platform we are targetting, merge the lists of associated keys.
     Merge by combining value lists like so:
       {win_foo = [a,b], lin_foo = [c,d], foo = [e], mac_bar = [f], bar = [g] }
       becomes {foo = [a,b,e], bar = [g]} on windows, and
       {foo = [e], bar = [f,g]} on mac

  Args:
    env: The hammer environment which knows which platforms are active
    params: The keyword argument dictionary.
  Returns:
    A new dictionary with the filtered and combined entries of params
  """
  platforms = {
    'linux': 'lin_',
    'mac': 'mac_',
    'posix': 'posix_',
    'windows': 'win_',
  }
  active_prefixes = [
    platforms[x] for x in iter(platforms) if env.Bit(x)
  ]
  inactive_prefixes = [
    platforms[x] for x in iter(platforms) if not env.Bit(x)
  ]

  merged = {}
  for arg, values in params.iteritems():
    inactive_platform = False

    key = arg

    for prefix in active_prefixes:
      if arg.startswith(prefix):
        key = arg[len(prefix):]

    for prefix in inactive_prefixes:
      if arg.startswith(prefix):
        inactive_platform = True

    if inactive_platform:
      continue

    AddToDict(merged, key, values)

  return merged


def MergeSettingsFromLibraryDependencies(env, params):
  if 'libs' in params:
    for lib in params['libs']:
      libparams = _GetLibParams(env, lib)
      if libparams:
        if 'dependent_target_settings' in libparams:
          params = CombineDicts(
              params,
              MergeAndFilterByPlatform(
                  env,
                  libparams['dependent_target_settings']))
  return params


def ExtendComponent(env, component, **kwargs):
  """A wrapper around a scons builder function that preprocesses and post-
     processes its inputs and outputs.  For example, it merges and filters
     certain keyword arguments before appending them to the environments
     construction variables.  It can build signed targets and 64bit copies
     of targets as well.

  Args:
    env: The hammer environment with which to build the target
    component: The environment's builder function, e.g. ComponentProgram
    kwargs: keyword arguments that are either merged, translated, and passed on
            to the call to component, or which control execution.
            TODO(): Document the fields, such as cppdefines->CPPDEFINES,
            prepend_includedirs, include_talk_media_libs, etc.
  Returns:
    The output node returned by the call to component, or a subsequent signed
    dependant node.
  """
  env = env.Clone()

  # prune parameters intended for other platforms, then merge
  params = MergeAndFilterByPlatform(env, kwargs)

  # get the 'target' field
  name = PopEntry(params, 'name')

  # get the 'packages' field and process it if present (only used for Linux).
  packages = PopEntry(params, 'packages')
  if packages and len(packages):
    params = CombineDicts(params, env.GetPackageParams(packages))

  # save pristine params of lib targets for future reference
  if 'ComponentLibrary' == component:
    _RecordLibParams(env, name, dict(params))

  # add any dependent target settings from library dependencies
  params = MergeSettingsFromLibraryDependencies(env, params)

  # if this is a signed binary we need to make an unsigned version first
  signed = env.Bit('windows') and PopEntry(params, 'signed')
  if signed:
    name = 'unsigned_' + name

  # potentially exit now
  srcs = PopEntry(params, 'srcs')
  if not srcs or not hasattr(env, component):
    return None

  # apply any explicit dependencies
  dependencies = PopEntry(params, 'depends')
  if dependencies is not None:
    env.Depends(name, dependencies)

  # put the contents of params into the environment
  # some entries are renamed then appended, others renamed then prepended
  appends = {
    'cppdefines' : 'CPPDEFINES',
    'libdirs' : 'LIBPATH',
    'link_flags' : 'LINKFLAGS',
    'libs' : 'LIBS',
    'FRAMEWORKS' : 'FRAMEWORKS',
  }
  prepends = {}
  if env.Bit('windows'):
    # MSVC compile flags have precedence at the beginning ...
    prepends['ccflags'] = 'CCFLAGS'
  else:
    # ... while GCC compile flags have precedence at the end
    appends['ccflags'] = 'CCFLAGS'
  if PopEntry(params, 'prepend_includedirs'):
    prepends['includedirs'] = 'CPPPATH'
  else:
    appends['includedirs'] = 'CPPPATH'

  for field, var in appends.items():
    values = PopEntry(params, field)
    if values is not None:
      env.Append(**{var : values})
  for field, var in prepends.items():
    values = PopEntry(params, field)
    if values is not None:
      env.Prepend(**{var : values})

  # any other parameters are replaced without renaming
  for field, value in params.items():
    env.Replace(**{field : value})

  if env.Bit('linux') and 'LIBS' in env:
    libs = env['LIBS']
    # When using --as-needed + --start/end-group, shared libraries need to come
    # after --end-group on the command-line because the pruning decision only
    # considers the preceding modules and --start/end-group may cause the
    # effective position of early static libraries on the command-line to be
    # deferred to the point of --end-group. To effect this, we move shared libs
    # into _LIBFLAGS, which has the --end-group as its first entry. SCons does
    # not track dependencies on system shared libraries anyway so we lose
    # nothing by removing them from LIBS.
    static_libs = [lib for lib in libs if
                   _GetLibParams(env, lib) or _IsPrebuiltLibrary(env, lib)]
    shared_libs = ['-l' + lib for lib in libs if not
                   (_GetLibParams(env, lib) or _IsPrebuiltLibrary(env, lib))]
    env.Replace(LIBS=static_libs)
    env.Append(_LIBFLAGS=shared_libs)

  # invoke the builder function
  builder = getattr(env, component)

  node = builder(name, srcs)

  if signed:
    # Get the name of the built binary, then get the name of the final signed
    # version from it.  We need the output path since we don't know the file
    # extension beforehand.
    target = node[0].path.split('_', 1)[1]
    # postsignprefix: If defined, postsignprefix is a string that should be
    # prepended to the target executable.  This is to provide a work around
    # for EXEs and DLLs with the same name, which thus have PDBs with the
    # same name.  Setting postsignprefix allows the EXE and its PDB
    # to be renamed and copied in a previous step; then the desired
    # name of the EXE (but not PDB) is reconstructed after signing.
    postsignprefix = PopEntry(params, 'postsignprefix')
    if postsignprefix is not None:
        target = postsignprefix + target
    signed_node = env.SignedBinary(
      source = node,
      target = '$STAGING_DIR/' + target,
    )
    env.Alias('signed_binaries', signed_node)
    return signed_node

  return node


def AddToDict(dictionary, key, values, append=True):
  """Merge the given key value(s) pair into a dictionary.  If it contains an
     entry with that key already, then combine by appending or prepending the
     values as directed.  Otherwise, assign a new keyvalue pair.
  """
  if values is None:
    return

  if key not in dictionary:
    dictionary[key] = values
    return

  cur = dictionary[key]
  # TODO: Make sure that there are no duplicates
  # in the list. I can't use python set for this since
  # the nodes that are returned by the SCONS builders
  # are not hashable.
  # dictionary[key] = list(set(cur).union(set(values)))
  if append:
    dictionary[key] = cur + values
  else:
    dictionary[key] = values + cur


def CombineDicts(a, b):
  """Unions two dictionaries of arrays/dictionaries.

  Unions two dictionaries of arrays/dictionaries by combining the values of keys
  shared between them. The original dictionaries should not be used again after
  this call.

  Args:
    a: First dict.
    b: Second dict.

  Returns:
    The union of a and b.
  """
  c = {}
  for key in a:
    if key in b:
      aval = a[key]
      bval = b.pop(key)
      if isinstance(aval, dict) and isinstance(bval, dict):
        c[key] = CombineDicts(aval, bval)
      else:
        c[key] = aval + bval
    else:
      c[key] = a[key]

  for key in b:
    c[key] = b[key]

  return c


def RenameKey(d, old, new, append=True):
  AddToDict(d, new, PopEntry(d, old), append)
