import time

import buildbot_common
import build_version
import parse_dsc

from build_paths import OUT_DIR, SRC_DIR, SDK_SRC_DIR, SCRIPT_DIR

sys.path.append(os.path.join(SDK_SRC_DIR, 'tools'))
import getos
platform = getos.GetPlatform()

# TODO(binji): ugly hack -- can I get the browser in a cleaner way?
sys.path.append(os.path.join(SRC_DIR, 'chrome', 'test', 'nacl_test_injection'))
import find_chrome
browser_path = find_chrome.FindChrome(SRC_DIR, ['Debug', 'Release'])

pepper_ver = str(int(build_version.ChromeMajorVersion()))
pepperdir = os.path.join(OUT_DIR, 'pepper_' + pepper_ver)

browser_tester_py = os.path.join(SRC_DIR, 'ppapi', 'native_client', 'tools',
                                 'browser_tester', 'browser_tester.py')

ALL_CONFIGS = ['Debug', 'Release']
ALL_TOOLCHAINS = ['newlib', 'glibc', 'pnacl', 'win', 'linux', 'mac']

# Values you can filter by:
#   name: The name of the test. (e.g. "pi_generator")
#   config: See ALL_CONFIGS above.
#   toolchain: See ALL_TOOLCHAINS above.
#   platform: mac/win/linux.
def BuildAndTest(options):
  # Refuse to run under cygwin.
  if sys.platform == 'cygwin':
    raise Exception('I do not work under cygwin, sorry.')

  # By default, use the version of Python is being used to run this script.
  python = sys.executable
  if sys.platform == 'darwin':
    # Mac 10.5 bots tend to use a particularlly old version of Python, look for
    # a newer version.
    macpython27 = '/Library/Frameworks/Python.framework/Versions/2.7/bin/python'
    if os.path.exists(macpython27):
      python = macpython27

  script_dir = os.path.dirname(os.path.abspath(__file__))
  src_dir = os.path.dirname(os.path.dirname(os.path.dirname(script_dir)))
  nacl_dir = os.path.join(src_dir, 'native_client')

  # Decide platform specifics.
  if options.browser_path:
    chrome_filename = options.browser_path
  else:
    chrome_filename = find_chrome.FindChrome(src_dir, [options.mode])
    if chrome_filename is None:
      raise Exception('Cannot find a chome binary - specify one with '
                      '--browser_path?')

  env = dict(os.environ)
  if sys.platform in ['win32', 'cygwin']:
    if options.bits == 64:
      bits = 64
    elif options.bits == 32:
      bits = 32
    elif '64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or \
         '64' in os.environ.get('PROCESSOR_ARCHITEW6432', ''):
      bits = 64
    else:
      bits = 32
    msvs_path = ';'.join([
        r'c:\Program Files\Microsoft Visual Studio 9.0\VC',
        r'c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC',
        r'c:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools',
        r'c:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Tools',
        r'c:\Program Files\Microsoft Visual Studio 8\VC',
        r'c:\Program Files (x86)\Microsoft Visual Studio 8\VC',
        r'c:\Program Files\Microsoft Visual Studio 8\Common7\Tools',
        r'c:\Program Files (x86)\Microsoft Visual Studio 8\Common7\Tools',
    ])
    env['PATH'] += ';' + msvs_path
    scons = [python, 'scons.py']
  elif sys.platform == 'darwin':
    if options.bits == 64:
      bits = 64
    elif options.bits == 32:
      bits = 32
    else:
      p = subprocess.Popen(['file', chrome_filename], stdout=subprocess.PIPE)
      (p_stdout, _) = p.communicate()
      assert p.returncode == 0
      if p_stdout.find('executable x86_64') >= 0:
        bits = 64
      else:
        bits = 32
    scons = [python, 'scons.py']
  else:
    p = subprocess.Popen(
        'uname -m | '
        'sed -e "s/i.86/ia32/;s/x86_64/x64/;s/amd64/x64/;s/arm.*/arm/"',
        shell=True, stdout=subprocess.PIPE)
    (p_stdout, _) = p.communicate()
    assert p.returncode == 0
    if options.bits == 64:
      bits = 64
    elif options.bits == 32:
      bits = 32
    elif p_stdout.find('64') >= 0:
      bits = 64
    else:
      bits = 32
    # xvfb-run has a 2-second overhead per invocation, so it is cheaper to wrap
    # the entire build step rather than each test (browser_headless=1).
    # We also need to make sure that there are at least 24 bits per pixel.
    # https://code.google.com/p/chromium/issues/detail?id=316687
    scons = [
        'xvfb-run',
        '--auto-servernum',
        '--server-args', '-screen 0 1024x768x24',
        python, 'scons.py',
    ]

  if options.jobs > 1:
    scons.append('-j%d' % options.jobs)

  scons.append('disable_tests=%s' % options.disable_tests)

  if options.buildbot is not None:
    scons.append('buildbot=%s' % (options.buildbot,))

  # Clean the output of the previous build.
  # Incremental builds can get wedged in weird ways, so we're trading speed
  # for reliability.
  shutil.rmtree(os.path.join(nacl_dir, 'scons-out'), True)

  # check that the HOST (not target) is 64bit
  # this is emulating what msvs_env.bat is doing
  if '64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or \
     '64' in os.environ.get('PROCESSOR_ARCHITEW6432', ''):
    # 64bit HOST
    env['VS90COMNTOOLS'] = ('c:\\Program Files (x86)\\'
                            'Microsoft Visual Studio 9.0\\Common7\\Tools\\')
    env['VS80COMNTOOLS'] = ('c:\\Program Files (x86)\\'
                            'Microsoft Visual Studio 8.0\\Common7\\Tools\\')
  else:
    # 32bit HOST
    env['VS90COMNTOOLS'] = ('c:\\Program Files\\Microsoft Visual Studio 9.0\\'
                            'Common7\\Tools\\')
    env['VS80COMNTOOLS'] = ('c:\\Program Files\\Microsoft Visual Studio 8.0\\'
                            'Common7\\Tools\\')

  # Run nacl/chrome integration tests.
  # Note that we have to add nacl_irt_test to --mode in order to get
  # inbrowser_test_runner to run.
  # TODO(mseaborn): Change it so that inbrowser_test_runner is not a
  # special case.
  cmd = scons + ['--verbose', '-k', 'platform=x86-%d' % bits,
      '--mode=opt-host,nacl,nacl_irt_test',
      'chrome_browser_path=%s' % chrome_filename,
  ]
  if not options.integration_bot and not options.morenacl_bot:
    cmd.append('disable_flaky_tests=1')
  cmd.append('chrome_browser_tests')

  # Propagate path to JSON output if present.
  # Note that RunCommand calls sys.exit on errors, so potential errors
  # from one command won't be overwritten by another one. Overwriting
  # a successful results file with either success or failure is fine.
  if options.json_build_results_output_file:
    cmd.append('json_build_results_output_file=%s' %
               options.json_build_results_output_file)

  # Download the toolchain(s).
  RunCommand([python,
              os.path.join(nacl_dir, 'build', 'download_toolchains.py'),
              '--no-arm-trusted', '--no-pnacl', 'TOOL_REVISIONS'],
             nacl_dir, os.environ)

  CleanTempDir()

  if options.enable_newlib:
    RunTests('nacl-newlib', cmd, nacl_dir, env)

  if options.enable_glibc:
    RunTests('nacl-glibc', cmd + ['--nacl_glibc'], nacl_dir, env)