"""
Compile the externals
"""

from __future__ import unicode_literals, absolute_import, division, print_function

import platform
import sys
import os
import re

__RCSID__ = "$Id$"

# We need to patch python platform module. It does a string comparison for the libc versions.
# it fails when going from 2.9 to 2.10,
# the fix converts the version to a tuple and attempts a numeric comparison

_libc_search = re.compile(b'(__libc_init)'
                          b'|'
                          b'(GLIBC_([0-9.]+))'
                          b'|'
                          b'(libc(_\\w+)?\\.so(?:\\.(\\d[0-9.]*))?)')


def libc_ver(executable=sys.executable, lib='', version='',
             chunksize=2048):
  """ Tries to determine the libc version that the file executable
      (which defaults to the Python interpreter) is linked against.

      Returns a tuple of strings (lib,version) which default to the
      given parameters in case the lookup fails.

      Note that the function has intimate knowledge of how different
      libc versions add symbols to the executable and thus is probably
      only useable for executables compiled using gcc.

      The file is read and scanned in chunks of chunksize bytes.

  """
  with open(executable, 'rb') as f:
    binary = f.read(chunksize)
    pos = 0
    version = [0, 0, 0]
    while True:
      m = _libc_search.search(binary, pos)
      if not m:
        binary = f.read(chunksize)
        if not binary:
          break
        pos = 0
        continue
      libcinit, glibc, glibcversion, so, threads, soversion = m.groups()
      if libcinit and not lib:
        lib = b'libc'
      elif glibc:
        glibcversion_parts = glibcversion.split(b'.')
        for i in range(len(glibcversion_parts)):
          try:
            glibcversion_parts[i] = int(glibcversion_parts[i])
          except ValueError:
            glibcversion_parts[i] = 0
        if libcinit and not lib:
          lib = b'libc'
        elif glibc:
          if lib != b'glibc':
            lib = b'glibc'
            version = glibcversion_parts
          elif glibcversion_parts > version:
            version = glibcversion_parts
      elif so:
        if lib != b'glibc':
          lib = b'libc'
          version = max(version, [int(soversion)]).pop()
          if threads and version[-len(threads):] != threads:
            version = version + threads
      pos = m.end()
  return lib.decode(), '.'.join(map(str, version))

# ## Command line interface


def getPlatformString():
  # Modified to return our desired platform string, R. Graciani
  platformTuple = (platform.system(), platform.machine())
  if platformTuple[0] == 'Linux':
    try:
      import subprocess
      sp = subprocess.Popen(['/sbin/ldconfig', '--print-cache'], stdout=subprocess.PIPE,
                            universal_newlines=True)
      spStdout = sp.stdout
    except Exception:
      sp = None
      spStdout = os.popen('/sbin/ldconfig --print-cache', 'r')
    ldre = re.compile(r".*=> (.*/libc\.so\..*$)")
    libs = []
    for line in spStdout.readlines():
      reM = ldre.match(line)
      if reM:
        libs.append(reM.groups()[0])
    if sp:
      if 'terminate' in dir(sp):
        sp.terminate()
        sp.wait()

    if not libs:
      # get version of higher libc installed
      if platform.machine().find('64') != -1:
        lib = '/lib64'
      else:
        lib = '/lib'
      for libFile in os.listdir(lib):
        if libFile.find('libc-') == 0 or libFile.find('libc.so') == 0:
          libs.append(os.path.join(lib, libFile))
    newest_lib = [0, 0, 0]
    for lib in libs:
      lib_parts = libc_ver(lib)[1].split('.')
      for i in range(len(lib_parts)):
        try:
          lib_parts[i] = int(lib_parts[i])
        except ValueError:
          lib_parts[i] = 0
          # print "non integer version numbers"
      if lib_parts > newest_lib:
        newest_lib = lib_parts

    platformTuple += ('glibc-' + '.'.join(map(str, newest_lib)),)
  elif platformTuple[0] == 'Darwin':
    platformTuple += ('.'.join(platform.mac_ver()[0].split(".")[:2]),)
  elif platformTuple[0] == 'Windows':
    platformTuple += (platform.win32_ver()[0],)
  else:
    platformTuple += (platform.release())

  platformString = "%s_%s_%s" % platformTuple

  return platformString


_gPlatform = None
_gPlatformTuple = None


def getPlatform():
  global _gPlatform, _gPlatformTuple

  if _gPlatform is None:
    _gPlatform = getPlatformString()
    _gPlatformTuple = tuple(_gPlatform.split('_'))

  return _gPlatform


def getPlatformTuple():
  getPlatform()
  return _gPlatformTuple
