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

# Keep a global dictionary of library target params for lookups in
# ExtendComponent().
_all_lib_targets = {}

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 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 not kwargs.has_key('explicit_libs'):
    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 not kwargs.has_key('explicit_libs'):
    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 AddMediaLibs(env, **kwargs):
  lmi_libdir = '$GOOGLE3/../googleclient/third_party/lmi/files/lib/'
  if env.Bit('windows'):
    if env.get('COVERAGE_ENABLED'):
      lmi_libdir += 'win32/c_only'
    else:
      lmi_libdir += 'win32/Release'
  elif env.Bit('mac'):
    lmi_libdir += 'macos'
  elif env.Bit('linux'):
      lmi_libdir += 'linux/x86'


  AddToDict(kwargs, 'libdirs', [
    '$MAIN_DIR/third_party/gips/Libraries/',
    lmi_libdir,
  ])

  gips_lib = ''
  if env.Bit('windows'):
    if env.Bit('debug'):
      gips_lib = 'gipsvoiceenginelib_mtd'
    else:
      gips_lib = 'gipsvoiceenginelib_mt'
  elif env.Bit('mac'):
    gips_lib = 'VoiceEngine_mac_universal_gcc'
  elif env.Bit('linux'):
      gips_lib = 'VoiceEngine_Linux_gcc'


  AddToDict(kwargs, 'libs', [
    gips_lib,
    'LmiAudioCommon',
    'LmiClient',
    'LmiCmcp',
    'LmiDeviceManager',
    'LmiH263ClientPlugIn',
    'LmiH263CodecCommon',
    'LmiH263Decoder',
    'LmiH263Encoder',
    'LmiH264ClientPlugIn',
    'LmiH264CodecCommon',
    'LmiH264Common',
    'LmiH264Decoder',
    'LmiH264Encoder',
    'LmiIce',
    'LmiMediaPayload',
    'LmiOs',
    'LmiPacketCache',
    'LmiProtocolStack',
    'LmiRateShaper',
    'LmiRtp',
    'LmiSecurity',
    'LmiSignaling',
    'LmiStun',
    'LmiTransport',
    'LmiUi',
    'LmiUtils',
    'LmiVideoCommon',
    'LmiXml',
  ])

  if env.Bit('windows'):
    AddToDict(kwargs, 'libs', [
      'dsound',
      'd3d9',
      'gdi32',
      'strmiids',
    ])

  if env.Bit('mac'):
    AddToDict(kwargs, 'FRAMEWORKS', [
      'AudioToolbox',
      'AudioUnit',
      'Cocoa',
      'CoreAudio',
      'CoreFoundation',
      'IOKit',
      'QTKit',
      'QuickTime',
      'QuartzCore',
    ])
  return kwargs


def ReadVersion(filename):
  """Executes the supplied file and pulls out a version definition from it. """
  defs = {}
  execfile(str(filename), defs)
  if not defs.has_key('version'):
    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 GetEntry(dict, 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 dictionaruy the value is fetched and then is it removed
     from the dictionary.

  Args:
    key: The key to get the value for.
    kwargs: The keyword argument dictionary.
  Returns:
    The value or None if the key is missing.
  """
  value = None
  if dict.has_key(key):
    value = dict[key]
    dict.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

# Linux can build both 32 and 64 bit on 64 bit host, but 32 bit host can
# only build 32 bit.  For 32 bit debian installer a 32 bit host is required.
# ChromeOS (linux) ebuild don't support 64 bit and requires 32 bit build only
# for now.
def Allow64BitCompile(env):
  return (env.Bit('linux') and env.Bit('platform_arch_64bit')
          )

def MergeSettingsFromLibraryDependencies(env, params):
  if params.has_key('libs'):
    for lib in params['libs']:
      if (_all_lib_targets.has_key(lib) and
          _all_lib_targets[lib].has_key('dependent_target_settings')):
        params = CombineDicts(
            params,
            MergeAndFilterByPlatform(
                env,
                _all_lib_targets[lib]['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 = GetEntry(params, 'name')

  # save pristine params of lib targets for future reference
  if 'ComponentLibrary' == component:
    _all_lib_targets[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 GetEntry(params, 'signed')
  if signed:
    name = 'unsigned_' + name

  # add default values
  if GetEntry(params, 'include_talk_media_libs'):
    params = AddMediaLibs(env, **params)

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

  # apply any explicit dependencies
  dependencies = GetEntry(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 GetEntry(params, 'prepend_includedirs'):
    prepends['includedirs'] = 'CPPPATH'
  else:
    appends['includedirs'] = 'CPPPATH'

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

  # workaround for pulse stripping link flag for unknown reason
  if Allow64BitCompile(env):
    env['SHLINKCOM'] = ('$SHLINK -o $TARGET -m32 $SHLINKFLAGS $SOURCES '
                        '$_LIBDIRFLAGS $_LIBFLAGS')
    env['LINKCOM'] = ('$LINK -o $TARGET -m32 $LINKFLAGS $SOURCES '
                      '$_LIBDIRFLAGS $_LIBFLAGS')

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

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

  node = builder(name, srcs)

  # make a parallel 64bit version if requested
  if Allow64BitCompile(env) and GetEntry(params, 'also64bit'):
    env_64bit = env.Clone()
    env_64bit.FilterOut(CCFLAGS = ['-m32'], LINKFLAGS = ['-m32'])
    env_64bit.Prepend(CCFLAGS = ['-m64', '-fPIC'], LINKFLAGS = ['-m64'])
    name_64bit = name + '64'
    env_64bit.Replace(OBJSUFFIX = '64' + env_64bit['OBJSUFFIX'])
    env_64bit.Replace(SHOBJSUFFIX = '64' + env_64bit['SHOBJSUFFIX'])
    if ('ComponentProgram' == component or
        ('ComponentLibrary' == component and
         env_64bit['COMPONENT_STATIC'] == False)):
      # link 64 bit versions of libraries
      libs = []
      for lib in env_64bit['LIBS']:
        if (_all_lib_targets.has_key(lib) and
            _all_lib_targets[lib].has_key('also64bit')):
          libs.append(lib + '64')
        else:
          libs.append(lib)
      env_64bit.Replace(LIBS = libs)

    env_64bit['SHLINKCOM'] = ('$SHLINK -o $TARGET -m64 $SHLINKFLAGS $SOURCES '
                              '$_LIBDIRFLAGS $_LIBFLAGS')
    env_64bit['LINKCOM'] = ('$LINK -o $TARGET -m64 $LINKFLAGS $SOURCES '
                            '$_LIBDIRFLAGS $_LIBFLAGS')
    builder = getattr(env_64bit, component)
    nodes = [node, builder(name_64bit, srcs)]
    return nodes

  if signed:  # Note currently incompatible with 64Bit flag
    # 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 = GetEntry(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 not dictionary.has_key(key):
    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 by combining values of keys shared between them.
  """
  c = {}
  for key in a:
    if b.has_key(key):
      c[key] = a[key] + b.pop(key)
    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, GetEntry(d, old), append)
